* [PATCH iproute2-next 0/7] cleanup help and exit codes
@ 2026-08-07 15:42 Stephen Hemminger
2026-08-07 15:42 ` [PATCH iproute2-next 1/7] ip: follow Linux convention for help vs usage Stephen Hemminger
` (6 more replies)
0 siblings, 7 replies; 8+ messages in thread
From: Stephen Hemminger @ 2026-08-07 15:42 UTC (permalink / raw)
To: netdev; +Cc: dsahern, Stephen Hemminger
This series cleans up how iproute2 commands handle help
and syntax errors. Before, ip help command and usage
errors both output to stderr and had non-zero exit code.
Now help outputs to stdout and exits with 0.
Since help and usage errors should not happen when
iproute2 commands are scripted this should have little impact
on users. There is no POSIX or other official standard for this;
the design choices here follow the precedent in coreutils, etc.
Initial conversion was done by hand, but after that the same pattern
was applied across all utilities with the aid of the "mechanical turk"
(ie. Claude Opus).
Before:
$ ip help 2>/dev/null; echo $? # text is on stderr
255
After:
$ ip help >/dev/null; echo $? # text is on stdout
0
Usage output is unchanged:
$ ip bogus 2>/dev/null; echo $?
1
Note: a help command inside a batch file still exits
immediately and following commands are not executed.
Example:
$ printf "help\nlink\n" | ./ip/ip -batch - ; echo $?
Usage: ip [ OPTIONS ] OBJECT { COMMAND | help }
ip [ -force ] -batch filename
...
0
Stephen Hemminger (7):
ip: follow Linux convention for help vs usage
ip/routel: follow help vs usage convention
misc: put help to stdout and usage to stderr
netshaper: put help to stdout and usage to stderr
bridge: put help to stdout and usage to stderr
genl: put help to stdout and usage to stderr
tc: put help to stdout and usage to stderr
bridge/bridge.c | 20 ++++++++++----------
bridge/fdb.c | 18 +++++++++---------
bridge/link.c | 16 +++++++++++-----
bridge/mdb.c | 14 +++++++-------
bridge/monitor.c | 11 ++++++-----
bridge/mst.c | 10 +++++-----
bridge/vlan.c | 10 +++++-----
bridge/vni.c | 10 +++++-----
genl/genl.c | 14 ++++++++------
ip/ip.c | 15 ++++++++-------
ip/ip6tunnel.c | 12 ++++++------
ip/ip_common.h | 4 ++--
ip/ipaddress.c | 18 +++++++++---------
ip/ipaddrlabel.c | 10 +++++-----
ip/ipfou.c | 12 ++++++------
ip/ipila.c | 12 ++++++------
ip/ipioam6.c | 13 ++++++++-----
ip/ipl2tp.c | 21 ++++++++++++---------
ip/iplink.c | 40 ++++++++++++++++++++-------------------
ip/iplink_amt.c | 15 +++++----------
ip/iplink_can.c | 11 +++--------
ip/iplink_dsa.c | 4 ++--
ip/iplink_hsr.c | 11 +++--------
ip/iplink_vxcan.c | 11 +++--------
ip/ipmacsec.c | 32 +++++++++++++++----------------
ip/ipmaddr.c | 14 +++++++-------
ip/ipmonitor.c | 10 +++++-----
ip/ipmptcp.c | 10 +++++-----
ip/ipmroute.c | 14 +++++++-------
ip/ipneigh.c | 18 +++++++++---------
ip/ipnetconf.c | 10 +++++-----
ip/ipnetns.c | 10 +++++-----
ip/ipnexthop.c | 26 ++++++++++++-------------
ip/ipntable.c | 10 +++++-----
ip/iproute.c | 20 ++++++++++----------
ip/iproute_lwtunnel.c | 33 +++++++++++++++++---------------
ip/iprule.c | 12 ++++++------
ip/ipseg6.c | 13 ++++++++-----
ip/iptoken.c | 13 +++++++------
ip/iptunnel.c | 12 ++++++------
ip/iptuntap.c | 12 ++++++------
ip/ipvrf.c | 10 +++++-----
ip/ipxfrm.c | 14 +++++++-------
ip/link_veth.c | 14 +++++---------
ip/routel | 11 ++++++-----
ip/rtmon.c | 10 +++++-----
ip/tcp_metrics.c | 12 ++++++------
ip/xfrm_monitor.c | 10 +++++-----
ip/xfrm_policy.c | 16 +++++++++-------
ip/xfrm_state.c | 26 +++++++++++++------------
misc/arpd.c | 12 +++++++-----
misc/ifstat.c | 44 +++++++++++++++++++++----------------------
misc/nstat.c | 11 ++++++-----
misc/rtacct.c | 13 ++++++-------
netshaper/netshaper.c | 31 +++++++++++++++---------------
tc/e_bpf.c | 15 ++++++++++-----
tc/f_basic.c | 12 +++++++-----
tc/f_bpf.c | 12 +++++++-----
tc/f_cgroup.c | 16 ++++++++++------
tc/f_flow.c | 12 +++++++-----
tc/f_flower.c | 13 +++++++++----
tc/f_fw.c | 12 +++++++-----
tc/f_matchall.c | 12 +++++++-----
tc/f_route.c | 12 +++++++-----
tc/f_u32.c | 12 +++++++-----
tc/m_action.c | 23 ++++++++++------------
tc/m_bpf.c | 10 ++++++----
tc/m_connmark.c | 16 +++++++++-------
tc/m_csum.c | 18 ++++++++++--------
tc/m_ct.c | 12 +++++++-----
tc/m_ctinfo.c | 16 +++++++++-------
tc/m_estimator.c | 12 +++++++-----
tc/m_gact.c | 27 +++++++++++++++-----------
tc/m_gate.c | 14 ++++++++------
tc/m_ife.c | 16 +++++++++-------
tc/m_mirred.c | 14 ++++++++------
tc/m_mpls.c | 16 +++++++++-------
tc/m_nat.c | 22 +++++++++++++---------
tc/m_pedit.c | 22 ++++++++++++----------
tc/m_police.c | 10 ++++++----
tc/m_sample.c | 24 ++++++++++++-----------
tc/m_simple.c | 16 +++++++++-------
tc/m_skbedit.c | 17 ++++++++++-------
tc/m_skbmod.c | 16 +++++++++-------
tc/m_tunnel_key.c | 20 +++++++++++---------
tc/m_vlan.c | 24 ++++++++++++-----------
tc/q_cake.c | 12 +++++++-----
tc/q_cbs.c | 12 +++++++-----
tc/q_choke.c | 12 +++++++-----
tc/q_clsact.c | 14 ++++++++++----
tc/q_codel.c | 12 +++++++-----
tc/q_drr.c | 24 +++++++++++++----------
tc/q_dualpi2.c | 38 ++++++++++++++++++++-----------------
tc/q_etf.c | 12 +++++++-----
tc/q_ets.c | 29 ++++++++++++++++------------
tc/q_fifo.c | 13 ++++++++-----
tc/q_fq.c | 12 +++++++-----
tc/q_fq_codel.c | 12 +++++++-----
tc/q_fq_pie.c | 12 +++++++-----
tc/q_gred.c | 19 ++++++++++---------
tc/q_hfsc.c | 28 +++++++++++++++------------
tc/q_hhf.c | 12 +++++++-----
tc/q_htb.c | 19 ++++++++++++-------
tc/q_ingress.c | 14 ++++++++++----
tc/q_mqprio.c | 10 ++++++----
tc/q_multiq.c | 12 +++++++-----
tc/q_netem.c | 21 +++++++++++++--------
tc/q_pie.c | 12 +++++++-----
tc/q_plug.c | 13 ++++++++-----
tc/q_prio.c | 15 +++++++++------
tc/q_qfq.c | 26 ++++++++++++++++---------
tc/q_red.c | 12 +++++++-----
tc/q_sfb.c | 14 ++++++++++----
tc/q_sfq.c | 12 +++++++-----
tc/q_skbprio.c | 13 ++++++++-----
tc/q_taprio.c | 10 ++++++----
tc/q_tbf.c | 14 ++++++++------
tc/tc.c | 12 ++++++------
tc/tc_class.c | 20 ++++++++++++--------
tc/tc_exec.c | 6 +++---
tc/tc_filter.c | 31 +++++++++++++++++-------------
tc/tc_monitor.c | 11 ++++++-----
tc/tc_qdisc.c | 14 +++++++-------
tc/tc_stab.c | 13 +++++++------
124 files changed, 1057 insertions(+), 868 deletions(-)
--
2.53.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH iproute2-next 1/7] ip: follow Linux convention for help vs usage
2026-08-07 15:42 [PATCH iproute2-next 0/7] cleanup help and exit codes Stephen Hemminger
@ 2026-08-07 15:42 ` Stephen Hemminger
2026-08-07 15:42 ` [PATCH iproute2-next 2/7] ip/routel: follow help vs usage convention Stephen Hemminger
` (5 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Stephen Hemminger @ 2026-08-07 15:42 UTC (permalink / raw)
To: netdev; +Cc: dsahern, Stephen Hemminger, Dmitri Seletski
The Linux convention is that help text goes to stdout
and exit code is 0 (success). And for case of incorrect arguments
the usage text goes to stderr, and exit code is 1 (failure).
Reported-by: Dmitri Seletski <drjoms@gmail.com>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
ip/ip.c | 15 ++++++++-------
ip/ip6tunnel.c | 12 ++++++------
ip/ip_common.h | 4 ++--
ip/ipaddress.c | 18 +++++++++---------
ip/ipaddrlabel.c | 10 +++++-----
ip/ipfou.c | 12 ++++++------
ip/ipila.c | 12 ++++++------
ip/ipioam6.c | 13 ++++++++-----
ip/ipl2tp.c | 21 ++++++++++++---------
ip/iplink.c | 40 +++++++++++++++++++++-------------------
ip/iplink_amt.c | 15 +++++----------
ip/iplink_can.c | 11 +++--------
ip/iplink_dsa.c | 4 ++--
ip/iplink_hsr.c | 11 +++--------
ip/iplink_vxcan.c | 11 +++--------
ip/ipmacsec.c | 32 ++++++++++++++++----------------
ip/ipmaddr.c | 14 +++++++-------
ip/ipmonitor.c | 10 +++++-----
ip/ipmptcp.c | 10 +++++-----
ip/ipmroute.c | 14 +++++++-------
ip/ipneigh.c | 18 +++++++++---------
ip/ipnetconf.c | 10 +++++-----
ip/ipnetns.c | 10 +++++-----
ip/ipnexthop.c | 26 +++++++++++++-------------
ip/ipntable.c | 10 +++++-----
ip/iproute.c | 20 ++++++++++----------
ip/iproute_lwtunnel.c | 33 ++++++++++++++++++---------------
ip/iprule.c | 12 ++++++------
ip/ipseg6.c | 13 ++++++++-----
ip/iptoken.c | 13 +++++++------
ip/iptunnel.c | 12 ++++++------
ip/iptuntap.c | 12 ++++++------
ip/ipvrf.c | 10 +++++-----
ip/ipxfrm.c | 14 +++++++-------
ip/link_veth.c | 14 +++++---------
ip/rtmon.c | 10 +++++-----
ip/tcp_metrics.c | 12 ++++++------
ip/xfrm_monitor.c | 10 +++++-----
ip/xfrm_policy.c | 16 +++++++++-------
ip/xfrm_state.c | 26 ++++++++++++++------------
40 files changed, 293 insertions(+), 297 deletions(-)
diff --git a/ip/ip.c b/ip/ip.c
index e4b71bde..feeb5f0a 100644
--- a/ip/ip.c
+++ b/ip/ip.c
@@ -52,11 +52,11 @@ const char *get_ip_lib_dir(void)
return lib_dir;
}
-static void usage(void) __attribute__((noreturn));
+static void usage(bool help) __attribute__((noreturn));
-static void usage(void)
+static void usage(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ip [ OPTIONS ] OBJECT { COMMAND | help }\n"
" ip [ -force ] -batch filename\n"
"where OBJECT := { address | addrlabel | fou | help | ila | ioam | l2tp | link |\n"
@@ -72,12 +72,13 @@ static void usage(void)
" -o[neline] | -t[imestamp] | -ts[hort] | -b[atch] [filename] |\n"
" -rc[vbuf] [size] | -n[etns] name | -N[umeric] | -a[ll] |\n"
" -c[olor]}\n");
- exit(-1);
+
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static int do_help(int argc, char **argv)
{
- usage();
+ usage(true);
return 0;
}
@@ -279,7 +280,7 @@ int main(int argc, char **argv)
rcvbuf = size;
} else if (matches_color(opt, &color)) {
} else if (matches(opt, "-help") == 0) {
- usage();
+ usage(true);
} else if (matches(opt, "-netns") == 0) {
NEXT_ARG();
if (netns_switch(argv[1]))
@@ -321,5 +322,5 @@ int main(int argc, char **argv)
return do_cmd(argv[1], argc-1, argv+1, true);
rtnl_close(&rth);
- usage();
+ usage(false);
}
diff --git a/ip/ip6tunnel.c b/ip/ip6tunnel.c
index 347bd46a..922a1873 100644
--- a/ip/ip6tunnel.c
+++ b/ip/ip6tunnel.c
@@ -29,11 +29,11 @@
#define DEFAULT_TNL_HOP_LIMIT (64)
-static void usage(void) __attribute__((noreturn));
+static void usage(bool help) __attribute__((noreturn));
-static void usage(void)
+static void usage(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ip -f inet6 tunnel { add | change | del | show } [ NAME ]\n"
" [ mode { ip6ip6 | ipip6 | ip6gre | vti6 | any } ]\n"
" [ remote ADDR local ADDR ] [ dev PHYS_DEV ]\n"
@@ -52,7 +52,7 @@ static void usage(void)
" KEY := { DOTTED_QUAD | NUMBER }\n",
IPV6_DEFAULT_TNL_ENCAP_LIMIT,
DEFAULT_TNL_HOP_LIMIT);
- exit(-1);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static void print_tunnel(const void *t)
@@ -267,7 +267,7 @@ static int parse_args(int argc, char **argv, int cmd, struct ip6_tnl_parm2 *p)
if (strcmp(*argv, "name") == 0) {
NEXT_ARG();
} else if (matches(*argv, "help") == 0)
- usage();
+ usage(true);
if (p->name[0])
duparg2("name", *argv);
if (get_ifname(p->name, *argv))
@@ -428,7 +428,7 @@ int do_ip6tunnel(int argc, char **argv)
matches(*argv, "list") == 0)
return do_show(argc - 1, argv + 1);
if (matches(*argv, "help") == 0)
- usage();
+ usage(true);
} else
return do_show(0, NULL);
diff --git a/ip/ip_common.h b/ip/ip_common.h
index 3f55ea33..db6de378 100644
--- a/ip/ip_common.h
+++ b/ip/ip_common.h
@@ -41,8 +41,8 @@ int print_addrlabel(struct nlmsghdr *n, void *arg);
int print_neigh(struct nlmsghdr *n, void *arg);
int ipaddr_list_link(int argc, char **argv);
void ipaddr_get_vf_rate(int, int *, int *, const char *);
-void iplink_usage(void) __attribute__((noreturn));
-void iplink_types_usage(void);
+void iplink_usage(bool help) __attribute__((noreturn));
+void iplink_types_usage(FILE *f);
void iproute_reset_filter(int ifindex);
void ipmroute_reset_filter(int ifindex);
diff --git a/ip/ipaddress.c b/ip/ipaddress.c
index 3653fd4e..0293801a 100644
--- a/ip/ipaddress.c
+++ b/ip/ipaddress.c
@@ -42,14 +42,14 @@ enum {
static struct link_filter filter;
static int do_link;
-static void usage(void) __attribute__((noreturn));
+static void usage(bool help) __attribute__((noreturn));
-static void usage(void)
+static void usage(bool help)
{
if (do_link)
- iplink_usage();
+ iplink_usage(help);
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ip address {add|change|replace} IFADDR dev IFNAME [ LIFETIME ]\n"
" [ CONFFLAG-LIST ]\n"
" ip address del IFADDR dev IFNAME [mngtmpaddr]\n"
@@ -76,9 +76,9 @@ static void usage(void)
"LFT := forever | SECONDS\n"
"ADDRPROTO := [ NAME | NUMBER ]\n"
);
- iplink_types_usage();
+ iplink_types_usage(help ? stdout : stderr);
- exit(-1);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static void print_link_flags(FILE *fp, unsigned int flags, unsigned int mdown)
@@ -2260,7 +2260,7 @@ static int ipaddr_list_flush_or_save(int argc, char **argv, int action)
if (strcmp(*argv, "dev") == 0)
NEXT_ARG();
else if (matches(*argv, "help") == 0)
- usage();
+ usage(true);
if (filter_dev)
duparg2("dev", *argv);
filter_dev = *argv;
@@ -2593,7 +2593,7 @@ static int ipaddr_modify(int cmd, int flags, int argc, char **argv)
if (strcmp(*argv, "local") == 0)
NEXT_ARG();
if (matches(*argv, "help") == 0)
- usage();
+ usage(true);
if (local_len)
duparg2("local", *argv);
lcl_arg = *argv;
@@ -2716,7 +2716,7 @@ int do_ipaddr(int argc, char **argv)
if (matches(*argv, "restore") == 0)
return ipaddr_restore();
if (matches(*argv, "help") == 0)
- usage();
+ usage(true);
fprintf(stderr, "Command \"%s\" is unknown, try \"ip address help\".\n", *argv);
exit(-1);
}
diff --git a/ip/ipaddrlabel.c b/ip/ipaddrlabel.c
index 0f49bbee..1d3864e0 100644
--- a/ip/ipaddrlabel.c
+++ b/ip/ipaddrlabel.c
@@ -31,14 +31,14 @@
extern struct rtnl_handle rth;
-static void usage(void) __attribute__((noreturn));
+static void usage(bool help) __attribute__((noreturn));
-static void usage(void)
+static void usage(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ip addrlabel { add | del } prefix PREFIX [ dev DEV ] [ label LABEL ]\n"
" ip addrlabel [ list | flush | help ]\n");
- exit(-1);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
int print_addrlabel(struct nlmsghdr *n, void *arg)
@@ -256,7 +256,7 @@ int do_ipaddrlabel(int argc, char **argv)
} else if (matches(argv[0], "flush") == 0) {
return ipaddrlabel_flush(argc-1, argv+1);
} else if (matches(argv[0], "help") == 0)
- usage();
+ usage(true);
fprintf(stderr, "Command \"%s\" is unknown, try \"ip addrlabel help\".\n", *argv);
exit(-1);
diff --git a/ip/ipfou.c b/ip/ipfou.c
index 8c1e061a..e25da65c 100644
--- a/ip/ipfou.c
+++ b/ip/ipfou.c
@@ -20,9 +20,9 @@
#include "ip_common.h"
#include "json_print.h"
-static void usage(void)
+static void usage(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ip fou add port PORT { ipproto PROTO | gue }\n"
" [ local IFADDR ] [ peer IFADDR ]\n"
" [ peer_port PORT ] [ dev IFNAME ]\n"
@@ -35,7 +35,7 @@ static void usage(void)
" PORT { 1..65535 }\n"
" IFADDR { addr }\n");
- exit(-1);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
/* netlink socket */
@@ -118,7 +118,7 @@ static int fou_parse_opt(int argc, char **argv, struct nlmsghdr *n,
} else {
fprintf(stderr
, "fou: unknown command \"%s\"?\n", *argv);
- usage();
+ usage(false);
return -1;
}
argc--, argv++;
@@ -329,10 +329,10 @@ static int do_show(int argc, char **argv)
int do_ipfou(int argc, char **argv)
{
if (argc < 1)
- usage();
+ usage(false);
if (matches(*argv, "help") == 0)
- usage();
+ usage(true);
if (genl_init_handle(&genl_rth, FOU_GENL_NAME, &genl_family))
exit(1);
diff --git a/ip/ipila.c b/ip/ipila.c
index 2590de9a..238fafac 100644
--- a/ip/ipila.c
+++ b/ip/ipila.c
@@ -21,9 +21,9 @@
#include "ila_common.h"
#include "json_print.h"
-static void usage(void)
+static void usage(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ip ila add loc_match LOCATOR_MATCH loc LOCATOR [ dev DEV ] OPTIONS\n"
" ip ila del loc_match LOCATOR_MATCH [ loc LOCATOR ] [ dev DEV ]\n"
" ip ila list\n"
@@ -31,7 +31,7 @@ static void usage(void)
" neutral-map-auto | no-action } ]\n"
" [ ident-type { luid | use-format } ]\n");
- exit(-1);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
/* netlink socket */
@@ -226,7 +226,7 @@ static int ila_parse_opt(int argc, char **argv, struct nlmsghdr *n,
}
ifindex_set = true;
} else {
- usage();
+ usage(false);
return -1;
}
argc--, argv++;
@@ -288,10 +288,10 @@ static int do_del(int argc, char **argv)
int do_ipila(int argc, char **argv)
{
if (argc < 1)
- usage();
+ usage(false);
if (matches(*argv, "help") == 0)
- usage();
+ usage(true);
if (genl_init_handle(&genl_rth, ILA_GENL_NAME, &genl_family))
exit(1);
diff --git a/ip/ipioam6.c b/ip/ipioam6.c
index 118fcd1c..7e5c020f 100644
--- a/ip/ipioam6.c
+++ b/ip/ipioam6.c
@@ -21,9 +21,9 @@
#include "libgenl.h"
#include "json_print.h"
-static void usage(void)
+static void usage(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ip ioam { COMMAND | help }\n"
" ip ioam namespace show\n"
" ip ioam namespace add ID [ data DATA32 ] [ wide DATA64 ]\n"
@@ -33,7 +33,7 @@ static void usage(void)
" ip ioam schema del ID\n"
" ip ioam namespace set ID schema { ID | none }\n"
" ip ioam monitor\n");
- exit(-1);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static struct rtnl_handle grth = { .fd = -1 };
@@ -270,8 +270,11 @@ int do_ioam6(int argc, char **argv)
{
bool maybe_wide = false;
- if (argc < 1 || strcmp(*argv, "help") == 0)
- usage();
+ if (argc < 1)
+ usage(false);
+
+ if (strcmp(*argv, "help") == 0)
+ usage(true);
memset(&opts, 0, sizeof(opts));
diff --git a/ip/ipl2tp.c b/ip/ipl2tp.c
index 97f7ff08..e7c092be 100644
--- a/ip/ipl2tp.c
+++ b/ip/ipl2tp.c
@@ -509,11 +509,11 @@ static int get_tunnel(struct l2tp_data *p)
* Command parser
*****************************************************************************/
-static void usage(void) __attribute__((noreturn));
+static void usage(bool help) __attribute__((noreturn));
-static void usage(void)
+static void usage(bool help)
{
- fprintf(stderr, "Usage: ip l2tp add tunnel\n"
+ fprintf(help ? stdout : stderr, "Usage: ip l2tp add tunnel\n"
" remote ADDR local ADDR\n"
" tunnel_id ID peer_tunnel_id ID\n"
" [ encap { ip | udp } ]\n"
@@ -539,7 +539,7 @@ static void usage(void)
" HEXSTR := { 8 or 16 hex digits (4 / 8 bytes) }\n"
" L2SPEC := { none | default }\n");
- exit(-1);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static int parse_args(int argc, char **argv, int cmd, struct l2tp_parm *p)
@@ -547,7 +547,7 @@ static int parse_args(int argc, char **argv, int cmd, struct l2tp_parm *p)
memset(p, 0, sizeof(*p));
if (argc == 0)
- usage();
+ usage(false);
/* Defaults */
p->l2spec_type = L2TP_L2SPECTYPE_DEFAULT;
@@ -715,10 +715,10 @@ static int parse_args(int argc, char **argv, int cmd, struct l2tp_parm *p)
} else if (strcmp(*argv, "session") == 0) {
p->session = 1;
} else if (matches(*argv, "help") == 0) {
- usage();
+ usage(true);
} else {
fprintf(stderr, "Unknown command: %s\n", *argv);
- usage();
+ usage(false);
}
argc--; argv++;
@@ -823,8 +823,11 @@ static int do_show(int argc, char **argv)
int do_ipl2tp(int argc, char **argv)
{
- if (argc < 1 || !matches(*argv, "help"))
- usage();
+ if (argc < 1)
+ usage(false);
+
+ if (matches(*argv, "help") == 0)
+ usage(true);
if (genl_init_handle(&genl_rth, L2TP_GENL_NAME, &genl_family))
exit(1);
diff --git a/ip/iplink.c b/ip/iplink.c
index c6aee8b6..a765002e 100644
--- a/ip/iplink.c
+++ b/ip/iplink.c
@@ -31,12 +31,12 @@
#endif
-static void usage(void) __attribute__((noreturn));
+static void usage(bool help) __attribute__((noreturn));
-void iplink_types_usage(void)
+void iplink_types_usage(FILE *f)
{
/* Remember to add new entry here if new type is added. */
- fprintf(stderr,
+ fprintf(f,
"TYPE := { amt | bareudp | bond | bond_slave | bridge | bridge_slave |\n"
" dsa | dummy | erspan | geneve | gre | gretap | gtp | hsr |\n"
" ifb | ip6erspan | ip6gre | ip6gretap | ip6tnl |\n"
@@ -47,9 +47,11 @@ void iplink_types_usage(void)
" xfrm | virt_wifi }\n");
}
-void iplink_usage(void)
+void iplink_usage(bool help)
{
- fprintf(stderr,
+ FILE *fp = help ? stdout : stderr;
+
+ fprintf(fp,
"Usage: ip link add [link DEV | parentdev NAME] [ name ] NAME\n"
" [ txqueuelen PACKETS ]\n"
" [ address LLADDR ]\n"
@@ -66,7 +68,7 @@ void iplink_usage(void)
" [ { up | down } ]\n"
" [ type TYPE ARGS ]\n");
- fprintf(stderr,
+ fprintf(fp,
" [ arp { on | off } ]\n"
" [ dynamic { on | off } ]\n"
" [ multicast { on | off } ]\n"
@@ -134,18 +136,18 @@ void iplink_usage(void)
" ip link property add dev DEVICE [ altname NAME .. ]\n"
" ip link property del dev DEVICE [ altname NAME .. ]\n");
- fprintf(stderr,
+ fprintf(fp,
"\n"
" ip link help [ TYPE ]\n"
"\n");
- iplink_types_usage();
+ iplink_types_usage(fp);
- exit(-1);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
-static void usage(void)
+static void usage(bool help)
{
- iplink_usage();
+ iplink_usage(help);
}
static int on_off(const char *msg, const char *realval)
@@ -1253,7 +1255,7 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req, char **type)
*argv, strlen(*argv) + 1);
} else {
if (matches(*argv, "help") == 0)
- usage();
+ usage(true);
if (strcmp(*argv, "dev") == 0)
NEXT_ARG();
@@ -1465,7 +1467,7 @@ static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv)
addattr_nest_end(&req.n, data);
} else if (argc) {
if (matches(*argv, "help") == 0)
- usage();
+ usage(true);
fprintf(stderr,
"Garbage instead of arguments \"%s ...\". Try \"ip link help\".\n",
*argv);
@@ -1681,7 +1683,7 @@ static int iplink_afstats(int argc, char **argv)
duparg2("dev", *argv);
filter_dev = *argv;
} else if (matches(*argv, "help") == 0) {
- usage();
+ usage(true);
} else {
fprintf(stderr,
"Command \"%s\" is unknown, try \"ip link help\".\n",
@@ -1739,7 +1741,7 @@ static int iplink_prop_mod(int argc, char **argv, struct iplink_req *req)
addattr_l(&req->n, sizeof(*req), IFLA_ALT_IFNAME,
name, strlen(name) + 1);
} else if (matches(*argv, "help") == 0) {
- usage();
+ usage(true);
} else {
if (strcmp(*argv, "dev") == 0)
NEXT_ARG();
@@ -1777,7 +1779,7 @@ static int iplink_prop(int argc, char **argv)
};
if (argc <= 0) {
- usage();
+ usage(false);
exit(-1);
}
@@ -1787,7 +1789,7 @@ static int iplink_prop(int argc, char **argv)
} else if (matches(*argv, "del") == 0) {
req.n.nlmsg_type = RTM_DELLINKPROP;
} else if (matches(*argv, "help") == 0) {
- usage();
+ usage(true);
} else {
fprintf(stderr, "Operator required\n");
exit(-1);
@@ -1800,7 +1802,7 @@ static void do_help(int argc, char **argv)
struct link_util *lu = NULL;
if (argc <= 0) {
- usage();
+ usage(true);
return;
}
@@ -1808,7 +1810,7 @@ static void do_help(int argc, char **argv)
if (lu && lu->print_help)
lu->print_help(lu, argc-1, argv+1, stdout);
else
- usage();
+ usage(true);
}
int do_iplink(int argc, char **argv)
diff --git a/ip/iplink_amt.c b/ip/iplink_amt.c
index 3a35bd9d..bb2966f2 100644
--- a/ip/iplink_amt.c
+++ b/ip/iplink_amt.c
@@ -37,12 +37,7 @@ static void print_usage(FILE *f)
);
}
-static char *modename[] = {"gateway", "relay"};
-
-static void usage(void)
-{
- print_usage(stderr);
-}
+static const char *modename[] = {"gateway", "relay"};
static void check_duparg(__u64 *attrs, int type, const char *key,
const char *argv)
@@ -75,7 +70,7 @@ static int amt_parse_opt(struct link_util *lu, int argc, char **argv,
} else if (strcmp(*argv, "relay") == 0) {
mode = 1;
} else {
- usage();
+ print_usage(stderr);
return -1;
}
addattr32(n, 1024, IFLA_AMT_MODE, mode);
@@ -119,11 +114,11 @@ static int amt_parse_opt(struct link_util *lu, int argc, char **argv,
addattr_l(n, 1024, IFLA_AMT_DISCOVERY_IP,
daddr.data, daddr.bytelen);
} else if (strcmp(*argv, "help") == 0) {
- usage();
- return -1;
+ print_usage(stdout);
+ exit(EXIT_SUCCESS);
} else {
fprintf(stderr, "amt: unknown command \"%s\"?\n", *argv);
- usage();
+ print_usage(stderr);
return -1;
}
argc--, argv++;
diff --git a/ip/iplink_can.c b/ip/iplink_can.c
index f631aab8..7b5e9a18 100644
--- a/ip/iplink_can.c
+++ b/ip/iplink_can.c
@@ -81,11 +81,6 @@ static void print_usage(FILE *f)
);
}
-static void usage(void)
-{
- print_usage(stderr);
-}
-
static void set_ctrlmode(char *name, char *arg,
struct can_ctrlmode *cm, __u32 flags)
{
@@ -374,11 +369,11 @@ static int can_parse_opt(struct link_util *lu, int argc, char **argv,
*argv);
addattr16(n, 1024, IFLA_CAN_TERMINATION, val);
} else if (matches(*argv, "help") == 0) {
- usage();
- return -1;
+ print_usage(stdout);
+ exit(EXIT_SUCCESS);
} else {
fprintf(stderr, "can: unknown option \"%s\"\n", *argv);
- usage();
+ print_usage(stderr);
return -1;
}
argc--, argv++;
diff --git a/ip/iplink_dsa.c b/ip/iplink_dsa.c
index e3f3f8ac..080d6dfe 100644
--- a/ip/iplink_dsa.c
+++ b/ip/iplink_dsa.c
@@ -25,8 +25,8 @@ static int dsa_parse_opt(struct link_util *lu, int argc, char **argv,
invarg("Device does not exist\n", *argv);
addattr_l(n, 1024, IFLA_DSA_MASTER, &ifindex, 4);
} else if (strcmp(*argv, "help") == 0) {
- print_usage(stderr);
- return -1;
+ print_usage(stdout);
+ exit(EXIT_SUCCESS);
} else {
fprintf(stderr, "dsa: unknown command \"%s\"?\n", *argv);
print_usage(stderr);
diff --git a/ip/iplink_hsr.c b/ip/iplink_hsr.c
index d79a4a40..f74a78ff 100644
--- a/ip/iplink_hsr.c
+++ b/ip/iplink_hsr.c
@@ -39,11 +39,6 @@ static void print_usage(FILE *f)
" 0 - HSR, 1 - PRP. (default = 0 - HSR)\n");
}
-static void usage(void)
-{
- print_usage(stderr);
-}
-
static int hsr_parse_opt(struct link_util *lu, int argc, char **argv,
struct nlmsghdr *n)
{
@@ -92,11 +87,11 @@ static int hsr_parse_opt(struct link_util *lu, int argc, char **argv,
invarg("No such interface", *argv);
addattr_l(n, 1024, IFLA_HSR_INTERLINK, &ifindex, 4);
} else if (matches(*argv, "help") == 0) {
- usage();
- return -1;
+ print_usage(stdout);
+ exit(EXIT_SUCCESS);
} else {
fprintf(stderr, "hsr: what is \"%s\"?\n", *argv);
- usage();
+ print_usage(stderr);
return -1;
}
argc--, argv++;
diff --git a/ip/iplink_vxcan.c b/ip/iplink_vxcan.c
index e0f9bacb..b1d5077f 100644
--- a/ip/iplink_vxcan.c
+++ b/ip/iplink_vxcan.c
@@ -17,13 +17,8 @@
static void print_usage(FILE *f)
{
- printf("Usage: ip link <options> type vxcan [peer <options>]\n"
- "To get <options> type 'ip link add help'\n");
-}
-
-static void usage(void)
-{
- print_usage(stderr);
+ fprintf(f, "Usage: ip link <options> type vxcan [peer <options>]\n"
+ "To get <options> type 'ip link add help'\n");
}
static int vxcan_parse_opt(struct link_util *lu, int argc, char **argv,
@@ -36,7 +31,7 @@ static int vxcan_parse_opt(struct link_util *lu, int argc, char **argv,
unsigned int ifi_flags, ifi_change, ifi_index;
if (strcmp(argv[0], "peer") != 0) {
- usage();
+ print_usage(stderr);
return -1;
}
diff --git a/ip/ipmacsec.c b/ip/ipmacsec.c
index 1864ffd3..92b81bf2 100644
--- a/ip/ipmacsec.c
+++ b/ip/ipmacsec.c
@@ -87,9 +87,9 @@ static int genl_family = -1;
_cmd, _flags)
-static void ipmacsec_usage(void)
+static void ipmacsec_usage(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ip macsec add DEV tx sa { 0..3 } [ OPTS ] key ID KEY\n"
" ip macsec set DEV tx sa { 0..3 } [ OPTS ]\n"
" ip macsec del DEV tx sa { 0..3 }\n"
@@ -108,7 +108,7 @@ static void ipmacsec_usage(void)
" SCI := { sci <u64> | port { 1..2^16-1 } address <lladdr> }\n"
" SALT := 96-bit hex string\n");
- exit(-1);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static bool ciphersuite_is_xpn(__u64 cid)
@@ -249,7 +249,7 @@ static int parse_sa_args(int *argcp, char ***argvp, struct sa_desc *sa)
} else {
fprintf(stderr, "macsec: unknown command \"%s\"?\n",
*argv);
- ipmacsec_usage();
+ ipmacsec_usage(false);
}
argv++; argc--;
@@ -340,7 +340,7 @@ static bool parse_rxsci(int *argcp, char ***argvp, struct rxsc_desc *rxsc,
if (*argcp == 0 ||
get_sci_portaddr(&sci, argcp, argvp, false, false) < 0) {
fprintf(stderr, "expected sci\n");
- ipmacsec_usage();
+ ipmacsec_usage(false);
}
rxsc->sci = sci.sci;
@@ -368,7 +368,7 @@ static int parse_rxsci_args(int *argcp, char ***argvp, struct rxsc_desc *rxsc)
} else {
fprintf(stderr, "macsec: unknown command \"%s\"?\n",
*argv);
- ipmacsec_usage();
+ ipmacsec_usage(false);
}
argv++; argc--;
@@ -504,7 +504,7 @@ static int do_modify_txsa(enum cmd c, int argc, char **argv, int ifindex)
txsa.active = 0xff;
if (argc == 0 || !get_sa(&argc, &argv, &txsa.an))
- ipmacsec_usage();
+ ipmacsec_usage(false);
if (c == CMD_DEL)
goto modify;
@@ -553,7 +553,7 @@ static int do_modify(enum cmd c, int argc, char **argv)
int ifindex;
if (argc == 0)
- ipmacsec_usage();
+ ipmacsec_usage(false);
ifindex = ll_name_to_index(*argv);
if (!ifindex) {
@@ -563,14 +563,14 @@ static int do_modify(enum cmd c, int argc, char **argv)
argc--; argv++;
if (argc == 0)
- ipmacsec_usage();
+ ipmacsec_usage(false);
if (strcmp(*argv, "tx") == 0)
return do_modify_txsa(c, argc-1, argv+1, ifindex);
if (strcmp(*argv, "rx") == 0)
return do_modify_rxsci(c, argc-1, argv+1, ifindex);
- ipmacsec_usage();
+ ipmacsec_usage(false);
return -1;
}
@@ -581,7 +581,7 @@ static int do_offload(enum cmd c, int argc, char **argv)
int ifindex, ret;
if (argc == 0)
- ipmacsec_usage();
+ ipmacsec_usage(false);
ifindex = ll_name_to_index(*argv);
if (!ifindex) {
@@ -591,11 +591,11 @@ static int do_offload(enum cmd c, int argc, char **argv)
argc--; argv++;
if (argc == 0)
- ipmacsec_usage();
+ ipmacsec_usage(false);
offload = parse_one_of("offload", *argv, offload_str, ARRAY_SIZE(offload_str), &ret);
if (ret)
- ipmacsec_usage();
+ ipmacsec_usage(false);
MACSEC_GENL_REQ(req, MACSEC_BUFLEN, macsec_commands[c][0][1], NLM_F_REQUEST);
@@ -1181,17 +1181,17 @@ static int do_show(int argc, char **argv)
if (argc == 0)
return do_dump(ifindex);
- ipmacsec_usage();
+ ipmacsec_usage(false);
return -1;
}
int do_ipmacsec(int argc, char **argv)
{
if (argc < 1)
- ipmacsec_usage();
+ ipmacsec_usage(false);
if (matches(*argv, "help") == 0)
- ipmacsec_usage();
+ ipmacsec_usage(true);
if (genl_init_handle(&genl_rth, MACSEC_GENL_NAME, &genl_family))
exit(1);
diff --git a/ip/ipmaddr.c b/ip/ipmaddr.c
index 95b703d2..5b16ab84 100644
--- a/ip/ipmaddr.c
+++ b/ip/ipmaddr.c
@@ -31,14 +31,14 @@ static struct {
int family;
} filter;
-static void usage(void) __attribute__((noreturn));
+static void usage(bool help) __attribute__((noreturn));
-static void usage(void)
+static void usage(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ip maddr [ add | del ] MULTIADDR dev STRING\n"
" ip maddr show [ dev STRING ]\n");
- exit(-1);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static int parse_hex(char *str, unsigned char *addr, size_t size)
@@ -371,7 +371,7 @@ static int multiaddr_list(int argc, char **argv)
if (strcmp(*argv, "dev") == 0) {
NEXT_ARG();
} else if (matches(*argv, "help") == 0)
- usage();
+ usage(true);
if (filter.dev)
duparg2("dev", *argv);
filter.dev = *argv;
@@ -426,7 +426,7 @@ static int multiaddr_modify(int cmd, int argc, char **argv)
NEXT_ARG();
}
if (matches(*argv, "help") == 0)
- usage();
+ usage(true);
if (ifr.ifr_hwaddr.sa_data[0])
duparg("address", *argv);
len = ll_addr_a2n(ifr.ifr_hwaddr.sa_data,
@@ -484,7 +484,7 @@ int do_multiaddr(int argc, char **argv)
|| matches(*argv, "lst") == 0)
return multiaddr_list(argc-1, argv+1);
if (matches(*argv, "help") == 0)
- usage();
+ usage(true);
fprintf(stderr, "Command \"%s\" is unknown, try \"ip maddr help\".\n", *argv);
exit(-1);
}
diff --git a/ip/ipmonitor.c b/ip/ipmonitor.c
index 1f4e860f..43e3f672 100644
--- a/ip/ipmonitor.c
+++ b/ip/ipmonitor.c
@@ -20,21 +20,21 @@
#include "ip_common.h"
#include "nh_common.h"
-static void usage(void) __attribute__((noreturn));
+static void usage(bool help) __attribute__((noreturn));
static int prefix_banner;
int listen_all_nsid;
struct rtnl_ctrl_data *ctrl_data;
int do_monitor;
-static void usage(void)
+static void usage(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ip monitor [ all | OBJECTS ] [ FILE ] [ label ] [ all-nsid ]\n"
" [ dev DEVICE ]\n"
"OBJECTS := address | link | mroute | maddress | acaddress | neigh |\n"
" netconf | nexthop | nsid | prefix | route | rule | stats\n"
"FILE := file FILENAME\n");
- exit(-1);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
void print_headers(FILE *fp, const char *label)
@@ -239,7 +239,7 @@ int do_ipmonitor(int argc, char **argv)
} else if (matches(*argv, "all-nsid") == 0) {
listen_all_nsid = 1;
} else if (matches(*argv, "help") == 0) {
- usage();
+ usage(true);
} else if (strcmp(*argv, "dev") == 0) {
NEXT_ARG();
diff --git a/ip/ipmptcp.c b/ip/ipmptcp.c
index 02cf72ce..37913ef6 100644
--- a/ip/ipmptcp.c
+++ b/ip/ipmptcp.c
@@ -20,9 +20,9 @@
#include "libnetlink.h"
#include "ll_map.h"
-static void usage(void)
+static void usage(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ip mptcp endpoint add ADDRESS [ dev NAME ] [ id ID ]\n"
" [ port NR ] [ FLAG-LIST ]\n"
" ip mptcp endpoint delete id ID [ ADDRESS ]\n"
@@ -36,7 +36,7 @@ static void usage(void)
"FLAG := [ signal | subflow | laminar | backup | fullmesh ]\n"
"CHANGE-OPT := [ backup | nobackup | fullmesh | nofullmesh ]\n");
- exit(-1);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
/* netlink socket */
@@ -621,10 +621,10 @@ static int mptcp_monitor(void)
int do_mptcp(int argc, char **argv)
{
if (argc == 0)
- usage();
+ usage(false);
if (matches(*argv, "help") == 0)
- usage();
+ usage(true);
if (genl_init_handle(&genl_rth, MPTCP_PM_NAME, &genl_family))
exit(1);
diff --git a/ip/ipmroute.c b/ip/ipmroute.c
index 164632e6..28019617 100644
--- a/ip/ipmroute.c
+++ b/ip/ipmroute.c
@@ -26,16 +26,16 @@
#include "ip_common.h"
#include "json_print.h"
-static void usage(void) __attribute__((noreturn));
+static void usage(bool help) __attribute__((noreturn));
-static void usage(void)
+static void usage(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ip mroute show [ [ to ] PREFIX ] [ from PREFIX ] [ iif DEVICE ]\n"
" [ table TABLE_ID ]\n"
"TABLE_ID := [ local | main | default | all | NUMBER ]\n"
);
- exit(-1);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static struct rtfilter {
@@ -259,7 +259,7 @@ static int mroute_list(int argc, char **argv)
if (strcmp(*argv, "all") == 0) {
filter.tb = 0;
} else if (strcmp(*argv, "help") == 0) {
- usage();
+ usage(true);
} else {
invarg("table id value is invalid\n", *argv);
}
@@ -277,7 +277,7 @@ static int mroute_list(int argc, char **argv)
NEXT_ARG();
}
if (matches(*argv, "help") == 0)
- usage();
+ usage(true);
if (get_prefix(&filter.mdst, *argv, preferred_family))
invarg("to value is invalid\n", *argv);
}
@@ -320,7 +320,7 @@ int do_multiroute(int argc, char **argv)
|| matches(*argv, "lst") == 0)
return mroute_list(argc-1, argv+1);
if (matches(*argv, "help") == 0)
- usage();
+ usage(true);
fprintf(stderr, "Command \"%s\" is unknown, try \"ip mroute help\".\n", *argv);
exit(-1);
}
diff --git a/ip/ipneigh.c b/ip/ipneigh.c
index be537187..475268fd 100644
--- a/ip/ipneigh.c
+++ b/ip/ipneigh.c
@@ -39,11 +39,11 @@ static struct
__u8 ndm_flags;
} filter;
-static void usage(void) __attribute__((noreturn));
+static void usage(bool help) __attribute__((noreturn));
-static void usage(void)
+static void usage(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ip neigh { add | del | change | replace }\n"
" { ADDR [ lladdr LLADDR ] [ nud STATE ] proxy ADDR }\n"
" [ dev DEV ] [ router ] [ use ] [ managed ] [ extern_learn ]\n"
@@ -55,7 +55,7 @@ static void usage(void)
"\n"
"STATE := { delay | failed | incomplete | noarp | none |\n"
" permanent | probe | reachable | stale }\n");
- exit(-1);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static int nud_state_a2n(unsigned int *state, const char *arg)
@@ -136,7 +136,7 @@ static int ipneigh_modify(int cmd, int flags, int argc, char **argv)
} else if (matches(*argv, "proxy") == 0) {
NEXT_ARG();
if (matches(*argv, "help") == 0)
- usage();
+ usage(true);
if (dst_ok)
duparg("address", *argv);
get_addr(&dst, *argv, preferred_family);
@@ -585,7 +585,7 @@ static int do_show_or_flush(int argc, char **argv, int flush)
NEXT_ARG();
}
if (matches(*argv, "help") == 0)
- usage();
+ usage(true);
if (get_prefix(&filter.pfx, *argv, filter.family))
invarg("to value is invalid\n", *argv);
if (filter.family == AF_UNSPEC)
@@ -686,7 +686,7 @@ static int ipneigh_get(int argc, char **argv)
} else if (matches(*argv, "proxy") == 0) {
NEXT_ARG();
if (matches(*argv, "help") == 0)
- usage();
+ usage(true);
if (dst_ok)
duparg("address", *argv);
get_addr(&dst, *argv, preferred_family);
@@ -698,7 +698,7 @@ static int ipneigh_get(int argc, char **argv)
NEXT_ARG();
if (matches(*argv, "help") == 0)
- usage();
+ usage(true);
if (dst_ok)
duparg2("to", *argv);
get_addr(&dst, *argv, preferred_family);
@@ -762,7 +762,7 @@ int do_ipneigh(int argc, char **argv)
if (matches(*argv, "flush") == 0)
return do_show_or_flush(argc-1, argv+1, 1);
if (matches(*argv, "help") == 0)
- usage();
+ usage(true);
} else
return do_show_or_flush(0, NULL, 0);
diff --git a/ip/ipnetconf.c b/ip/ipnetconf.c
index 57bb99d1..269e9596 100644
--- a/ip/ipnetconf.c
+++ b/ip/ipnetconf.c
@@ -28,12 +28,12 @@ static const char * const rp_filter_names[] = {
"off", "strict", "loose"
};
-static void usage(void) __attribute__((noreturn));
+static void usage(bool help) __attribute__((noreturn));
-static void usage(void)
+static void usage(bool help)
{
- fprintf(stderr, "Usage: ip netconf show [ dev STRING ]\n");
- exit(-1);
+ fprintf(help ? stdout : stderr, "Usage: ip netconf show [ dev STRING ]\n");
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static struct rtattr *netconf_rta(struct netconfmsg *ncm)
@@ -238,7 +238,7 @@ int do_ipnetconf(int argc, char **argv)
matches(*argv, "list") == 0)
return do_show(argc-1, argv+1);
if (matches(*argv, "help") == 0)
- usage();
+ usage(true);
} else
return do_show(0, NULL);
diff --git a/ip/ipnetns.c b/ip/ipnetns.c
index 587534ae..ec0c567b 100644
--- a/ip/ipnetns.c
+++ b/ip/ipnetns.c
@@ -24,9 +24,9 @@
#include "ip_common.h"
#include "namespace.h"
-static int usage(void)
+static int usage(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ip netns list\n"
" ip netns add NAME\n"
" ip netns attach NAME PID\n"
@@ -38,7 +38,7 @@ static int usage(void)
" ip netns monitor\n"
" ip netns list-id [target-nsid POSITIVE-INT] [nsid POSITIVE-INT]\n"
"NETNSID := auto | POSITIVE-INT\n");
- exit(-1);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
/* This socket is used to get nsid */
@@ -421,7 +421,7 @@ static int netns_list_id(int argc, char **argv)
invarg("\"nsid\" value should be >= 0",
argv[1]);
} else
- usage();
+ usage(false);
argc--; argv++;
}
@@ -1013,7 +1013,7 @@ int do_netns(int argc, char **argv)
}
if (matches(*argv, "help") == 0)
- return usage();
+ return usage(true);
if (matches(*argv, "add") == 0)
return netns_add(argc-1, argv+1, true);
diff --git a/ip/ipnexthop.c b/ip/ipnexthop.c
index ad8ad0c0..e5a6d775 100644
--- a/ip/ipnexthop.c
+++ b/ip/ipnexthop.c
@@ -39,11 +39,11 @@ enum {
static struct hlist_head nh_cache[NH_CACHE_SIZE];
static struct rtnl_handle nh_cache_rth = { .fd = -1 };
-static void usage(void) __attribute__((noreturn));
+static void usage(bool help) __attribute__((noreturn));
-static void usage(void)
+static void usage(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ip nexthop { list | flush } [ protocol ID ] SELECTOR\n"
" ip nexthop { add | replace } id ID NH [ protocol ID ]\n"
" ip nexthop { get | del } id ID\n"
@@ -63,7 +63,7 @@ static void usage(void)
" [ unbalanced_timer UNBALANCED ]\n"
"ENCAPTYPE := [ mpls ]\n"
"ENCAPHDR := [ MPLSLABEL ]\n");
- exit(-1);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static int nh_dump_filter(struct nlmsghdr *nlh, int reqlen)
@@ -1154,7 +1154,7 @@ static int ipnh_modify(int cmd, unsigned int flags, int argc, char **argv)
addattr32(&req.n, sizeof(req), NHA_HW_STATS_ENABLE,
hw_stats);
} else if (strcmp(*argv, "help") == 0) {
- usage();
+ usage(true);
} else {
invarg("", *argv);
}
@@ -1251,7 +1251,7 @@ static int ipnh_list_flush(int argc, char **argv, int action)
} else if (!matches(*argv, "fdb")) {
filter.fdb = 1;
} else if (matches(*argv, "help") == 0) {
- usage();
+ usage(true);
} else {
invarg("", *argv);
}
@@ -1290,13 +1290,13 @@ static int ipnh_get(int argc, char **argv)
NEXT_ARG();
id = ipnh_parse_id(*argv);
} else {
- usage();
+ usage(false);
}
argc--; argv++;
}
if (!id) {
- usage();
+ usage(false);
return -1;
}
@@ -1330,7 +1330,7 @@ static int ipnh_bucket_list(int argc, char **argv)
NEXT_ARG();
filter.nhid = ipnh_parse_id(*argv);
} else if (matches(*argv, "help") == 0) {
- usage();
+ usage(true);
} else {
invarg("", *argv);
}
@@ -1414,13 +1414,13 @@ static int ipnh_bucket_get(int argc, char **argv)
invarg("invalid bucket index value", *argv);
bucket_valid = true;
} else {
- usage();
+ usage(false);
}
argc--; argv++;
}
if (!id || !bucket_valid) {
- usage();
+ usage(false);
return -1;
}
@@ -1441,7 +1441,7 @@ static int do_ipnh_bucket(int argc, char **argv)
return ipnh_bucket_get(argc-1, argv+1);
if (!matches(*argv, "help"))
- usage();
+ usage(true);
fprintf(stderr,
"Command \"%s\" is unknown, try \"ip nexthop help\".\n", *argv);
@@ -1477,7 +1477,7 @@ int do_ipnh(int argc, char **argv)
return do_ipnh_bucket(argc-1, argv+1);
if (!matches(*argv, "help"))
- usage();
+ usage(true);
fprintf(stderr,
"Command \"%s\" is unknown, try \"ip nexthop help\".\n", *argv);
diff --git a/ip/ipntable.c b/ip/ipntable.c
index 51fa067c..103ab6e3 100644
--- a/ip/ipntable.c
+++ b/ip/ipntable.c
@@ -27,11 +27,11 @@ static struct
const char *name;
} filter;
-static void usage(void) __attribute__((noreturn));
+static void usage(bool help) __attribute__((noreturn));
-static void usage(void)
+static void usage(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ip ntable change name NAME [ dev DEV ]\n"
" [ thresh1 VAL ] [ thresh2 VAL ] [ thresh3 VAL ] [ gc_int MSEC ]\n"
" [ PARMS ]\n"
@@ -45,7 +45,7 @@ static void usage(void)
" [ locktime MSEC ]\n"
);
- exit(-1);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static int ipntable_modify(int cmd, int flags, int argc, char **argv)
@@ -695,7 +695,7 @@ int do_ipntable(int argc, char **argv)
matches(*argv, "list") == 0)
return ipntable_show(argc-1, argv+1);
if (matches(*argv, "help") == 0)
- usage();
+ usage(true);
} else
return ipntable_show(0, NULL);
diff --git a/ip/iproute.c b/ip/iproute.c
index 1ce71f78..7dd57db6 100644
--- a/ip/iproute.c
+++ b/ip/iproute.c
@@ -52,11 +52,11 @@ static const char *mx_names[RTAX_MAX+1] = {
[RTAX_CC_ALGO] = "congctl",
[RTAX_FASTOPEN_NO_COOKIE] = "fastopen_no_cookie"
};
-static void usage(void) __attribute__((noreturn));
+static void usage(bool help) __attribute__((noreturn));
-static void usage(void)
+static void usage(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ip route { list | flush } SELECTOR\n"
" ip route save SELECTOR\n"
" ip route restore\n"
@@ -116,7 +116,7 @@ static void usage(void)
"XFRMINFO := if_id IF_ID [ link_dev LINK ]\n"
"ROUTE_GET_FLAGS := ROUTE_GET_FLAG [ ROUTE_GET_FLAGS ]\n"
"ROUTE_GET_FLAG := [ connected | fibmatch | notify ]\n");
- exit(-1);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
@@ -1566,7 +1566,7 @@ static int iproute_modify(int cmd, unsigned int flags, int argc, char **argv)
}
if (matches(*argv, "help") == 0)
- usage();
+ usage(true);
if (dst_ok)
duparg2("to", *argv);
get_prefix(&dst, *argv, req.r.rtm_family);
@@ -1582,7 +1582,7 @@ static int iproute_modify(int cmd, unsigned int flags, int argc, char **argv)
}
if (!dst_ok)
- usage();
+ usage(false);
if (d) {
int idx = ll_name_to_index(d);
@@ -1851,7 +1851,7 @@ static int iproute_list_flush_or_save(int argc, char **argv, int action)
} else if (strcmp(*argv, "cache") == 0) {
filter.cloned = 1;
} else if (strcmp(*argv, "help") == 0) {
- usage();
+ usage(true);
} else {
invarg("table id value is invalid\n", *argv);
}
@@ -2078,7 +2078,7 @@ static int iproute_get(int argc, char **argv)
NEXT_ARG();
if (matches(*argv, "help") == 0)
- usage();
+ usage(true);
from_ok = 1;
get_prefix(&addr, *argv, req.r.rtm_family);
if (req.r.rtm_family == AF_UNSPEC)
@@ -2165,7 +2165,7 @@ static int iproute_get(int argc, char **argv)
NEXT_ARG();
}
if (matches(*argv, "help") == 0)
- usage();
+ usage(true);
get_prefix(&addr, *argv, req.r.rtm_family);
if (req.r.rtm_family == AF_UNSPEC)
req.r.rtm_family = addr.family;
@@ -2455,7 +2455,7 @@ int do_iproute(int argc, char **argv)
if (matches(*argv, "showdump") == 0)
return iproute_showdump();
if (matches(*argv, "help") == 0)
- usage();
+ usage(true);
fprintf(stderr,
"Command \"%s\" is unknown, try \"ip route help\".\n", *argv);
diff --git a/ip/iproute_lwtunnel.c b/ip/iproute_lwtunnel.c
index 9a1e747c..513d16e1 100644
--- a/ip/iproute_lwtunnel.c
+++ b/ip/iproute_lwtunnel.c
@@ -60,17 +60,18 @@ static const char *format_encap_type(uint16_t type)
}
}
-static void encap_type_usage(void)
+static void encap_type_usage(bool help)
{
+ FILE *fp = help ? stdout : stderr;
uint16_t i;
- fprintf(stderr, "Usage: ip route ... encap TYPE [ OPTIONS ] [...]\n");
+ fprintf(fp, "Usage: ip route ... encap TYPE [ OPTIONS ] [...]\n");
for (i = 1; i <= LWTUNNEL_ENCAP_MAX; i++)
- fprintf(stderr, "%s %s\n", format_encap_type(i),
+ fprintf(fp, "%s %s\n", format_encap_type(i),
i == 1 ? "TYPE := " : " ");
- exit(-1);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static uint16_t read_encap_type(const char *name)
@@ -96,7 +97,7 @@ static uint16_t read_encap_type(const char *name)
else if (strcmp(name, "xfrm") == 0)
return LWTUNNEL_ENCAP_XFRM;
else if (strcmp(name, "help") == 0)
- encap_type_usage();
+ encap_type_usage(true);
return LWTUNNEL_ENCAP_NONE;
}
@@ -2182,11 +2183,13 @@ static int parse_encap_ip6(struct rtattr *rta, size_t len,
return ret;
}
-static void lwt_bpf_usage(void)
+static void lwt_bpf_usage(bool help)
{
- fprintf(stderr, "Usage: ip route ... encap bpf [ in BPF ] [ out BPF ] [ xmit BPF ] [...]\n");
- fprintf(stderr, "BPF := obj FILE [ section NAME ] [ verbose ]\n");
- exit(-1);
+ FILE *fp = help ? stdout : stderr;
+
+ fprintf(fp, "Usage: ip route ... encap bpf [ in BPF ] [ out BPF ] [ xmit BPF ] [...]\n");
+ fprintf(fp, "BPF := obj FILE [ section NAME ] [ verbose ]\n");
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static int parse_encap_bpf(struct rtattr *rta, size_t len, int *argcp,
@@ -2223,7 +2226,7 @@ static int parse_encap_bpf(struct rtattr *rta, size_t len, int *argcp,
headroom);
headroom_set = 1;
} else if (strcmp(*argv, "help") == 0) {
- lwt_bpf_usage();
+ lwt_bpf_usage(true);
} else {
break;
}
@@ -2240,10 +2243,10 @@ static int parse_encap_bpf(struct rtattr *rta, size_t len, int *argcp,
return 0;
}
-static void lwt_xfrm_usage(void)
+static void lwt_xfrm_usage(bool help)
{
- fprintf(stderr, "Usage: ip route ... encap xfrm if_id IF_ID [ link_dev LINK ]\n");
- exit(-1);
+ fprintf(help ? stdout : stderr, "Usage: ip route ... encap xfrm if_id IF_ID [ link_dev LINK ]\n");
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static int parse_encap_xfrm(struct rtattr *rta, size_t len,
@@ -2275,7 +2278,7 @@ static int parse_encap_xfrm(struct rtattr *rta, size_t len,
exit(nodev(*argv));
ret = rta_addattr32(rta, len, LWT_XFRM_LINK, link);
} else if (!strcmp(*argv, "help")) {
- lwt_xfrm_usage();
+ lwt_xfrm_usage(true);
}
if (ret)
break;
@@ -2283,7 +2286,7 @@ static int parse_encap_xfrm(struct rtattr *rta, size_t len,
}
if (!if_id_ok)
- lwt_xfrm_usage();
+ lwt_xfrm_usage(false);
/* argv is currently the first unparsed argument,
* but the lwt_parse_encap() caller will move to the next,
diff --git a/ip/iprule.c b/ip/iprule.c
index b56b1b18..6fde6004 100644
--- a/ip/iprule.c
+++ b/ip/iprule.c
@@ -34,11 +34,11 @@ enum list_action {
extern struct rtnl_handle rth;
-static void usage(void) __attribute__((noreturn));
+static void usage(bool help) __attribute__((noreturn));
-static void usage(void)
+static void usage(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ip rule { add | del } SELECTOR ACTION\n"
" ip rule { flush | save | restore }\n"
" ip rule [ list [ SELECTOR ]]\n"
@@ -59,7 +59,7 @@ static void usage(void)
"SUPPRESSOR := [ suppress_prefixlength NUMBER ]\n"
" [ suppress_ifgroup DEVGROUP ]\n"
"TABLE_ID := [ local | main | default | NUMBER ]\n");
- exit(-1);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static struct
@@ -1189,7 +1189,7 @@ static int iprule_modify(int cmd, int argc, char **argv)
NEXT_ARG();
if (matches(*argv, "help") == 0)
- usage();
+ usage(true);
else if (matches(*argv, "goto") == 0) {
__u32 target;
@@ -1252,7 +1252,7 @@ int do_iprule(int argc, char **argv)
} else if (matches(argv[0], "flush") == 0) {
return iprule_list_flush_or_save(argc-1, argv+1, IPRULE_FLUSH);
} else if (matches(argv[0], "help") == 0)
- usage();
+ usage(true);
fprintf(stderr,
"Command \"%s\" is unknown, try \"ip rule help\".\n", *argv);
diff --git a/ip/ipseg6.c b/ip/ipseg6.c
index efd37227..e3e6a1e8 100644
--- a/ip/ipseg6.c
+++ b/ip/ipseg6.c
@@ -27,16 +27,16 @@
#define HMAC_KEY_PROMPT "Enter secret for HMAC key ID (blank to delete): "
-static void usage(void)
+static void usage(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ip sr { COMMAND | help }\n"
" ip sr hmac show\n"
" ip sr hmac set KEYID ALGO\n"
" ip sr tunsrc show\n"
" ip sr tunsrc set ADDRESS\n"
"where ALGO := { sha1 | sha256 }\n");
- exit(-1);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static struct rtnl_handle grth = { .fd = -1 };
@@ -204,8 +204,11 @@ static int seg6_do_cmd(void)
int do_seg6(int argc, char **argv)
{
- if (argc < 1 || matches(*argv, "help") == 0)
- usage();
+ if (argc < 1)
+ usage(false);
+
+ if (matches(*argv, "help") == 0)
+ usage(true);
memset(&opts, 0, sizeof(opts));
diff --git a/ip/iptoken.c b/ip/iptoken.c
index 8bd9b4dc..4381a56f 100644
--- a/ip/iptoken.c
+++ b/ip/iptoken.c
@@ -30,12 +30,13 @@ struct rtnl_dump_args {
int ifindex;
};
-static void usage(void) __attribute__((noreturn));
+static void usage(bool help) __attribute__((noreturn));
-static void usage(void)
+static void usage(bool help)
{
- fprintf(stderr, "Usage: ip token [ list | set | del | get ] [ TOKEN ] [ dev DEV ]\n");
- exit(-1);
+ fprintf(help ? stdout : stderr,
+ "Usage: ip token [ list | set | del | get ] [ TOKEN ] [ dev DEV ]\n");
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static int print_token(struct nlmsghdr *n, void *arg)
@@ -146,7 +147,7 @@ static int iptoken_set(int argc, char **argv, bool delete)
}
} else {
if (matches(*argv, "help") == 0)
- usage();
+ usage(true);
if (!have_token) {
get_prefix(&addr, *argv, req.ifi.ifi_family);
have_token = true;
@@ -195,7 +196,7 @@ int do_iptoken(int argc, char **argv)
} else if (matches(argv[0], "get") == 0) {
return iptoken_list(argc - 1, argv + 1);
} else if (matches(argv[0], "help") == 0)
- usage();
+ usage(true);
fprintf(stderr, "Command \"%s\" is unknown, try \"ip token help\".\n", *argv);
exit(-1);
diff --git a/ip/iptunnel.c b/ip/iptunnel.c
index b6da1459..5929e1ef 100644
--- a/ip/iptunnel.c
+++ b/ip/iptunnel.c
@@ -24,11 +24,11 @@
#include "ip_common.h"
#include "tunnel.h"
-static void usage(void) __attribute__((noreturn));
+static void usage(bool help) __attribute__((noreturn));
-static void usage(void)
+static void usage(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ip tunnel { add | change | del | show | prl | 6rd } [ NAME ]\n"
" [ mode { gre | ipip | isatap | sit | vti } ]\n"
" [ remote ADDR ] [ local ADDR ]\n"
@@ -42,7 +42,7 @@ static void usage(void)
" TOS := { STRING | 00..ff | inherit | inherit/STRING | inherit/00..ff }\n"
" TTL := { 1..255 | inherit }\n"
" KEY := { DOTTED_QUAD | NUMBER }\n");
- exit(-1);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static void set_tunnel_proto(struct ip_tunnel_parm *p, int proto)
@@ -166,7 +166,7 @@ static int parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p)
if (strcmp(*argv, "name") == 0)
NEXT_ARG();
else if (matches(*argv, "help") == 0)
- usage();
+ usage(true);
if (p->name[0])
duparg2("name", *argv);
@@ -593,7 +593,7 @@ int do_iptunnel(int argc, char **argv)
if (matches(*argv, "6rd") == 0)
return do_6rd(argc - 1, argv + 1);
if (matches(*argv, "help") == 0)
- usage();
+ usage(true);
} else
return do_show(0, NULL);
diff --git a/ip/iptuntap.c b/ip/iptuntap.c
index 0f46fe6a..91de6050 100644
--- a/ip/iptuntap.c
+++ b/ip/iptuntap.c
@@ -31,18 +31,18 @@ static const char drv_name[] = "tun";
#define TUNDEV "/dev/net/tun"
-static void usage(void) __attribute__((noreturn));
+static void usage(bool help) __attribute__((noreturn));
-static void usage(void)
+static void usage(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ip tuntap { add | del | show | list | lst | help } [ dev PHYS_DEV ]\n"
" [ mode { tun | tap } ] [ user USER ] [ group GROUP ]\n"
" [ one_queue ] [ pi ] [ vnet_hdr ] [ multi_queue ] [ name NAME ]\n"
"\n"
"Where: USER := { STRING | NUMBER }\n"
" GROUP := { STRING | NUMBER }\n");
- exit(-1);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static int tap_add_ioctl(struct ifreq *ifr, uid_t uid, gid_t gid)
@@ -179,7 +179,7 @@ static int parse_args(int argc, char **argv,
if (matches(*argv, "name") == 0) {
NEXT_ARG();
} else if (matches(*argv, "help") == 0)
- usage();
+ usage(true);
if (ifr->ifr_name[0])
duparg2("name", *argv);
if (get_ifname(ifr->ifr_name, *argv))
@@ -460,7 +460,7 @@ int do_iptuntap(int argc, char **argv)
matches(*argv, "list") == 0)
return do_show(argc-1, argv+1);
if (matches(*argv, "help") == 0)
- usage();
+ usage(true);
} else
return do_show(0, NULL);
diff --git a/ip/ipvrf.c b/ip/ipvrf.c
index e7c702ab..e2b897d2 100644
--- a/ip/ipvrf.c
+++ b/ip/ipvrf.c
@@ -30,15 +30,15 @@
static struct link_filter vrf_filter;
-static void usage(void)
+static void usage(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ip vrf show [NAME] ...\n"
" ip vrf exec [NAME] cmd ...\n"
" ip vrf identify [PID]\n"
" ip vrf pids [NAME]\n");
- exit(-1);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
/*
@@ -585,7 +585,7 @@ static int ipvrf_show(int argc, char **argv)
vrf_filter.kind = "vrf";
if (argc > 1)
- usage();
+ usage(false);
if (argc == 1) {
__u32 tb_id;
@@ -645,7 +645,7 @@ int do_ipvrf(int argc, char **argv)
return ipvrf_show(argc-1, argv+1);
if (matches(*argv, "help") == 0)
- usage();
+ usage(true);
fprintf(stderr, "Command \"%s\" is unknown, try \"ip vrf help\".\n",
*argv);
diff --git a/ip/ipxfrm.c b/ip/ipxfrm.c
index 586d24fb..1765ec81 100644
--- a/ip/ipxfrm.c
+++ b/ip/ipxfrm.c
@@ -28,14 +28,14 @@
struct xfrm_filter filter;
-static void usage(void) __attribute__((noreturn));
+static void usage(bool help) __attribute__((noreturn));
-static void usage(void)
+static void usage(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ip xfrm XFRM-OBJECT { COMMAND | help }\n"
"where XFRM-OBJECT := state | policy | monitor\n");
- exit(-1);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
/* This is based on utils.c(inet_addr_match) */
@@ -1556,7 +1556,7 @@ int do_xfrm(int argc, char **argv)
memset(&filter, 0, sizeof(filter));
if (argc < 1)
- usage();
+ usage(false);
if (matches(*argv, "state") == 0 ||
matches(*argv, "sa") == 0)
@@ -1566,9 +1566,9 @@ int do_xfrm(int argc, char **argv)
else if (matches(*argv, "monitor") == 0)
return do_xfrm_monitor(argc-1, argv+1);
else if (matches(*argv, "help") == 0) {
- usage();
+ usage(true);
fprintf(stderr, "xfrm Object \"%s\" is unknown.\n", *argv);
exit(-1);
}
- usage();
+ usage(false);
}
diff --git a/ip/link_veth.c b/ip/link_veth.c
index 6da5b64f..222e7f4b 100644
--- a/ip/link_veth.c
+++ b/ip/link_veth.c
@@ -12,15 +12,11 @@
#include "utils.h"
#include "ip_common.h"
-static void print_usage(FILE *f)
+static void print_usage(FILE *fp)
{
- printf("Usage: ip link <options> type veth [peer <options>]\n"
- "To get <options> type 'ip link add help'\n");
-}
-
-static void usage(void)
-{
- print_usage(stderr);
+ fprintf(fp,
+ "Usage: ip link <options> type veth [peer <options>]\n"
+ "To get <options> type 'ip link add help'\n");
}
static int veth_parse_opt(struct link_util *lu, int argc, char **argv,
@@ -33,7 +29,7 @@ static int veth_parse_opt(struct link_util *lu, int argc, char **argv,
unsigned int ifi_flags, ifi_change, ifi_index;
if (strcmp(argv[0], "peer") != 0) {
- usage();
+ print_usage(stderr);
return -1;
}
diff --git a/ip/rtmon.c b/ip/rtmon.c
index 470f4ba6..ef49da1e 100644
--- a/ip/rtmon.c
+++ b/ip/rtmon.c
@@ -55,14 +55,14 @@ static int dump_msg2(struct nlmsghdr *n, void *arg)
return dump_msg(NULL, n, arg);
}
-static void usage(void)
+static void usage(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: rtmon [ OPTIONS ] file FILE [ all | OBJECTS ]\n"
"OPTIONS := { -f[amily] { inet | inet6 | link | help } |\n"
" -4 | -6 | -0 | -V[ersion] }\n"
"OBJECTS := [ link ] [ address ] [ route ]\n");
- exit(-1);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
int
@@ -90,7 +90,7 @@ main(int argc, char **argv)
else if (strcmp(argv[1], "link") == 0)
family = AF_INET6;
else if (strcmp(argv[1], "help") == 0)
- usage();
+ usage(true);
else {
fprintf(stderr, "Protocol ID \"%s\" is unknown, try \"rtmon help\".\n", argv[1]);
exit(-1);
@@ -122,7 +122,7 @@ main(int argc, char **argv)
} else if (strcmp(argv[1], "all") == 0) {
groups = ~0U;
} else if (matches(argv[1], "help") == 0) {
- usage();
+ usage(true);
} else {
fprintf(stderr, "Argument \"%s\" is unknown, try \"rtmon help\".\n", argv[1]);
exit(-1);
diff --git a/ip/tcp_metrics.c b/ip/tcp_metrics.c
index 6b9e6831..a5fdfb4d 100644
--- a/ip/tcp_metrics.c
+++ b/ip/tcp_metrics.c
@@ -23,14 +23,14 @@
#include "ip_common.h"
#include "libgenl.h"
-static void usage(void)
+static void usage(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ip tcp_metrics/tcpmetrics { COMMAND | help }\n"
" ip tcp_metrics { show | flush } SELECTOR\n"
" ip tcp_metrics delete [ address ] ADDRESS\n"
"SELECTOR := [ [ address ] PREFIX ]\n");
- exit(-1);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
/* netlink socket */
@@ -366,7 +366,7 @@ static int tcpm_do_cmd(int cmd, int argc, char **argv)
NEXT_ARG();
if (matches(*argv, "help") == 0)
- usage();
+ usage(true);
if (f.saddr.bitlen >= 0)
duparg2(who, *argv);
@@ -392,7 +392,7 @@ static int tcpm_do_cmd(int cmd, int argc, char **argv)
NEXT_ARG();
}
if (matches(*argv, "help") == 0)
- usage();
+ usage(true);
if (f.daddr.bitlen >= 0)
duparg2(who, *argv);
@@ -529,7 +529,7 @@ int do_tcp_metrics(int argc, char **argv)
return tcpm_do_cmd(cmds[i].code, argc-1, argv+1);
}
if (matches(argv[0], "help") == 0)
- usage();
+ usage(true);
fprintf(stderr, "Command \"%s\" is unknown, try \"ip tcp_metrics help\".\n",
*argv);
diff --git a/ip/xfrm_monitor.c b/ip/xfrm_monitor.c
index a96358b0..7f6f088a 100644
--- a/ip/xfrm_monitor.c
+++ b/ip/xfrm_monitor.c
@@ -17,16 +17,16 @@
#include "xfrm.h"
#include "ip_common.h"
-static void usage(void) __attribute__((noreturn));
+static void usage(bool help) __attribute__((noreturn));
static int listen_all_nsid;
static bool nokeys;
-static void usage(void)
+static void usage(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ip xfrm monitor [ nokeys ] [ all-nsid ] [ all | OBJECTS | help ]\n"
"OBJECTS := { acquire | expire | SA | aevent | policy | report }\n");
- exit(-1);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static int xfrm_acquire_print(struct nlmsghdr *n, void *arg)
@@ -361,7 +361,7 @@ int do_xfrm_monitor(int argc, char **argv)
lreport = 1;
groups = 0;
} else if (matches(*argv, "help") == 0) {
- usage();
+ usage(true);
} else {
fprintf(stderr, "Argument \"%s\" is unknown, try \"ip xfrm monitor help\".\n", *argv);
exit(-1);
diff --git a/ip/xfrm_policy.c b/ip/xfrm_policy.c
index e60acd5b..79fe59f3 100644
--- a/ip/xfrm_policy.c
+++ b/ip/xfrm_policy.c
@@ -32,11 +32,13 @@
#define XFRM_TMPLS_BUF_SIZE 1024
#define CTX_BUF_SIZE 256
-static void usage(void) __attribute__((noreturn));
+static void usage(bool help) __attribute__((noreturn));
-static void usage(void)
+static void usage(bool help)
{
- fprintf(stderr,
+ FILE *fp = help ? stdout : stderr;
+
+ fprintf(fp,
"Usage: ip xfrm policy { add | update } SELECTOR dir DIR [ ctx CTX ]\n"
" [ mark MARK [ mask MASK ] ] [ index INDEX ] [ ptype PTYPE ]\n"
" [ action ACTION ] [ priority PRIORITY ] [ flag FLAG-LIST ]\n"
@@ -69,18 +71,18 @@ static void usage(void)
"TMPL := ID [ mode MODE ] [ reqid REQID ] [ level LEVEL ]\n"
"ID := [ src ADDR ] [ dst ADDR ] [ proto XFRM-PROTO ] [ spi SPI ]\n"
"XFRM-PROTO := ");
- fprintf(stderr,
+ fprintf(fp,
"%s | %s | %s | %s | %s\n",
strxf_xfrmproto(IPPROTO_ESP),
strxf_xfrmproto(IPPROTO_AH),
strxf_xfrmproto(IPPROTO_COMP),
strxf_xfrmproto(IPPROTO_ROUTING),
strxf_xfrmproto(IPPROTO_DSTOPTS));
- fprintf(stderr,
+ fprintf(fp,
"MODE := transport | tunnel | beet | ro | in_trigger\n"
"LEVEL := required | use\n");
- exit(-1);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static int xfrm_policy_dir_parse(__u8 *dir, int *argcp, char ***argvp)
@@ -1340,7 +1342,7 @@ int do_xfrm_policy(int argc, char **argv)
if (matches(*argv, "getdefault") == 0)
return xfrm_spd_getdefault(argc-1, argv+1);
if (matches(*argv, "help") == 0)
- usage();
+ usage(true);
fprintf(stderr, "Command \"%s\" is unknown, try \"ip xfrm policy help\".\n", *argv);
exit(-1);
}
diff --git a/ip/xfrm_state.c b/ip/xfrm_state.c
index dcd08d59..d344ddc9 100644
--- a/ip/xfrm_state.c
+++ b/ip/xfrm_state.c
@@ -34,11 +34,13 @@
#define XFRM_ALGO_KEY_BUF_SIZE 512
#define CTX_BUF_SIZE 256
-static void usage(void) __attribute__((noreturn));
+static void usage(bool help) __attribute__((noreturn));
-static void usage(void)
+static void usage(bool help)
{
- fprintf(stderr,
+ FILE *fp = help ? stdout : stderr;
+
+ fprintf(fp,
"Usage: ip xfrm state { add | update } ID [ ALGO-LIST ] [ mode MODE ]\n"
" [ mark MARK [ mask MASK ] ] [ reqid REQID ] [ dir DIR ] [ seq SEQ ]\n"
" [ replay-window SIZE ] [ replay-seq SEQ ] [ replay-oseq SEQ ]\n"
@@ -59,30 +61,30 @@ static void usage(void)
"Usage: ip xfrm state count\n"
"ID := [ src ADDR ] [ dst ADDR ] [ proto XFRM-PROTO ] [ spi SPI ]\n"
"XFRM-PROTO := ");
- fprintf(stderr,
+ fprintf(fp,
"%s | %s | %s | %s | %s\n",
strxf_xfrmproto(IPPROTO_ESP),
strxf_xfrmproto(IPPROTO_AH),
strxf_xfrmproto(IPPROTO_COMP),
strxf_xfrmproto(IPPROTO_ROUTING),
strxf_xfrmproto(IPPROTO_DSTOPTS));
- fprintf(stderr,
+ fprintf(fp,
"ALGO-LIST := [ ALGO-LIST ] ALGO\n"
"ALGO := { ");
- fprintf(stderr,
+ fprintf(fp,
"%s | %s",
strxf_algotype(XFRMA_ALG_CRYPT),
strxf_algotype(XFRMA_ALG_AUTH));
- fprintf(stderr,
+ fprintf(fp,
" } ALGO-NAME ALGO-KEYMAT |\n"
" %s", strxf_algotype(XFRMA_ALG_AUTH_TRUNC));
- fprintf(stderr,
+ fprintf(fp,
" ALGO-NAME ALGO-KEYMAT ALGO-TRUNC-LEN |\n"
" %s", strxf_algotype(XFRMA_ALG_AEAD));
- fprintf(stderr,
+ fprintf(fp,
" ALGO-NAME ALGO-KEYMAT ALGO-ICV-LEN |\n"
" %s", strxf_algotype(XFRMA_ALG_COMP));
- fprintf(stderr,
+ fprintf(fp,
" ALGO-NAME\n"
"MODE := transport | tunnel | beet | ro | in_trigger\n"
"FLAG-LIST := [ FLAG-LIST ] FLAG\n"
@@ -99,7 +101,7 @@ static void usage(void)
"ENCAP := { espinudp | espinudp-nonike | espintcp } SPORT DPORT OADDR\n"
"DIR := in | out\n");
- exit(-1);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static int xfrm_algo_parse(struct xfrm_algo *alg, enum xfrm_attr_type_t type,
@@ -1512,7 +1514,7 @@ int do_xfrm_state(int argc, char **argv)
return xfrm_sad_getinfo(argc, argv);
}
if (matches(*argv, "help") == 0)
- usage();
+ usage(true);
fprintf(stderr, "Command \"%s\" is unknown, try \"ip xfrm state help\".\n", *argv);
exit(-1);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH iproute2-next 2/7] ip/routel: follow help vs usage convention
2026-08-07 15:42 [PATCH iproute2-next 0/7] cleanup help and exit codes Stephen Hemminger
2026-08-07 15:42 ` [PATCH iproute2-next 1/7] ip: follow Linux convention for help vs usage Stephen Hemminger
@ 2026-08-07 15:42 ` Stephen Hemminger
2026-08-07 15:42 ` [PATCH iproute2-next 3/7] misc: put help to stdout and usage to stderr Stephen Hemminger
` (4 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Stephen Hemminger @ 2026-08-07 15:42 UTC (permalink / raw)
To: netdev; +Cc: dsahern, Stephen Hemminger
Similar to update to ip, put help on stdout and usage
on stderr.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
ip/routel | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/ip/routel b/ip/routel
index 09a90126..defe738c 100755
--- a/ip/routel
+++ b/ip/routel
@@ -11,10 +11,11 @@ import getopt
import subprocess
-def usage():
+def usage(help=False):
'''Print usage and exit'''
- print("Usage: {} [tablenr [raw ip args...]]".format(sys.argv[0]))
- sys.exit(64)
+ print("Usage: {} [tablenr [raw ip args...]]".format(sys.argv[0]),
+ file=sys.stdout if help else sys.stderr)
+ sys.exit(0 if help else 1)
def main():
@@ -23,12 +24,12 @@ def main():
try:
opts, args = getopt.getopt(sys.argv[1:], "h46f:", ["help", "family="])
except getopt.GetoptError as err:
- print(err)
+ print(err, file=sys.stderr)
usage()
for opt, arg in opts:
if opt in ["-h", "--help"]:
- usage()
+ usage(True)
elif opt == '-6':
family = 'inet6'
elif opt == "-4":
--
2.53.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH iproute2-next 3/7] misc: put help to stdout and usage to stderr
2026-08-07 15:42 [PATCH iproute2-next 0/7] cleanup help and exit codes Stephen Hemminger
2026-08-07 15:42 ` [PATCH iproute2-next 1/7] ip: follow Linux convention for help vs usage Stephen Hemminger
2026-08-07 15:42 ` [PATCH iproute2-next 2/7] ip/routel: follow help vs usage convention Stephen Hemminger
@ 2026-08-07 15:42 ` Stephen Hemminger
2026-08-07 15:42 ` [PATCH iproute2-next 4/7] netshaper: " Stephen Hemminger
` (3 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Stephen Hemminger @ 2026-08-07 15:42 UTC (permalink / raw)
To: netdev; +Cc: dsahern, Stephen Hemminger
Similar change to other iproute2 commands.
Syntax error should print to stderr and exit with non-zero.
Help command should print to stdout and exit with zero status.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
misc/arpd.c | 12 +++++++-----
misc/ifstat.c | 44 ++++++++++++++++++++++----------------------
misc/nstat.c | 11 ++++++-----
misc/rtacct.c | 13 ++++++-------
4 files changed, 41 insertions(+), 39 deletions(-)
diff --git a/misc/arpd.c b/misc/arpd.c
index a42603f6..230d3580 100644
--- a/misc/arpd.c
+++ b/misc/arpd.c
@@ -6,6 +6,7 @@
*/
#include <stdio.h>
+#include <stdbool.h>
#include <syslog.h>
#include <malloc.h>
#include <string.h>
@@ -88,11 +89,12 @@ int broadcast_rate = 1000;
int broadcast_burst = 3000;
int poll_timeout = 30000;
-static void usage(void)
+static void usage(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: arpd [ -lkh? ] [ -a N ] [ -b dbase ] [ -B number ] [ -f file ] [ -n time ] [-p interval ] [ -R rate ] [ interfaces ]\n");
- exit(1);
+
+ exit(help ? 0 : 1);
}
static int handle_if(int ifindex)
@@ -594,7 +596,7 @@ int main(int argc, char **argv)
case 'f':
if (do_load) {
fprintf(stderr, "Duplicate option -f\n");
- usage();
+ usage(true);
}
do_load = optarg;
break;
@@ -633,7 +635,7 @@ int main(int argc, char **argv)
case 'h':
case '?':
default:
- usage();
+ usage(opt == 'h');
}
}
argc -= optind;
diff --git a/misc/ifstat.c b/misc/ifstat.c
index ec59a9eb..c2ea5942 100644
--- a/misc/ifstat.c
+++ b/misc/ifstat.c
@@ -756,8 +756,8 @@ static int verify_forging(int fd)
static void xstat_usage(void)
{
fprintf(stderr,
-"Usage: ifstat supported xstats:\n"
-" cpu_hits Counts only packets that went via the CPU.\n");
+ "Usage: ifstat supported xstats:\n"
+ " cpu_hits Counts only packets that went via the CPU.\n");
}
struct extended_stats_options_t {
@@ -796,27 +796,27 @@ static const char *get_filter_type(const char *name)
return NULL;
}
-static void usage(void) __attribute__((noreturn));
+static void usage(bool help) __attribute__((noreturn));
-static void usage(void)
+static void usage(bool help)
{
- fprintf(stderr,
-"Usage: ifstat [OPTION] [ PATTERN [ PATTERN ] ]\n"
-" -h, --help this message\n"
-" -a, --ignore ignore history\n"
-" -d, --scan=SECS sample every statistics every SECS\n"
-" -e, --errors show errors\n"
-" -j, --json format output in JSON\n"
-" -n, --nooutput do history only\n"
-" -p, --pretty pretty print\n"
-" -r, --reset reset history\n"
-" -s, --noupdate don't update history\n"
-" -t, --interval=SECS report average over the last SECS\n"
-" -V, --version output version information\n"
-" -z, --zeros show entries with zero activity\n"
-" -x, --extended=TYPE show extended stats of TYPE\n");
-
- exit(-1);
+ fprintf(help ? stdout : stderr,
+ "Usage: ifstat [OPTION] [ PATTERN [ PATTERN ] ]\n"
+ " -h, --help this message\n"
+ " -a, --ignore ignore history\n"
+ " -d, --scan=SECS sample every statistics every SECS\n"
+ " -e, --errors show errors\n"
+ " -j, --json format output in JSON\n"
+ " -n, --nooutput do history only\n"
+ " -p, --pretty pretty print\n"
+ " -r, --reset reset history\n"
+ " -s, --noupdate don't update history\n"
+ " -t, --interval=SECS report average over the last SECS\n"
+ " -V, --version output version information\n"
+ " -z, --zeros show entries with zero activity\n"
+ " -x, --extended=TYPE show extended stats of TYPE\n");
+
+ exit(help ? 0 : 1);
}
static const struct option longopts[] = {
@@ -898,7 +898,7 @@ int main(int argc, char *argv[])
case 'h':
case '?':
default:
- usage();
+ usage(ch == 'h');
}
}
diff --git a/misc/nstat.c b/misc/nstat.c
index 4a9f3326..cd822ba2 100644
--- a/misc/nstat.c
+++ b/misc/nstat.c
@@ -7,6 +7,7 @@
#include <stdio.h>
#include <stdlib.h>
+#include <stdbool.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
@@ -528,11 +529,11 @@ static int verify_forging(int fd)
return -1;
}
-static void usage(void) __attribute__((noreturn));
+static void usage(bool help) __attribute__((noreturn));
-static void usage(void)
+static void usage(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: nstat [OPTION] [ PATTERN [ PATTERN ] ]\n"
" -h, --help this message\n"
" -a, --ignore ignore history\n"
@@ -545,7 +546,7 @@ static void usage(void)
" -t, --interval=SECS report average over the last SECS\n"
" -V, --version output version information\n"
" -z, --zeros show entries with zero activity\n");
- exit(-1);
+ exit(help ? 0 : 1);
}
static const struct option longopts[] = {
@@ -612,7 +613,7 @@ int main(int argc, char *argv[])
case 'h':
case '?':
default:
- usage();
+ usage(ch == 'h');
}
}
diff --git a/misc/rtacct.c b/misc/rtacct.c
index cd84b7f0..0e2c03af 100644
--- a/misc/rtacct.c
+++ b/misc/rtacct.c
@@ -412,14 +412,13 @@ static int verify_forging(int fd)
return -1;
}
-static void usage(void) __attribute__((noreturn));
+static void usage(bool help) __attribute__((noreturn));
-static void usage(void)
+static void usage(bool help)
{
- fprintf(stderr,
-"Usage: rtacct [ -h?vVzrnasd:t: ] [ ListOfRealms ]\n"
- );
- exit(-1);
+ fprintf(help ? stdout : stderr,
+ "Usage: rtacct [ -h?vVzrnasd:t: ] [ ListOfRealms ]\n");
+ exit(help ? 0 : 1);
}
int main(int argc, char *argv[])
@@ -469,7 +468,7 @@ int main(int argc, char *argv[])
case 'h':
case '?':
default:
- usage();
+ usage(ch == 'h');
}
}
--
2.53.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH iproute2-next 4/7] netshaper: put help to stdout and usage to stderr
2026-08-07 15:42 [PATCH iproute2-next 0/7] cleanup help and exit codes Stephen Hemminger
` (2 preceding siblings ...)
2026-08-07 15:42 ` [PATCH iproute2-next 3/7] misc: put help to stdout and usage to stderr Stephen Hemminger
@ 2026-08-07 15:42 ` Stephen Hemminger
2026-08-07 15:42 ` [PATCH iproute2-next 5/7] bridge: " Stephen Hemminger
` (2 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Stephen Hemminger @ 2026-08-07 15:42 UTC (permalink / raw)
To: netdev; +Cc: dsahern, Stephen Hemminger
Similar change to other iproute2 commands.
Syntax error should print to stderr and exit with non-zero.
Help command should print to stdout and exit with zero status.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
netshaper/netshaper.c | 31 ++++++++++++++++---------------
1 file changed, 16 insertions(+), 15 deletions(-)
diff --git a/netshaper/netshaper.c b/netshaper/netshaper.c
index 3b47d43d..85999dd5 100644
--- a/netshaper/netshaper.c
+++ b/netshaper/netshaper.c
@@ -26,9 +26,11 @@
static struct rtnl_handle gen_rth = { .fd = -1 };
static int genl_family = -1;
-static void usage(void)
+static void usage(bool help) __attribute__((noreturn));
+
+static void usage(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: netshaper [ OPTIONS ] { COMMAND | help }\n"
"OPTIONS := { -V[ersion] | -c[olor] | -help }\n"
"COMMAND := { set | get | delete | group } dev DEVNAME\n"
@@ -46,6 +48,8 @@ static void usage(void)
" HANDLE_ID := UINT (required for queue/node, optional for netdev)\n"
" BW_MIN/BW_MAX := UINT{ kbit | mbit | gbit }\n"
" WEIGHT := UINT\n");
+
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static const char *net_shaper_scope_names[NET_SHAPER_SCOPE_MAX + 1] = {
@@ -243,7 +247,7 @@ static int do_cmd(int argc, char **argv, int cmd)
if (strcmp(*argv, "scope") != 0) {
fprintf(stderr, "What is \"%s\"\n", *argv);
- usage();
+ usage(false);
return -1;
}
NEXT_ARG();
@@ -270,7 +274,7 @@ static int do_cmd(int argc, char **argv, int cmd)
NEXT_ARG();
if (strcmp(*argv, "id") != 0) {
fprintf(stderr, "What is \"%s\"\n", *argv);
- usage();
+ usage(false);
return -1;
}
NEXT_ARG();
@@ -282,7 +286,7 @@ static int do_cmd(int argc, char **argv, int cmd)
}
} else {
fprintf(stderr, "What is \"%s\"\n", *argv);
- usage();
+ usage(false);
return -1;
}
argc--;
@@ -363,7 +367,7 @@ static int parse_scope_id(const char *what, int *argcp, char ***argvp, int *scop
NEXT_ARG();
if (strcmp(*argv, "id") != 0) {
fprintf(stderr, "What is \"%s\"\n", *argv);
- usage();
+ usage(false);
return -1;
}
NEXT_ARG();
@@ -517,7 +521,7 @@ static int do_group(int argc, char **argv)
continue;
} else {
fprintf(stderr, "What is \"%s\"\n", *argv);
- usage();
+ usage(false);
goto free_leaves;
}
argc--;
@@ -609,8 +613,7 @@ int main(int argc, char **argv)
opt++;
if (strcmp(opt, "-help") == 0) {
- usage();
- exit(0);
+ usage(true);
} else if (strcmp(opt, "-Version") == 0 ||
strcmp(opt, "-V") == 0) {
printf("netshaper utility, %s\n", version);
@@ -627,6 +630,9 @@ int main(int argc, char **argv)
check_enable_color(color, 0);
+ if (argc > 1 && strcmp(argv[1], "help") == 0)
+ usage(true);
+
if (genl_init_handle(&gen_rth, NET_SHAPER_FAMILY_NAME, &genl_family))
exit(1);
@@ -642,15 +648,10 @@ int main(int argc, char **argv)
return do_cmd(argc - 1, argv + 1, NET_SHAPER_CMD_GET);
if (strcmp(*argv, "group") == 0)
return do_group(argc - 1, argv + 1);
- if (strcmp(*argv, "help") == 0) {
- usage();
- return 0;
- }
fprintf(stderr,
"Command \"%s\" is unknown, try \"netshaper help\".\n",
*argv);
exit(-1);
}
- usage();
- exit(-1);
+ usage(false);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH iproute2-next 5/7] bridge: put help to stdout and usage to stderr
2026-08-07 15:42 [PATCH iproute2-next 0/7] cleanup help and exit codes Stephen Hemminger
` (3 preceding siblings ...)
2026-08-07 15:42 ` [PATCH iproute2-next 4/7] netshaper: " Stephen Hemminger
@ 2026-08-07 15:42 ` Stephen Hemminger
2026-08-07 15:42 ` [PATCH iproute2-next 6/7] genl: " Stephen Hemminger
2026-08-07 15:42 ` [PATCH iproute2-next 7/7] tc: " Stephen Hemminger
6 siblings, 0 replies; 8+ messages in thread
From: Stephen Hemminger @ 2026-08-07 15:42 UTC (permalink / raw)
To: netdev; +Cc: dsahern, Stephen Hemminger
Similar change to other iproute2 commands.
Syntax error should print to stderr and exit with non-zero.
Help command should print to stdout and exit with zero status.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
bridge/bridge.c | 20 ++++++++++----------
bridge/fdb.c | 18 +++++++++---------
bridge/link.c | 16 +++++++++++-----
bridge/mdb.c | 14 +++++++-------
bridge/monitor.c | 11 ++++++-----
bridge/mst.c | 10 +++++-----
bridge/vlan.c | 10 +++++-----
bridge/vni.c | 10 +++++-----
8 files changed, 58 insertions(+), 51 deletions(-)
diff --git a/bridge/bridge.c b/bridge/bridge.c
index d993ba19..45504e7f 100644
--- a/bridge/bridge.c
+++ b/bridge/bridge.c
@@ -29,23 +29,23 @@ int timestamp;
static const char *batch_file;
int force;
-static void usage(void) __attribute__((noreturn));
+static void usage(bool help) __attribute__((noreturn));
-static void usage(void)
+static void usage(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: bridge [ OPTIONS ] OBJECT { COMMAND | help }\n"
" bridge [ -force ] -batch filename\n"
"where OBJECT := { link | fdb | mdb | mst | vlan | vni | monitor }\n"
" OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] |\n"
" -o[neline] | -t[imestamp] | -n[etns] name |\n"
" -com[pressvlans] -c[olor] -p[retty] -j[son] }\n");
- exit(-1);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static int do_help(int argc, char **argv)
{
- usage();
+ usage(true);
}
@@ -118,7 +118,7 @@ main(int argc, char **argv)
opt++;
if (matches(opt, "-help") == 0) {
- usage();
+ usage(true);
} else if (matches(opt, "-Version") == 0) {
printf("bridge utility, %s\n", version);
exit(0);
@@ -135,13 +135,13 @@ main(int argc, char **argv)
argc--;
argv++;
if (argc <= 1)
- usage();
+ usage(false);
if (strcmp(argv[1], "inet") == 0)
preferred_family = AF_INET;
else if (strcmp(argv[1], "inet6") == 0)
preferred_family = AF_INET6;
else if (strcmp(argv[1], "help") == 0)
- usage();
+ usage(true);
else
invarg("invalid protocol family", argv[1]);
} else if (strcmp(opt, "-4") == 0) {
@@ -165,7 +165,7 @@ main(int argc, char **argv)
argc--;
argv++;
if (argc <= 1)
- usage();
+ usage(false);
batch_file = argv[1];
} else {
fprintf(stderr,
@@ -192,5 +192,5 @@ main(int argc, char **argv)
return do_cmd(argv[1], argc-1, argv+1);
rtnl_close(&rth);
- usage();
+ usage(false);
}
diff --git a/bridge/fdb.c b/bridge/fdb.c
index 05f093b5..9338cf82 100644
--- a/bridge/fdb.c
+++ b/bridge/fdb.c
@@ -33,9 +33,9 @@
static unsigned int filter_index, filter_dynamic, filter_master,
filter_state, filter_vlan;
-static void usage(void)
+static void usage(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: bridge fdb { add | append | del | replace } ADDR dev DEV\n"
" [ self ] [ master ] [ use ] [ router ] [ extern_learn ]\n"
" [ sticky ] [ local | static | dynamic ] [ vlan VID ]\n"
@@ -51,7 +51,7 @@ static void usage(void)
" [ master ] [ [no]permanent | [no]static | [no]dynamic ]\n"
" [ [no]added_by_user ] [ [no]extern_learn ] [ [no]sticky ]\n"
" [ [no]offloaded ] [ [no]router ]\n");
- exit(-1);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static const char *state_n2a(unsigned int s)
@@ -379,7 +379,7 @@ static int fdb_show(int argc, char **argv)
filter_dynamic = 1;
} else {
if (matches(*argv, "help") == 0)
- usage();
+ usage(true);
}
argc--; argv++;
}
@@ -558,7 +558,7 @@ static int fdb_modify(int cmd, int flags, int argc, char **argv)
NEXT_ARG();
if (matches(*argv, "help") == 0)
- usage();
+ usage(true);
if (addr)
duparg2("to", *argv);
addr = *argv;
@@ -680,7 +680,7 @@ static int fdb_get(int argc, char **argv)
NEXT_ARG();
if (matches(*argv, "help") == 0)
- usage();
+ usage(true);
if (addr)
duparg2("to", *argv);
addr = *argv;
@@ -871,11 +871,11 @@ static int fdb_flush(int argc, char **argv)
get_addr(&dst, *argv, preferred_family);
dst_ok = 1;
} else if (strcmp(*argv, "help") == 0) {
- NEXT_ARG();
+ usage(true);
} else {
fprintf(stderr, "bridge fdb: unknown command \"%s\"?\n",
*argv);
- usage();
+ usage(false);
return -1;
}
argc--; argv++;
@@ -966,7 +966,7 @@ int do_fdb(int argc, char **argv)
if (strcmp(*argv, "flush") == 0)
return fdb_flush(argc-1, argv+1);
if (matches(*argv, "help") == 0)
- usage();
+ usage(true);
} else
return fdb_show(0, NULL);
diff --git a/bridge/link.c b/bridge/link.c
index 370d7de4..1ceeaaac 100644
--- a/bridge/link.c
+++ b/bridge/link.c
@@ -298,9 +298,9 @@ int print_linkinfo(struct nlmsghdr *n, void *arg)
return 0;
}
-static void usage(void)
+static void usage(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: bridge link set dev DEV [ cost COST ] [ priority PRIO ] [ state STATE ]\n"
" [ guard {on | off} ]\n"
" [ hairpin {on | off} ]\n"
@@ -326,7 +326,7 @@ static void usage(void)
" [ backup_nhid NHID ]\n"
" [ self ] [ master ]\n"
" bridge link show [dev DEV] [master DEVICE]\n");
- exit(-1);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static int brlink_modify(int argc, char **argv)
@@ -521,7 +521,13 @@ static int brlink_modify(int argc, char **argv)
invarg("invalid backup_nhid", *argv);
backup_nhid_set = true;
} else {
- usage();
+ bool help = matches(*argv, "help") == 0;
+
+ if (!help)
+ fprintf(stderr,
+ "Error: argument \"%s\" is unknown.\n",
+ *argv);
+ usage(help);
}
argc--; argv++;
}
@@ -699,7 +705,7 @@ int do_link(int argc, char **argv)
matches(*argv, "list") == 0)
return brlink_show(argc-1, argv+1);
if (matches(*argv, "help") == 0)
- usage();
+ usage(true);
} else
return brlink_show(0, NULL);
diff --git a/bridge/mdb.c b/bridge/mdb.c
index 112deeb9..11b2bce9 100644
--- a/bridge/mdb.c
+++ b/bridge/mdb.c
@@ -30,9 +30,9 @@
static unsigned int filter_index, filter_vlan;
-static void usage(void)
+static void usage(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: bridge mdb { add | del | replace } dev DEV port PORT grp GROUP [src SOURCE] [permanent | temp] [vid VID]\n"
" [ filter_mode { include | exclude } ] [ source_list SOURCE_LIST ] [ proto PROTO ] [ dst IPADDR ]\n"
" [ dst_port DST_PORT ] [ vni VNI ] [ src_vni SRC_VNI ] [ via DEV ]\n"
@@ -40,7 +40,7 @@ static void usage(void)
" bridge mdb get dev DEV grp GROUP [ src SOURCE ] [ vid VID ] [ src_vni SRC_VNI ]\n"
" bridge mdb flush dev DEV [ port PORT ] [ vid VID ] [ src_vni SRC_VNI ] [ proto PROTO ]\n"
" [ [no]permanent ] [ dst IPADDR ] [ dst_port DST_PORT ] [ vni VNI ]\n");
- exit(-1);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static bool is_temp_mcast_rtr(__u8 type)
@@ -764,7 +764,7 @@ static int mdb_modify(int cmd, int flags, int argc, char **argv)
set_attrs = true;
} else {
if (matches(*argv, "help") == 0)
- usage();
+ usage(true);
}
argc--; argv++;
}
@@ -891,7 +891,7 @@ static int mdb_get(int argc, char **argv)
get_attrs = true;
} else {
if (strcmp(*argv, "help") == 0)
- usage();
+ usage(true);
}
argc--; argv++;
}
@@ -1005,7 +1005,7 @@ static int mdb_flush(int argc, char **argv)
set_attrs = true;
} else {
if (strcmp(*argv, "help") == 0)
- usage();
+ usage(true);
}
argc--; argv++;
}
@@ -1099,7 +1099,7 @@ int do_mdb(int argc, char **argv)
if (strcmp(*argv, "flush") == 0)
return mdb_flush(argc-1, argv+1);
if (matches(*argv, "help") == 0)
- usage();
+ usage(true);
} else
return mdb_show(0, NULL);
diff --git a/bridge/monitor.c b/bridge/monitor.c
index 552614d7..ac7ade23 100644
--- a/bridge/monitor.c
+++ b/bridge/monitor.c
@@ -21,13 +21,14 @@
#include "br_common.h"
-static void usage(void) __attribute__((noreturn));
+static void usage(bool help) __attribute__((noreturn));
static int prefix_banner;
-static void usage(void)
+static void usage(bool help)
{
- fprintf(stderr, "Usage: bridge monitor [file | link | fdb | mdb | vlan | vni | all]\n");
- exit(-1);
+ fprintf(help ? stdout : stderr,
+ "Usage: bridge monitor [file | link | fdb | mdb | vlan | vni | all]\n");
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static int accept_msg(struct rtnl_ctrl_data *ctrl,
@@ -111,7 +112,7 @@ int do_monitor(int argc, char **argv)
lvni = 1;
prefix_banner = 1;
} else if (matches(*argv, "help") == 0) {
- usage();
+ usage(true);
} else {
fprintf(stderr, "Argument \"%s\" is unknown, try \"bridge monitor help\".\n", *argv);
exit(-1);
diff --git a/bridge/mst.c b/bridge/mst.c
index df242c9d..e1c5d141 100644
--- a/bridge/mst.c
+++ b/bridge/mst.c
@@ -22,12 +22,12 @@
static unsigned int filter_index;
-static void usage(void)
+static void usage(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: bridge mst set dev DEV msti MSTI state STATE\n"
" bridge mst {show} [ dev DEV ]\n");
- exit(-1);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static void print_mst_entry(struct rtattr *a, FILE *fp)
@@ -190,7 +190,7 @@ static int mst_set(int argc, char **argv)
s = *argv;
} else {
if (matches(*argv, "help") == 0)
- usage();
+ usage(true);
}
argc--; argv++;
}
@@ -254,7 +254,7 @@ int do_mst(int argc, char **argv)
matches(*argv, "list") == 0)
return mst_show(argc-1, argv+1);
if (matches(*argv, "help") == 0)
- usage();
+ usage(true);
} else
return mst_show(0, NULL);
diff --git a/bridge/vlan.c b/bridge/vlan.c
index ff03ac86..a3628bce 100644
--- a/bridge/vlan.c
+++ b/bridge/vlan.c
@@ -29,9 +29,9 @@ enum vlan_show_subject {
#define VLAN_ID_LEN 9
-static void usage(void)
+static void usage(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: bridge vlan { add | del } vid VLAN_ID dev DEV [ tunnel_info id TUNNEL_ID ]\n"
" [ pvid ] [ untagged ]\n"
" [ self ] [ master ]\n"
@@ -57,7 +57,7 @@ static void usage(void)
" [ mcast_query_response_interval QUERY_RESPONSE_INTERVAL ]\n"
" [ msti MSTI ]\n"
" bridge vlan global { show } [ dev DEV ] [ vid VLAN_ID ]\n");
- exit(-1);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static int parse_tunnel_info(int *argcp, char ***argvp, __u32 *tun_id_start,
@@ -1332,7 +1332,7 @@ static int vlan_global(int argc, char **argv)
else if (strcmp(*argv, "set") == 0)
return vlan_global_option_set(argc-1, argv+1);
else
- usage();
+ usage(matches(*argv, "help") == 0);
} else {
return vlan_global_show(0, NULL);
}
@@ -1362,7 +1362,7 @@ int do_vlan(int argc, char **argv)
if (strcmp(*argv, "global") == 0)
return vlan_global(argc-1, argv+1);
if (matches(*argv, "help") == 0)
- usage();
+ usage(true);
} else {
return vlan_show(0, NULL, VLAN_SHOW_VLAN);
}
diff --git a/bridge/vni.c b/bridge/vni.c
index b28647fd..7a4c0084 100644
--- a/bridge/vni.c
+++ b/bridge/vni.c
@@ -27,9 +27,9 @@ static unsigned int filter_index;
/* max len of "<start>-<end>" */
#define VXLAN_ID_LEN 17
-static void usage(void)
+static void usage(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: bridge vni { add | del } vni VNI\n"
" [ { group | remote } IP_ADDRESS ]\n"
" dev DEV\n"
@@ -37,7 +37,7 @@ static void usage(void)
"\n"
"Where: VNI := 0-16777215\n"
);
- exit(-1);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static int parse_vni_filter(const char *argv, struct nlmsghdr *n, int reqsize,
@@ -121,7 +121,7 @@ static int vni_modify(int cmd, int argc, char **argv)
daddr_present = true;
} else {
if (strcmp(*argv, "help") == 0)
- usage();
+ usage(true);
}
argc--; argv++;
}
@@ -399,7 +399,7 @@ int do_vni(int argc, char **argv)
strcmp(*argv, "list") == 0)
return vni_show(argc-1, argv+1);
if (strcmp(*argv, "help") == 0)
- usage();
+ usage(true);
} else {
return vni_show(0, NULL);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH iproute2-next 6/7] genl: put help to stdout and usage to stderr
2026-08-07 15:42 [PATCH iproute2-next 0/7] cleanup help and exit codes Stephen Hemminger
` (4 preceding siblings ...)
2026-08-07 15:42 ` [PATCH iproute2-next 5/7] bridge: " Stephen Hemminger
@ 2026-08-07 15:42 ` Stephen Hemminger
2026-08-07 15:42 ` [PATCH iproute2-next 7/7] tc: " Stephen Hemminger
6 siblings, 0 replies; 8+ messages in thread
From: Stephen Hemminger @ 2026-08-07 15:42 UTC (permalink / raw)
To: netdev; +Cc: dsahern, Stephen Hemminger
Similar change to other iproute2 commands.
Syntax error should print to stderr and exit with non-zero.
Help command should print to stdout and exit with zero status.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
genl/genl.c | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/genl/genl.c b/genl/genl.c
index b497a3ad..27b679df 100644
--- a/genl/genl.c
+++ b/genl/genl.c
@@ -7,6 +7,8 @@
#include <stdio.h>
#include <stdlib.h>
+#include <stdbool.h>
+#include <stddef.h>
#include <unistd.h>
#include <fcntl.h>
#include <dlfcn.h>
@@ -90,16 +92,16 @@ noexist:
return f;
}
-static void usage(void) __attribute__((noreturn));
+static void usage(bool help) __attribute__((noreturn));
-static void usage(void)
+static void usage(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: genl [ OPTIONS ] OBJECT [help] }\n"
"where OBJECT := { ctrl etc }\n"
" OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] | -r[aw] |\n"
" -j[son] | -p[retty] }\n");
- exit(-1);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
int main(int argc, char **argv)
@@ -122,7 +124,7 @@ int main(int argc, char **argv)
} else if (matches(argv[1], "-pretty") == 0) {
++pretty;
} else if (matches(argv[1], "-help") == 0) {
- usage();
+ usage(true);
} else {
fprintf(stderr,
"Option \"%s\" is unknown, try \"genl -help\".\n",
@@ -146,5 +148,5 @@ int main(int argc, char **argv)
return ret;
}
- usage();
+ usage(true);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH iproute2-next 7/7] tc: put help to stdout and usage to stderr
2026-08-07 15:42 [PATCH iproute2-next 0/7] cleanup help and exit codes Stephen Hemminger
` (5 preceding siblings ...)
2026-08-07 15:42 ` [PATCH iproute2-next 6/7] genl: " Stephen Hemminger
@ 2026-08-07 15:42 ` Stephen Hemminger
6 siblings, 0 replies; 8+ messages in thread
From: Stephen Hemminger @ 2026-08-07 15:42 UTC (permalink / raw)
To: netdev; +Cc: dsahern, Stephen Hemminger
Similar change to other iproute2 commands.
Syntax error should print to stderr and exit with non-zero.
Help command should print to stdout and exit with zero status.
The qdisc, class and filter parsers used to print the usage message
and then carry on and execute the command; asking for help now stops
before the command is run. Add the missing help keyword to the htb
qdisc, sfb, ingress and clsact parsers, and handle it in the gact and
nat actions where it was being eaten by the argument parser.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
tc/e_bpf.c | 15 ++++++++++-----
tc/f_basic.c | 12 +++++++-----
tc/f_bpf.c | 12 +++++++-----
tc/f_cgroup.c | 16 ++++++++++------
tc/f_flow.c | 12 +++++++-----
tc/f_flower.c | 13 +++++++++----
tc/f_fw.c | 12 +++++++-----
tc/f_matchall.c | 12 +++++++-----
tc/f_route.c | 12 +++++++-----
tc/f_u32.c | 12 +++++++-----
tc/m_action.c | 23 ++++++++++-------------
tc/m_bpf.c | 10 ++++++----
tc/m_connmark.c | 16 +++++++++-------
tc/m_csum.c | 18 ++++++++++--------
tc/m_ct.c | 12 +++++++-----
tc/m_ctinfo.c | 16 +++++++++-------
tc/m_estimator.c | 12 +++++++-----
tc/m_gact.c | 27 ++++++++++++++++-----------
tc/m_gate.c | 14 ++++++++------
tc/m_ife.c | 16 +++++++++-------
tc/m_mirred.c | 14 ++++++++------
tc/m_mpls.c | 16 +++++++++-------
tc/m_nat.c | 22 +++++++++++++---------
tc/m_pedit.c | 22 ++++++++++++----------
tc/m_police.c | 10 ++++++----
tc/m_sample.c | 24 +++++++++++++-----------
tc/m_simple.c | 16 +++++++++-------
tc/m_skbedit.c | 17 ++++++++++-------
tc/m_skbmod.c | 16 +++++++++-------
tc/m_tunnel_key.c | 20 +++++++++++---------
tc/m_vlan.c | 24 +++++++++++++-----------
tc/q_cake.c | 12 +++++++-----
tc/q_cbs.c | 12 +++++++-----
tc/q_choke.c | 12 +++++++-----
tc/q_clsact.c | 14 ++++++++++----
tc/q_codel.c | 12 +++++++-----
tc/q_drr.c | 24 ++++++++++++++----------
tc/q_dualpi2.c | 38 +++++++++++++++++++++-----------------
tc/q_etf.c | 12 +++++++-----
tc/q_ets.c | 29 +++++++++++++++++------------
tc/q_fifo.c | 13 ++++++++-----
tc/q_fq.c | 12 +++++++-----
tc/q_fq_codel.c | 12 +++++++-----
tc/q_fq_pie.c | 12 +++++++-----
tc/q_gred.c | 19 ++++++++++---------
tc/q_hfsc.c | 28 ++++++++++++++++------------
tc/q_hhf.c | 12 +++++++-----
tc/q_htb.c | 19 ++++++++++++-------
tc/q_ingress.c | 14 ++++++++++----
tc/q_mqprio.c | 10 ++++++----
tc/q_multiq.c | 12 +++++++-----
tc/q_netem.c | 21 +++++++++++++--------
tc/q_pie.c | 12 +++++++-----
tc/q_plug.c | 13 ++++++++-----
tc/q_prio.c | 15 +++++++++------
tc/q_qfq.c | 26 +++++++++++++++++---------
tc/q_red.c | 12 +++++++-----
tc/q_sfb.c | 14 ++++++++++----
tc/q_sfq.c | 12 +++++++-----
tc/q_skbprio.c | 13 ++++++++-----
tc/q_taprio.c | 10 ++++++----
tc/q_tbf.c | 14 ++++++++------
tc/tc.c | 12 ++++++------
tc/tc_class.c | 20 ++++++++++++--------
tc/tc_exec.c | 6 +++---
tc/tc_filter.c | 31 ++++++++++++++++++-------------
tc/tc_monitor.c | 11 ++++++-----
tc/tc_qdisc.c | 14 +++++++-------
tc/tc_stab.c | 13 +++++++------
69 files changed, 635 insertions(+), 455 deletions(-)
diff --git a/tc/e_bpf.c b/tc/e_bpf.c
index cca853f9..113b0341 100644
--- a/tc/e_bpf.c
+++ b/tc/e_bpf.c
@@ -20,9 +20,9 @@
static char *argv_default[] = { BPF_DEFAULT_CMD, NULL };
-static void explain(void)
+static void explain(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ... bpf [ import UDS_FILE ] [ run CMD ]\n"
" ... bpf [ debug ]\n"
" ... bpf [ graft MAP_FILE ] [ key KEY ]\n"
@@ -37,6 +37,9 @@ static void explain(void)
"\'cls\' is default. KEY is optional and can be inferred from the\n"
"section name, otherwise it needs to be provided.\n",
BPF_DEFAULT_CMD);
+
+ if (help)
+ exit(EXIT_SUCCESS);
}
static int bpf_num_env_entries(void)
@@ -94,7 +97,9 @@ static int parse_bpf(const struct exec_util *eu, int argc, char **argv)
return bpf_graft_map(bpf_map_path, has_key ?
&key : NULL, argc, argv);
} else {
- explain();
+ bool help = strcmp(*argv, "help") == 0;
+
+ explain(help);
return -1;
}
@@ -103,13 +108,13 @@ static int parse_bpf(const struct exec_util *eu, int argc, char **argv)
if (!bpf_uds_name) {
fprintf(stderr, "bpf: No import parameter provided!\n");
- explain();
+ explain(false);
return -1;
}
if (argv_run != argv_default && argc == 0) {
fprintf(stderr, "bpf: No run command provided!\n");
- explain();
+ explain(false);
return -1;
}
diff --git a/tc/f_basic.c b/tc/f_basic.c
index eac9d19a..29916e72 100644
--- a/tc/f_basic.c
+++ b/tc/f_basic.c
@@ -19,9 +19,9 @@
#include "tc_util.h"
#include "m_ematch.h"
-static void explain(void)
+static void explain(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ... basic [ match EMATCH_TREE ]\n"
" [ action ACTION_SPEC ] [ classid CLASSID ]\n"
"\n"
@@ -30,6 +30,9 @@ static void explain(void)
" ACTION_SPEC := ... look at individual actions\n"
"\n"
"NOTE: CLASSID is parsed as hexadecimal input.\n");
+
+ if (help)
+ exit(EXIT_SUCCESS);
}
static int basic_parse_opt(const struct filter_util *qu, char *handle,
@@ -89,11 +92,10 @@ static int basic_parse_opt(const struct filter_util *qu, char *handle,
}
continue;
} else if (strcmp(*argv, "help") == 0) {
- explain();
- return -1;
+ explain(true);
} else {
fprintf(stderr, "What is \"%s\"?\n", *argv);
- explain();
+ explain(false);
return -1;
}
argc--; argv++;
diff --git a/tc/f_bpf.c b/tc/f_bpf.c
index 50fe01ca..c19114c7 100644
--- a/tc/f_bpf.c
+++ b/tc/f_bpf.c
@@ -17,9 +17,9 @@
static const enum bpf_prog_type bpf_type = BPF_PROG_TYPE_SCHED_CLS;
-static void explain(void)
+static void explain(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ... bpf ...\n"
"\n"
"BPF use case:\n"
@@ -51,6 +51,9 @@ static void explain(void)
"ACTION_SPEC := ... look at individual actions\n"
"NOTE: CLASSID is parsed as hexadecimal input.\n",
bpf_prog_to_default_section(bpf_type));
+
+ if (help)
+ exit(EXIT_SUCCESS);
}
static void bpf_cbpf_cb(void *nl, const struct sock_filter *ops, int ops_len)
@@ -153,14 +156,13 @@ opt_bpf:
}
continue;
} else if (matches(*argv, "help") == 0) {
- explain();
- return -1;
+ explain(true);
} else {
if (!seen_run)
goto opt_bpf;
fprintf(stderr, "What is \"%s\"?\n", *argv);
- explain();
+ explain(false);
return -1;
}
diff --git a/tc/f_cgroup.c b/tc/f_cgroup.c
index 9b94b62e..3828f429 100644
--- a/tc/f_cgroup.c
+++ b/tc/f_cgroup.c
@@ -11,10 +11,15 @@
#include "tc_util.h"
#include "m_ematch.h"
-static void explain(void)
+static void explain(bool help)
{
- fprintf(stderr, "Usage: ... cgroup [ match EMATCH_TREE ]\n");
- fprintf(stderr, " [ action ACTION_SPEC ]\n");
+ fprintf(help ? stdout : stderr,
+ "Usage: ... cgroup [ match EMATCH_TREE ]\n");
+ fprintf(help ? stdout : stderr,
+ " [ action ACTION_SPEC ]\n");
+
+ if (help)
+ exit(EXIT_SUCCESS);
}
static int cgroup_parse_opt(const struct filter_util *qu, char *handle,
@@ -62,11 +67,10 @@ static int cgroup_parse_opt(const struct filter_util *qu, char *handle,
}
continue;
} else if (strcmp(*argv, "help") == 0) {
- explain();
- return -1;
+ explain(true);
} else {
fprintf(stderr, "What is \"%s\"?\n", *argv);
- explain();
+ explain(false);
return -1;
}
}
diff --git a/tc/f_flow.c b/tc/f_flow.c
index 1a1faa90..4cdf6735 100644
--- a/tc/f_flow.c
+++ b/tc/f_flow.c
@@ -14,9 +14,9 @@
#include "tc_util.h"
#include "m_ematch.h"
-static void explain(void)
+static void explain(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ... flow ...\n"
"\n"
" [mapping mode]: map key KEY [ OPS ] ...\n"
@@ -33,6 +33,9 @@ static void explain(void)
"OPS := [ or NUM | and NUM | xor NUM | rshift NUM | addend NUM ]\n"
"ID := X:Y\n"
);
+
+ if (help)
+ exit(EXIT_SUCCESS);
}
static const char *flow_keys[FLOW_KEY_MAX+1] = {
@@ -233,11 +236,10 @@ static int flow_parse_opt(const struct filter_util *fu, char *handle,
}
continue;
} else if (matches(*argv, "help") == 0) {
- explain();
- return -1;
+ explain(true);
} else {
fprintf(stderr, "What is \"%s\"?\n", *argv);
- explain();
+ explain(false);
return -1;
}
argv++, argc--;
diff --git a/tc/f_flower.c b/tc/f_flower.c
index 6fc2c6a1..d44ebd72 100644
--- a/tc/f_flower.c
+++ b/tc/f_flower.c
@@ -44,9 +44,9 @@ enum flower_icmp_field {
FLOWER_ICMP_FIELD_CODE
};
-static void explain(void)
+static void explain(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ... flower [ MATCH-LIST ] [ verbose ]\n"
" [ skip_sw | skip_hw ]\n"
" [ action ACTION-SPEC ] [ classid CLASSID ]\n"
@@ -118,6 +118,9 @@ static void explain(void)
"NOTE: CLASSID, IP-PROTO are parsed as hexadecimal input.\n"
"NOTE: There can be only used one mask per one prio. If user needs\n"
" to specify different mask, he has to use different prio.\n");
+
+ if (help)
+ exit(EXIT_SUCCESS);
}
/* prints newline, two spaces, name/value */
@@ -2287,9 +2290,11 @@ static int flower_parse_opt(const struct filter_util *qu, char *handle,
return -1;
continue;
} else {
- if (strcmp(*argv, "help") != 0)
+ bool help = strcmp(*argv, "help") == 0;
+
+ if (!help)
fprintf(stderr, "What is \"%s\"?\n", *argv);
- explain();
+ explain(help);
return -1;
}
argc--; argv++;
diff --git a/tc/f_fw.c b/tc/f_fw.c
index c9b4e179..bba934a7 100644
--- a/tc/f_fw.c
+++ b/tc/f_fw.c
@@ -17,9 +17,9 @@
#include "utils.h"
#include "tc_util.h"
-static void explain(void)
+static void explain(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ... fw [ classid CLASSID ] [ indev DEV ] [ action ACTION_SPEC ]\n"
" CLASSID := Push matching packets to the class identified by CLASSID with format X:Y\n"
" CLASSID is parsed as hexadecimal input.\n"
@@ -27,6 +27,9 @@ static void explain(void)
" ACTION_SPEC := Apply an action on matching packets.\n"
" NOTE: handle is represented as HANDLE[/FWMASK].\n"
" FWMASK is 0xffffffff by default.\n");
+
+ if (help)
+ exit(EXIT_SUCCESS);
}
static int fw_parse_opt(const struct filter_util *qu, char *handle, int argc, char **argv, struct nlmsghdr *n)
@@ -99,11 +102,10 @@ static int fw_parse_opt(const struct filter_util *qu, char *handle, int argc, ch
strncpy(d, *argv, sizeof(d) - 1);
addattr_l(n, MAX_MSG, TCA_FW_INDEV, d, strlen(d) + 1);
} else if (strcmp(*argv, "help") == 0) {
- explain();
- return -1;
+ explain(true);
} else {
fprintf(stderr, "What is \"%s\"?\n", *argv);
- explain();
+ explain(false);
return -1;
}
argc--; argv++;
diff --git a/tc/f_matchall.c b/tc/f_matchall.c
index e595ac38..29e7369a 100644
--- a/tc/f_matchall.c
+++ b/tc/f_matchall.c
@@ -18,9 +18,9 @@
#include "utils.h"
#include "tc_util.h"
-static void explain(void)
+static void explain(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ... matchall [skip_sw | skip_hw]\n"
" [ action ACTION_SPEC ] [ classid CLASSID ]\n"
"\n"
@@ -29,6 +29,9 @@ static void explain(void)
" ACTION_SPEC := ... look at individual actions\n"
"\n"
"NOTE: CLASSID is parsed as hexadecimal input.\n");
+
+ if (help)
+ exit(EXIT_SUCCESS);
}
static int matchall_parse_opt(const struct filter_util *qu, char *handle,
@@ -83,11 +86,10 @@ static int matchall_parse_opt(const struct filter_util *qu, char *handle,
flags |= TCA_CLS_FLAGS_SKIP_SW;
continue;
} else if (strcmp(*argv, "help") == 0) {
- explain();
- return -1;
+ explain(true);
} else {
fprintf(stderr, "What is \"%s\"?\n", *argv);
- explain();
+ explain(false);
return -1;
}
argc--; argv++;
diff --git a/tc/f_route.c b/tc/f_route.c
index c234ddf0..08f5fab3 100644
--- a/tc/f_route.c
+++ b/tc/f_route.c
@@ -19,15 +19,18 @@
#include "tc_common.h"
#include "tc_util.h"
-static void explain(void)
+static void explain(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ... route [ from REALM | fromif TAG ] [ to REALM ]\n"
" [ classid CLASSID ] [ action ACTION_SPEC ]\n"
" ACTION_SPEC := ... look at individual actions\n"
" CLASSID := X:Y\n"
"\n"
"NOTE: CLASSID is parsed as hexadecimal input.\n");
+
+ if (help)
+ exit(EXIT_SUCCESS);
}
static int route_parse_opt(const struct filter_util *qu, char *handle, int argc, char **argv, struct nlmsghdr *n)
@@ -114,11 +117,10 @@ static int route_parse_opt(const struct filter_util *qu, char *handle, int argc,
return -1;
}
} else if (strcmp(*argv, "help") == 0) {
- explain();
- return -1;
+ explain(true);
} else {
fprintf(stderr, "What is \"%s\"?\n", *argv);
- explain();
+ explain(false);
return -1;
}
argc--; argv++;
diff --git a/tc/f_u32.c b/tc/f_u32.c
index 088d744e..083f1af6 100644
--- a/tc/f_u32.c
+++ b/tc/f_u32.c
@@ -22,9 +22,9 @@
#include "utils.h"
#include "tc_util.h"
-static void explain(void)
+static void explain(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ... u32 [ match SELECTOR ... ] [ link HTID ] [ classid CLASSID ]\n"
" [ action ACTION_SPEC ] [ offset OFFSET_SPEC ]\n"
" [ ht HTID ] [ hashkey HASHKEY_SPEC ]\n"
@@ -36,6 +36,9 @@ static void explain(void)
" SAMPLE_ARGS [ divisor DIVISOR ]\n"
" FILTERID := X:Y:Z\n"
"\nNOTE: CLASSID is parsed at hexadecimal input.\n");
+
+ if (help)
+ exit(EXIT_SUCCESS);
}
static int get_u32_handle(__u32 *handle, const char *str)
@@ -1189,11 +1192,10 @@ static int u32_parse_opt(const struct filter_util *qu, char *handle,
} else if (strcmp(*argv, "skip_sw") == 0) {
flags |= TCA_CLS_FLAGS_SKIP_SW;
} else if (strcmp(*argv, "help") == 0) {
- explain();
- return -1;
+ explain(true);
} else {
fprintf(stderr, "What is \"%s\"?\n", *argv);
- explain();
+ explain(false);
return -1;
}
argc--; argv++;
diff --git a/tc/m_action.c b/tc/m_action.c
index bbc8e6a6..b75c1bfa 100644
--- a/tc/m_action.c
+++ b/tc/m_action.c
@@ -30,7 +30,9 @@ static int gact_ld; /* f*ckin backward compatibility */
#endif
static int tab_flush;
-static void act_usage(void)
+static void act_usage(bool help) __attribute__((noreturn));
+
+static void act_usage(bool help)
{
/*XXX: In the near future add a action->print_help to improve
* usability
@@ -39,7 +41,7 @@ static void act_usage(void)
* does that, they would know how to fix this ..
*
*/
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"usage: tc actions <ACTSPECOP>*\n"
"Where: ACTSPECOP := ACR | GD | FL\n"
" ACR := add | change | replace <ACTSPEC>*\n"
@@ -56,7 +58,7 @@ static void act_usage(void)
" Each action has its own parameters (ACTPARAMS)\n"
"\n");
- exit(-1);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static int print_noaopt(const struct action_util *au, FILE *f, struct rtattr *opt)
@@ -893,28 +895,23 @@ int do_action(int argc, char **argv)
} else if (matches(*argv, "list") == 0 ||
matches(*argv, "show") == 0 ||
matches(*argv, "lst") == 0) {
- if (argc <= 2) {
- act_usage();
- return -1;
- }
+ if (argc <= 2)
+ act_usage(false);
argc -= 2;
argv += 2;
return tc_act_list_or_flush(&argc, &argv,
RTM_GETACTION);
} else if (matches(*argv, "flush") == 0) {
- if (argc <= 2) {
- act_usage();
- return -1;
- }
+ if (argc <= 2)
+ act_usage(false);
argc -= 2;
argv += 2;
return tc_act_list_or_flush(&argc, &argv,
RTM_DELACTION);
} else if (matches(*argv, "help") == 0) {
- act_usage();
- return -1;
+ act_usage(true);
} else {
fprintf(stderr,
"Command \"%s\" is unknown, try \"tc actions help\".\n",
diff --git a/tc/m_bpf.c b/tc/m_bpf.c
index 83b21b57..0653fda2 100644
--- a/tc/m_bpf.c
+++ b/tc/m_bpf.c
@@ -19,9 +19,9 @@
static const enum bpf_prog_type bpf_type = BPF_PROG_TYPE_SCHED_ACT;
-static void explain(void)
+static void explain(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ... bpf ... [ index INDEX ]\n"
"\n"
"BPF use case:\n"
@@ -49,6 +49,9 @@ static void explain(void)
"Where optionally INDEX points to an existing action, or\n"
"explicitly specifies an action index upon creation.\n",
bpf_prog_to_default_section(bpf_type));
+
+ if (help)
+ exit(EXIT_SUCCESS);
}
static void bpf_cbpf_cb(void *nl, const struct sock_filter *ops, int ops_len)
@@ -111,8 +114,7 @@ opt_bpf:
bpf_obj = cfg.object;
bpf_uds_name = cfg.uds;
} else if (matches(*argv, "help") == 0) {
- explain();
- return -1;
+ explain(true);
} else if (matches(*argv, "index") == 0) {
break;
} else {
diff --git a/tc/m_connmark.c b/tc/m_connmark.c
index fa5ae79b..c7c63d83 100644
--- a/tc/m_connmark.c
+++ b/tc/m_connmark.c
@@ -14,9 +14,9 @@
#include <linux/tc_act/tc_connmark.h>
static void
-explain(void)
+explain(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ... connmark [zone ZONE] [CONTROL] [index <INDEX>]\n"
"where :\n"
"\tZONE is the conntrack zone\n"
@@ -24,11 +24,13 @@ explain(void)
"\t goto chain <CHAIN_INDEX>\n");
}
+static void usage(bool help) __attribute__((noreturn));
+
static void
-usage(void)
+usage(bool help)
{
- explain();
- exit(-1);
+ explain(help);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static int
@@ -47,7 +49,7 @@ parse_connmark(const struct action_util *a, int *argc_p, char ***argv_p, int tca
argc--;
argv++;
} else if (matches(*argv, "help") == 0) {
- usage();
+ usage(true);
} else {
break;
}
@@ -55,7 +57,7 @@ parse_connmark(const struct action_util *a, int *argc_p, char ***argv_p, int tca
}
if (!ok) {
- explain();
+ explain(false);
return -1;
}
diff --git a/tc/m_csum.c b/tc/m_csum.c
index f558d979..afb41e55 100644
--- a/tc/m_csum.c
+++ b/tc/m_csum.c
@@ -16,19 +16,21 @@
#include "tc_util.h"
static void
-explain(void)
+explain(bool help)
{
- fprintf(stderr, "Usage: ... csum <UPDATE>\n"
+ fprintf(help ? stdout : stderr, "Usage: ... csum <UPDATE>\n"
"Where: UPDATE := <TARGET> [<UPDATE>]\n"
" TARGET := { ip4h | icmp | igmp | tcp | udp | udplite | sctp | <SWEETS> }\n"
" SWEETS := { and | or | \'+\' }\n");
}
+static void usage(bool help) __attribute__((noreturn));
+
static void
-usage(void)
+usage(bool help)
{
- explain();
- exit(-1);
+ explain(help);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static int
@@ -99,20 +101,20 @@ parse_csum(const struct action_util *a, int *argc_p,
} else if (parse_csum_args(&argc, &argv, &sel)) {
fprintf(stderr, "Illegal csum construct (%s)\n",
*argv);
- explain();
+ explain(false);
return -1;
}
ok++;
continue;
} else if (matches(*argv, "help") == 0) {
- usage();
+ usage(true);
} else {
break;
}
}
if (!ok) {
- explain();
+ explain(false);
return -1;
}
diff --git a/tc/m_ct.c b/tc/m_ct.c
index e549cb9c..12045cf5 100644
--- a/tc/m_ct.c
+++ b/tc/m_ct.c
@@ -16,10 +16,12 @@
#include "rt_names.h"
#include <linux/tc_act/tc_ct.h>
+static void usage(bool help) __attribute__((noreturn));
+
static void
-usage(void)
+usage(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ct clear\n"
" ct commit [force] [zone ZONE] [mark MASKED_MARK] [label MASKED_LABEL] [nat NAT_SPEC] [helper HELPER]\n"
" ct [nat] [zone ZONE]\n"
@@ -27,7 +29,7 @@ usage(void)
" NAT_SPEC is {src|dst} addr addr1[-addr2] [port port1[-port2]]\n"
" HELPER is family-proto-name such as ipv4-tcp-ftp\n"
"\n");
- exit(-1);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static int ct_parse_nat_addr_range(const char *str, struct nlmsghdr *n)
@@ -262,7 +264,7 @@ parse_ct(const struct action_util *a, int *argc_p, char ***argv_p, int tca_id,
NEXT_ARG();
if (matches(*argv, "addr") != 0)
- usage();
+ usage(false);
NEXT_ARG();
ret = ct_parse_nat_addr_range(*argv, n);
@@ -310,7 +312,7 @@ parse_ct(const struct action_util *a, int *argc_p, char ***argv_p, int tca_id,
return -1;
}
} else if (matches(*argv, "help") == 0) {
- usage();
+ usage(true);
} else if (matches(*argv, "helper") == 0) {
NEXT_ARG();
diff --git a/tc/m_ctinfo.c b/tc/m_ctinfo.c
index 41449c11..bfd77cea 100644
--- a/tc/m_ctinfo.c
+++ b/tc/m_ctinfo.c
@@ -14,9 +14,9 @@
#include <linux/tc_act/tc_ctinfo.h>
static void
-explain(void)
+explain(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ... ctinfo [dscp mask [statemask]] [cpmark [mask]] [zone ZONE] [CONTROL] [index <INDEX>]\n"
"where :\n"
"\tdscp MASK bitmask location of stored DSCP\n"
@@ -27,11 +27,13 @@ explain(void)
"\t goto chain <CHAIN_INDEX>\n");
}
+static void usage(bool help) __attribute__((noreturn));
+
static void
-usage(void)
+usage(bool help)
{
- explain();
- exit(-1);
+ explain(help);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static int
@@ -52,7 +54,7 @@ parse_ctinfo(const struct action_util *a, int *argc_p, char ***argv_p, int tca_i
ok = 1;
NEXT_ARG_FWD();
} else if (matches(*argv, "help") == 0) {
- usage();
+ usage(true);
} else {
break;
}
@@ -60,7 +62,7 @@ parse_ctinfo(const struct action_util *a, int *argc_p, char ***argv_p, int tca_i
}
if (!ok) {
- explain();
+ explain(false);
return -1;
}
diff --git a/tc/m_estimator.c b/tc/m_estimator.c
index 98fc5e73..efceb067 100644
--- a/tc/m_estimator.c
+++ b/tc/m_estimator.c
@@ -18,15 +18,17 @@
#include "tc_util.h"
#include "tc_common.h"
-static void est_help(void);
+static void est_help(bool help) __attribute__((noreturn));
-static void est_help(void)
+static void est_help(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ... estimator INTERVAL TIME-CONST\n"
" INTERVAL is interval between measurements\n"
" TIME-CONST is averaging time constant\n"
"Example: ... est 1sec 8sec\n");
+
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
int parse_estimator(int *p_argc, char ***p_argv, struct tc_estimator *est)
@@ -39,12 +41,12 @@ int parse_estimator(int *p_argc, char ***p_argv, struct tc_estimator *est)
if (est->ewma_log)
duparg("estimator", *argv);
if (matches(*argv, "help") == 0)
- est_help();
+ est_help(true);
if (get_time(&A, *argv))
invarg("estimator", "invalid estimator interval");
NEXT_ARG();
if (matches(*argv, "help") == 0)
- est_help();
+ est_help(true);
if (get_time(&time_const, *argv))
invarg("estimator", "invalid estimator time constant");
if (tc_setup_estimator(A, time_const, est) < 0) {
diff --git a/tc/m_gact.c b/tc/m_gact.c
index 854d823e..1b003de4 100644
--- a/tc/m_gact.c
+++ b/tc/m_gact.c
@@ -34,11 +34,12 @@ static const char *prob_n2a(int p)
#endif
static void
-explain(void)
+explain(bool help)
{
+ FILE *fp = help ? stdout : stderr;
#ifdef CONFIG_GACT_PROB
- fprintf(stderr, "Usage: ... gact <ACTION> [RAND] [INDEX]\n");
- fprintf(stderr,
+ fprintf(fp, "Usage: ... gact <ACTION> [RAND] [INDEX]\n");
+ fprintf(fp,
"Where: \tACTION := reclassify | drop | continue | pass | pipe |\n"
" \t goto chain <CHAIN_INDEX> | jump <JUMP_COUNT>\n"
"\tRAND := random <RANDTYPE> <ACTION> <VAL>\n"
@@ -48,7 +49,7 @@ explain(void)
"\tINDEX := index value used\n"
"\n");
#else
- fprintf(stderr, "Usage: ... gact <ACTION> [INDEX]\n"
+ fprintf(fp, "Usage: ... gact <ACTION> [INDEX]\n"
"Where: \tACTION := reclassify | drop | continue | pass | pipe |\n"
" \t goto chain <CHAIN_INDEX> | jump <JUMP_COUNT>\n"
"\tINDEX := index value used\n"
@@ -58,11 +59,13 @@ explain(void)
}
+static void usage(bool help) __attribute__((noreturn));
+
static void
-usage(void)
+usage(bool help)
{
- explain();
- exit(-1);
+ explain(help);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static int
@@ -83,11 +86,13 @@ parse_gact(const struct action_util *a, int *argc_p, char ***argv_p,
if (!matches(*argv, "gact"))
NEXT_ARG();
+ if (matches(*argv, "help") == 0)
+ usage(true); /* does not return */
/* we're binding existing gact action to filter by index. */
if (!matches(*argv, "index"))
goto skip_args;
if (parse_action_control(&argc, &argv, &p.action, false))
- usage(); /* does not return */
+ usage(false); /* does not return */
#ifdef CONFIG_GACT_PROB
if (argc > 0) {
@@ -107,7 +112,7 @@ parse_gact(const struct action_util *a, int *argc_p, char ***argv_p,
if (parse_action_control(&argc, &argv,
&pp.paction, false) == -1)
- usage();
+ usage(false);
if (get_u16(&pp.pval, *argv, 10)) {
fprintf(stderr,
"Illegal probability val 0x%x\n",
@@ -123,7 +128,7 @@ parse_gact(const struct action_util *a, int *argc_p, char ***argv_p,
argc--;
argv++;
} else if (matches(*argv, "help") == 0) {
- usage();
+ usage(true);
}
}
#endif
@@ -139,7 +144,7 @@ skip_args:
argc--;
argv++;
} else if (matches(*argv, "help") == 0) {
- usage();
+ usage(true);
}
}
diff --git a/tc/m_gate.c b/tc/m_gate.c
index d71dd609..678a2e0b 100644
--- a/tc/m_gate.c
+++ b/tc/m_gate.c
@@ -20,9 +20,9 @@ struct gate_entry {
int32_t maxoctets;
};
-static void explain(void)
+static void explain(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: gate [ priority PRIO-SPEC ] [ base-time BASE-TIME ]\n"
" [ cycle-time CYCLE-TIME ]\n"
" [ cycle-time-ext CYCLE-TIME-EXT ]\n"
@@ -45,10 +45,12 @@ static void explain(void)
" goto chain <CHAIN_INDEX>\n");
}
-static void usage(void)
+static void usage(bool help) __attribute__((noreturn));
+
+static void usage(bool help)
{
- explain();
- exit(-1);
+ explain(help);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static void explain_entry_format(void)
@@ -304,7 +306,7 @@ create_entry:
list_add_tail(&e->list, &gate_entries);
entry_num++;
} else if (matches(*argv, "help") == 0) {
- usage();
+ usage(true);
} else {
break;
}
diff --git a/tc/m_ife.c b/tc/m_ife.c
index 90bc7a5b..cc7a8d74 100644
--- a/tc/m_ife.c
+++ b/tc/m_ife.c
@@ -20,9 +20,9 @@
#include "tc_util.h"
#include <linux/tc_act/tc_ife.h>
-static void ife_explain(void)
+static void ife_explain(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage:... ife {decode|encode} [{ALLOW|USE} ATTR] [dst DMAC] [src SMAC] [type TYPE] [CONTROL] [index INDEX]\n"
"\tALLOW := Encode direction. Allows encoding specified metadata\n"
"\t\t e.g \"allow mark\"\n"
@@ -38,10 +38,12 @@ static void ife_explain(void)
"decode is used for receiving IFE packets\n");
}
-static void ife_usage(void)
+static void ife_usage(bool help) __attribute__((noreturn));
+
+static void ife_usage(bool help)
{
- ife_explain();
- exit(-1);
+ ife_explain(help);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static int parse_ife(const struct action_util *a, int *argc_p, char ***argv_p,
@@ -136,7 +138,7 @@ static int parse_ife(const struct action_util *a, int *argc_p, char ***argv_p,
}
fprintf(stderr, "src MAC address <%s>\n", saddr);
} else if (matches(*argv, "help") == 0) {
- ife_usage();
+ ife_usage(true);
} else {
break;
}
@@ -162,7 +164,7 @@ static int parse_ife(const struct action_util *a, int *argc_p, char ***argv_p,
if (!ok) {
fprintf(stderr, "IFE requires decode/encode specified\n");
- ife_usage();
+ ife_usage(false);
}
tail = addattr_nest(n, MAX_MSG, tca_id);
diff --git a/tc/m_mirred.c b/tc/m_mirred.c
index e9ae5199..d148be3a 100644
--- a/tc/m_mirred.c
+++ b/tc/m_mirred.c
@@ -21,9 +21,9 @@
#include <linux/tc_act/tc_mirred.h>
static void
-explain(void)
+explain(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: mirred <DIRECTION> <ACTION> [index INDEX] <TARGET>\n"
"where:\n"
"\tDIRECTION := <ingress | egress>\n"
@@ -36,11 +36,13 @@ explain(void)
"\tBLOCKID := 32-bit unsigned block ID\n");
}
+static void usage(bool help) __attribute__((noreturn));
+
static void
-usage(void)
+usage(bool help)
{
- explain();
- exit(-1);
+ explain(help);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static const char *mirred_n2a(int action)
@@ -287,7 +289,7 @@ parse_mirred(const struct action_util *a, int *argc_p, char ***argv_p,
}
} else if (matches(*argv, "help") == 0) {
- usage();
+ usage(true);
} else {
fprintf(stderr, "mirred option not supported %s\n", *argv);
}
diff --git a/tc/m_mpls.c b/tc/m_mpls.c
index 89137456..e5055ce8 100644
--- a/tc/m_mpls.c
+++ b/tc/m_mpls.c
@@ -20,9 +20,9 @@ static const char * const action_names[] = {
[TCA_MPLS_ACT_MAC_PUSH] = "mac_push",
};
-static void explain(void)
+static void explain(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: mpls pop [ protocol MPLS_PROTO ] [CONTROL]\n"
" mpls push [ protocol MPLS_PROTO ] [ label MPLS_LABEL ] [ tc MPLS_TC ]\n"
" [ ttl MPLS_TTL ] [ bos MPLS_BOS ] [CONTROL]\n"
@@ -37,10 +37,12 @@ static void explain(void)
" goto chain <CHAIN_INDEX>\n");
}
-static void usage(void)
+static void usage(bool help) __attribute__((noreturn));
+
+static void usage(bool help)
{
- explain();
- exit(-1);
+ explain(help);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static bool can_modify_mpls_fields(unsigned int action)
@@ -68,7 +70,7 @@ static bool check_double_action(unsigned int action, const char *arg)
fprintf(stderr,
"Error: got \"%s\" but action already set to \"%s\"\n",
arg, action_names[action]);
- explain();
+ explain(false);
return true;
}
@@ -151,7 +153,7 @@ static int parse_mpls(const struct action_util *a, int *argc_p, char ***argv_p,
if (ll_proto_a2n(&proto, *argv))
invarg("protocol is invalid", *argv);
} else if (matches(*argv, "help") == 0) {
- usage();
+ usage(true);
} else {
break;
}
diff --git a/tc/m_nat.c b/tc/m_nat.c
index 0ec3fd11..69d79047 100644
--- a/tc/m_nat.c
+++ b/tc/m_nat.c
@@ -18,20 +18,22 @@
#include <linux/tc_act/tc_nat.h>
static void
-explain(void)
+explain(bool help)
{
- fprintf(stderr, "Usage: ... nat NAT\n"
+ fprintf(help ? stdout : stderr, "Usage: ... nat NAT\n"
"NAT := DIRECTION OLD NEW\n"
"DIRECTION := { ingress | egress }\n"
"OLD := PREFIX\n"
"NEW := ADDRESS\n");
}
+static void usage(bool help) __attribute__((noreturn));
+
static void
-usage(void)
+usage(bool help)
{
- explain();
- exit(-1);
+ explain(help);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static int
@@ -88,18 +90,20 @@ parse_nat(const struct action_util *a, int *argc_p, char ***argv_p, int tca_id,
while (argc > 0) {
if (matches(*argv, "nat") == 0) {
NEXT_ARG();
- if (strcmp(*argv, "index") == 0) {
+ if (matches(*argv, "help") == 0) {
+ usage(true);
+ } else if (strcmp(*argv, "index") == 0) {
goto skip_args;
} else if (parse_nat_args(&argc, &argv, &sel)) {
fprintf(stderr, "Illegal nat construct (%s)\n",
*argv);
- explain();
+ explain(false);
return -1;
}
ok++;
continue;
} else if (matches(*argv, "help") == 0) {
- usage();
+ usage(true);
} else {
break;
}
@@ -107,7 +111,7 @@ parse_nat(const struct action_util *a, int *argc_p, char ***argv_p, int tca_id,
}
if (!ok) {
- explain();
+ explain(false);
return -1;
}
diff --git a/tc/m_pedit.c b/tc/m_pedit.c
index 040d6168..5d8bf0df 100644
--- a/tc/m_pedit.c
+++ b/tc/m_pedit.c
@@ -27,9 +27,9 @@
static struct m_pedit_util *pedit_list;
static int pedit_debug;
-static void explain(void)
+static void explain(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ... pedit munge [ex] <MUNGE> [CONTROL]\n"
"Where: MUNGE := <RAW>|<LAYERED>\n"
"\t<RAW>:= <OFFSETC>[ATC]<CMD>\n \t\tOFFSETC:= offset <offval> <u8|u16|u32>\n"
@@ -46,10 +46,12 @@ static void explain(void)
}
-static void usage(void)
+static void usage(bool help) __attribute__((noreturn));
+
+static void usage(bool help)
{
- explain();
- exit(-1);
+ explain(help);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static int pedit_parse_nopopt(int *argc_p, char ***argv_p,
@@ -641,7 +643,7 @@ static int parse_pedit(const struct action_util *a, int *argc_p, char ***argv_p,
if (ok > 1) {
fprintf(stderr,
"'ex' must be before first 'munge'\n");
- explain();
+ explain(false);
return -1;
}
sel.extended = true;
@@ -650,12 +652,12 @@ static int parse_pedit(const struct action_util *a, int *argc_p, char ***argv_p,
continue;
} else if (matches(*argv, "help") == 0) {
- usage();
+ usage(true);
} else if (matches(*argv, "munge") == 0) {
if (!ok) {
fprintf(stderr, "Bad pedit construct (%s)\n",
*argv);
- explain();
+ explain(false);
return -1;
}
NEXT_ARG();
@@ -663,7 +665,7 @@ static int parse_pedit(const struct action_util *a, int *argc_p, char ***argv_p,
if (parse_munge(&argc, &argv, &sel)) {
fprintf(stderr, "Bad pedit construct (%s)\n",
*argv);
- explain();
+ explain(false);
return -1;
}
ok++;
@@ -674,7 +676,7 @@ static int parse_pedit(const struct action_util *a, int *argc_p, char ***argv_p,
}
if (!ok) {
- explain();
+ explain(false);
return -1;
}
diff --git a/tc/m_police.c b/tc/m_police.c
index f5c538c9..ce1de40c 100644
--- a/tc/m_police.c
+++ b/tc/m_police.c
@@ -27,9 +27,11 @@ struct action_util police_action_util = {
.print_aopt = print_police,
};
-static void usage(void)
+static void usage(bool help) __attribute__((noreturn));
+
+static void usage(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ... police [ rate BPS burst BYTES[/BYTES] ] \n"
" [ pkts_rate RATE pkts_burst PACKETS ] [ mtu BYTES[/BYTES] ]\n"
" [ peakrate BPS ] [ avrate BPS ] [ overhead BYTES ]\n"
@@ -39,7 +41,7 @@ static void usage(void)
" or conform (<NOTEXCEEDACT>) the configured bandwidth limit.\n"
" EXCEEDACT/NOTEXCEEDACT := { pipe | ok | reclassify | drop | continue |\n"
" goto chain <CHAIN_INDEX> }\n");
- exit(-1);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static int act_parse_police(const struct action_util *a, int *argc_p, char ***argv_p,
@@ -152,7 +154,7 @@ static int act_parse_police(const struct action_util *a, int *argc_p, char ***ar
if (get_u64(&ppsburst64, *argv, 10))
invarg("pkts_burst", *argv);
} else if (strcmp(*argv, "help") == 0) {
- usage();
+ usage(true);
} else {
break;
}
diff --git a/tc/m_sample.c b/tc/m_sample.c
index 44ba859f..cec2cc9a 100644
--- a/tc/m_sample.c
+++ b/tc/m_sample.c
@@ -11,9 +11,9 @@
#include "tc_common.h"
#include <linux/tc_act/tc_sample.h>
-static void explain(void)
+static void explain(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: sample SAMPLE_CONF\n"
"where:\n"
"\tSAMPLE_CONF := SAMPLE_PARAMS | SAMPLE_INDEX\n"
@@ -25,10 +25,12 @@ static void explain(void)
"\tINDEX := integer index of the sample action\n");
}
-static void usage(void)
+static void usage(bool help) __attribute__((noreturn));
+
+static void usage(bool help)
{
- explain();
- exit(-1);
+ explain(help);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static int parse_sample(const struct action_util *a, int *argc_p, char ***argv_p,
@@ -60,7 +62,7 @@ static int parse_sample(const struct action_util *a, int *argc_p, char ***argv_p
NEXT_ARG();
if (get_u32(&rate, *argv, 10) != 0) {
fprintf(stderr, "Illegal rate %s\n", *argv);
- usage();
+ usage(false);
return -1;
}
rate_set = true;
@@ -69,7 +71,7 @@ static int parse_sample(const struct action_util *a, int *argc_p, char ***argv_p
if (get_u32(&group, *argv, 10) != 0) {
fprintf(stderr, "Illegal group num %s\n",
*argv);
- usage();
+ usage(false);
return -1;
}
group_set = true;
@@ -78,12 +80,12 @@ static int parse_sample(const struct action_util *a, int *argc_p, char ***argv_p
if (get_u32(&trunc, *argv, 10) != 0) {
fprintf(stderr, "Illegal truncation size %s\n",
*argv);
- usage();
+ usage(false);
return -1;
}
trunc_set = true;
} else if (matches(*argv, "help") == 0) {
- usage();
+ usage(true);
} else {
break;
}
@@ -106,12 +108,12 @@ static int parse_sample(const struct action_util *a, int *argc_p, char ***argv_p
if (!p.index && !group_set) {
fprintf(stderr, "param \"group\" not set\n");
- usage();
+ usage(false);
}
if (!p.index && !rate_set) {
fprintf(stderr, "param \"rate\" not set\n");
- usage();
+ usage(false);
}
tail = addattr_nest(n, MAX_MSG, tca_id);
diff --git a/tc/m_simple.c b/tc/m_simple.c
index a3afc12e..96d1da53 100644
--- a/tc/m_simple.c
+++ b/tc/m_simple.c
@@ -74,19 +74,21 @@
#ifndef SIMP_MAX_DATA
#define SIMP_MAX_DATA 32
#endif
-static void explain(void)
+static void explain(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage:... simple [sdata STRING] [index INDEX] [CONTROL]\n"
"\tSTRING being an arbitrary string\n"
"\tINDEX := optional index value used\n"
"\tCONTROL := reclassify|pipe|drop|continue|ok\n");
}
-static void usage(void)
+static void usage(bool help) __attribute__((noreturn));
+
+static void usage(bool help)
{
- explain();
- exit(-1);
+ explain(help);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static int
@@ -110,7 +112,7 @@ parse_simple(const struct action_util *a, int *argc_p, char ***argv_p, int tca_i
argc--;
argv++;
} else if (matches(*argv, "help") == 0) {
- usage();
+ usage(true);
} else {
break;
}
@@ -134,7 +136,7 @@ parse_simple(const struct action_util *a, int *argc_p, char ***argv_p, int tca_i
}
if (!ok) {
- explain();
+ explain(false);
return -1;
}
diff --git a/tc/m_skbedit.c b/tc/m_skbedit.c
index 5c9b2f24..0fe73e3f 100644
--- a/tc/m_skbedit.c
+++ b/tc/m_skbedit.c
@@ -16,9 +16,10 @@
#include <linux/tc_act/tc_skbedit.h>
#include <linux/if_packet.h>
-static void explain(void)
+static void explain(bool help)
{
- fprintf(stderr, "Usage: ... skbedit <[QM] [PM] [MM] [PT] [IF]>\n"
+ fprintf(help ? stdout : stderr,
+ "Usage: ... skbedit <[QM] [PM] [MM] [PT] [IF]>\n"
"QM = queue_mapping QUEUE_MAPPING\n"
"PM = priority PRIORITY\n"
"MM = mark MARK[/MASK]\n"
@@ -33,11 +34,13 @@ static void explain(void)
"note: inheritdsfield maps DS field to skb->priority\n");
}
+static void usage(bool help) __attribute__((noreturn));
+
static void
-usage(void)
+usage(bool help)
{
- explain();
- exit(-1);
+ explain(help);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static int
@@ -121,7 +124,7 @@ parse_skbedit(const struct action_util *a, int *argc_p, char ***argv_p, int tca_
pure_flags |= SKBEDIT_F_INHERITDSFIELD;
ok++;
} else if (matches(*argv, "help") == 0) {
- usage();
+ usage(true);
} else {
break;
}
@@ -146,7 +149,7 @@ parse_skbedit(const struct action_util *a, int *argc_p, char ***argv_p, int tca_
}
if (!ok) {
- explain();
+ explain(false);
return -1;
}
diff --git a/tc/m_skbmod.c b/tc/m_skbmod.c
index a13581be..a75cb0f5 100644
--- a/tc/m_skbmod.c
+++ b/tc/m_skbmod.c
@@ -20,9 +20,9 @@
#include "tc_util.h"
#include <linux/tc_act/tc_skbmod.h>
-static void skbmod_explain(void)
+static void skbmod_explain(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage:... skbmod { set <SETTABLE> | swap <SWAPPABLE> | ecn } [CONTROL] [index INDEX]\n"
"where SETTABLE is: [dmac DMAC] [smac SMAC] [etype ETYPE]\n"
"where SWAPPABLE is: \"mac\" to swap mac addresses\n"
@@ -34,10 +34,12 @@ static void skbmod_explain(void)
"\tINDEX := skbmod index value to use\n");
}
-static void skbmod_usage(void)
+static void skbmod_usage(bool help) __attribute__((noreturn));
+
+static void skbmod_usage(bool help)
{
- skbmod_explain();
- exit(-1);
+ skbmod_explain(help);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static int parse_skbmod(const struct action_util *a, int *argc_p, char ***argv_p,
@@ -110,7 +112,7 @@ static int parse_skbmod(const struct action_util *a, int *argc_p, char ***argv_p
p.flags |= SKBMOD_F_ECN;
ok += 1;
} else if (matches(*argv, "help") == 0) {
- skbmod_usage();
+ skbmod_usage(true);
} else {
break;
}
@@ -136,7 +138,7 @@ static int parse_skbmod(const struct action_util *a, int *argc_p, char ***argv_p
if (!ok) {
fprintf(stderr, "skbmod requires at least one option\n");
- skbmod_usage();
+ skbmod_usage(false);
}
tail = addattr_nest(n, MAX_MSG, tca_id);
diff --git a/tc/m_tunnel_key.c b/tc/m_tunnel_key.c
index b65d88e0..ea593e4f 100644
--- a/tc/m_tunnel_key.c
+++ b/tc/m_tunnel_key.c
@@ -15,9 +15,9 @@
#include "tc_util.h"
#include <linux/tc_act/tc_tunnel_key.h>
-static void explain(void)
+static void explain(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: tunnel_key unset\n"
" tunnel_key set <TUNNEL_KEY>\n"
"Where TUNNEL_KEY is a combination of:\n"
@@ -30,10 +30,12 @@ static void explain(void)
"nofrag\n");
}
-static void usage(void)
+static void usage(bool help) __attribute__((noreturn));
+
+static void usage(bool help)
{
- explain();
- exit(-1);
+ explain(help);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static int tunnel_key_parse_ip_addr(const char *str, int addr4_type,
@@ -336,7 +338,7 @@ static int parse_tunnel_key(const struct action_util *a, int *argc_p, char ***ar
if (action) {
fprintf(stderr, "unexpected \"%s\" - action already specified\n",
*argv);
- explain();
+ explain(false);
return -1;
}
action = TCA_TUNNEL_KEY_ACT_RELEASE;
@@ -344,7 +346,7 @@ static int parse_tunnel_key(const struct action_util *a, int *argc_p, char ***ar
if (action) {
fprintf(stderr, "unexpected \"%s\" - action already specified\n",
*argv);
- explain();
+ explain(false);
return -1;
}
action = TCA_TUNNEL_KEY_ACT_SET;
@@ -429,7 +431,7 @@ static int parse_tunnel_key(const struct action_util *a, int *argc_p, char ***ar
} else if (strcmp(*argv, "nofrag") == 0) {
nofrag = 1;
} else if (matches(*argv, "help") == 0) {
- usage();
+ usage(true);
} else {
break;
}
@@ -459,7 +461,7 @@ static int parse_tunnel_key(const struct action_util *a, int *argc_p, char ***ar
if (action == TCA_TUNNEL_KEY_ACT_SET &&
(!has_src_ip || !has_dst_ip)) {
fprintf(stderr, "set needs tunnel_key parameters\n");
- explain();
+ explain(false);
return -1;
}
diff --git a/tc/m_vlan.c b/tc/m_vlan.c
index 5ff8c712..0cb8b8af 100644
--- a/tc/m_vlan.c
+++ b/tc/m_vlan.c
@@ -23,9 +23,9 @@ static const char * const action_names[] = {
[TCA_VLAN_ACT_PUSH_ETH] = "push_eth",
};
-static void explain(void)
+static void explain(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: vlan pop [CONTROL]\n"
" vlan push [ protocol VLANPROTO ] id VLANID [ priority VLANPRIO ] [CONTROL]\n"
" vlan modify [ protocol VLANPROTO ] id VLANID [ priority VLANPRIO ] [CONTROL]\n"
@@ -37,10 +37,12 @@ static void explain(void)
" goto chain <CHAIN_INDEX>\n");
}
-static void usage(void)
+static void usage(bool help) __attribute__((noreturn));
+
+static void usage(bool help)
{
- explain();
- exit(-1);
+ explain(help);
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
static bool has_push_attribs(int action)
@@ -53,7 +55,7 @@ static void unexpected(const char *arg)
fprintf(stderr,
"unexpected \"%s\" - action already specified\n",
arg);
- explain();
+ explain(false);
}
static int parse_vlan(const struct action_util *a, int *argc_p, char ***argv_p,
@@ -152,7 +154,7 @@ static int parse_vlan(const struct action_util *a, int *argc_p, char ***argv_p,
invarg("src_mac is invalid", *argv);
src_mac_set = 1;
} else if (matches(*argv, "help") == 0) {
- usage();
+ usage(true);
} else {
break;
}
@@ -178,7 +180,7 @@ static int parse_vlan(const struct action_util *a, int *argc_p, char ***argv_p,
if (has_push_attribs(action) && !id_set) {
fprintf(stderr, "id needs to be set for %s\n",
action_names[action]);
- explain();
+ explain(false);
return -1;
}
@@ -186,12 +188,12 @@ static int parse_vlan(const struct action_util *a, int *argc_p, char ***argv_p,
if (!dst_mac_set) {
fprintf(stderr, "dst_mac needs to be set for %s\n",
action_names[action]);
- explain();
+ explain(false);
return -1;
} else if (!src_mac_set) {
fprintf(stderr, "src_mac needs to be set for %s\n",
action_names[action]);
- explain();
+ explain(false);
return -1;
}
}
@@ -205,7 +207,7 @@ static int parse_vlan(const struct action_util *a, int *argc_p, char ***argv_p,
if (proto != htons(ETH_P_8021Q) &&
proto != htons(ETH_P_8021AD)) {
fprintf(stderr, "protocol not supported\n");
- explain();
+ explain(false);
return -1;
}
diff --git a/tc/q_cake.c b/tc/q_cake.c
index 250cc8b6..dfc749c4 100644
--- a/tc/q_cake.c
+++ b/tc/q_cake.c
@@ -68,9 +68,9 @@ static struct cake_preset *find_preset(char *argv)
return NULL;
}
-static void explain(void)
+static void explain(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ... cake [ bandwidth RATE | unlimited* | autorate-ingress ]\n"
" [ rtt TIME | datacentre | lan | metro | regional |\n"
" internet* | oceanic | satellite | interplanetary ]\n"
@@ -86,6 +86,9 @@ static void explain(void)
" [ ptm | atm | noatm* ] [ overhead N | conservative | raw* ]\n"
" [ mpu N ] [ ingress | egress* ]\n"
" (* marks defaults)\n");
+
+ if (help)
+ exit(EXIT_SUCCESS);
}
static int cake_parse_opt(const struct qdisc_util *qu, int argc, char **argv,
@@ -341,11 +344,10 @@ static int cake_parse_opt(const struct qdisc_util *qu, int argc, char **argv,
return -1;
}
} else if (strcmp(*argv, "help") == 0) {
- explain();
- return -1;
+ explain(true);
} else {
fprintf(stderr, "What is \"%s\"?\n", *argv);
- explain();
+ explain(false);
return -1;
}
argc--; argv++;
diff --git a/tc/q_cbs.c b/tc/q_cbs.c
index 5adfee7f..cf9015a7 100644
--- a/tc/q_cbs.c
+++ b/tc/q_cbs.c
@@ -17,11 +17,14 @@
#include "utils.h"
#include "tc_util.h"
-static void explain(void)
+static void explain(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ... cbs hicredit BYTES locredit BYTES sendslope BPS idleslope BPS\n"
" [offload 0|1]\n");
+
+ if (help)
+ exit(EXIT_SUCCESS);
}
static void explain1(const char *arg, const char *val)
@@ -87,11 +90,10 @@ static int cbs_parse_opt(const struct qdisc_util *qu, int argc,
return -1;
}
} else if (strcmp(*argv, "help") == 0) {
- explain();
- return -1;
+ explain(true);
} else {
fprintf(stderr, "cbs: unknown parameter \"%s\"\n", *argv);
- explain();
+ explain(false);
return -1;
}
argc--; argv++;
diff --git a/tc/q_choke.c b/tc/q_choke.c
index a16f5f68..94b961d5 100644
--- a/tc/q_choke.c
+++ b/tc/q_choke.c
@@ -20,11 +20,14 @@
#include "tc_red.h"
-static void explain(void)
+static void explain(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ... choke limit PACKETS bandwidth KBPS [ecn]\n"
" [ min PACKETS ] [ max PACKETS ] [ burst PACKETS ]\n");
+
+ if (help)
+ exit(EXIT_SUCCESS);
}
static int choke_parse_opt(const struct qdisc_util *qu, int argc, char **argv,
@@ -92,11 +95,10 @@ static int choke_parse_opt(const struct qdisc_util *qu, int argc, char **argv,
return -1;
}
} else if (strcmp(*argv, "help") == 0) {
- explain();
- return -1;
+ explain(true);
} else {
fprintf(stderr, "What is \"%s\"?\n", *argv);
- explain();
+ explain(false);
return -1;
}
argc--; argv++;
diff --git a/tc/q_clsact.c b/tc/q_clsact.c
index 5bd9eb20..53f2b2c7 100644
--- a/tc/q_clsact.c
+++ b/tc/q_clsact.c
@@ -5,17 +5,23 @@
#include "utils.h"
#include "tc_util.h"
-static void explain(void)
+static void explain(bool help)
{
- fprintf(stderr, "Usage: ... clsact\n");
+ fprintf(help ? stdout : stderr, "Usage: ... clsact\n");
+
+ if (help)
+ exit(EXIT_SUCCESS);
}
static int clsact_parse_opt(const struct qdisc_util *qu, int argc, char **argv,
struct nlmsghdr *n, const char *dev)
{
if (argc > 0) {
- fprintf(stderr, "What is \"%s\"?\n", *argv);
- explain();
+ bool help = strcmp(*argv, "help") == 0;
+
+ if (!help)
+ fprintf(stderr, "What is \"%s\"?\n", *argv);
+ explain(help);
return -1;
}
diff --git a/tc/q_codel.c b/tc/q_codel.c
index 15029b4c..20a8ee3f 100644
--- a/tc/q_codel.c
+++ b/tc/q_codel.c
@@ -20,12 +20,15 @@
#include "utils.h"
#include "tc_util.h"
-static void explain(void)
+static void explain(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ... codel [ limit PACKETS ] [ target TIME ]\n"
" [ interval TIME ] [ ecn | noecn ]\n"
" [ ce_threshold TIME ]\n");
+
+ if (help)
+ exit(EXIT_SUCCESS);
}
static int codel_parse_opt(const struct qdisc_util *qu, int argc, char **argv,
@@ -68,11 +71,10 @@ static int codel_parse_opt(const struct qdisc_util *qu, int argc, char **argv,
} else if (strcmp(*argv, "noecn") == 0) {
ecn = 0;
} else if (strcmp(*argv, "help") == 0) {
- explain();
- return -1;
+ explain(true);
} else {
fprintf(stderr, "What is \"%s\"?\n", *argv);
- explain();
+ explain(false);
return -1;
}
argc--; argv++;
diff --git a/tc/q_drr.c b/tc/q_drr.c
index add684d5..277fda7b 100644
--- a/tc/q_drr.c
+++ b/tc/q_drr.c
@@ -17,14 +17,20 @@
#include "utils.h"
#include "tc_util.h"
-static void explain(void)
+static void explain(bool help)
{
- fprintf(stderr, "Usage: ... drr\n");
+ fprintf(help ? stdout : stderr, "Usage: ... drr\n");
+
+ if (help)
+ exit(EXIT_SUCCESS);
}
-static void explain2(void)
+static void explain2(bool help)
{
- fprintf(stderr, "Usage: ... drr quantum SIZE\n");
+ fprintf(help ? stdout : stderr, "Usage: ... drr quantum SIZE\n");
+
+ if (help)
+ exit(EXIT_SUCCESS);
}
@@ -33,11 +39,10 @@ static int drr_parse_opt(const struct qdisc_util *qu, int argc, char **argv,
{
while (argc) {
if (strcmp(*argv, "help") == 0) {
- explain();
- return -1;
+ explain(true);
} else {
fprintf(stderr, "What is \"%s\"?\n", *argv);
- explain();
+ explain(false);
return -1;
}
}
@@ -61,11 +66,10 @@ static int drr_parse_class_opt(const struct qdisc_util *qu, int argc, char **arg
}
addattr_l(n, 1024, TCA_DRR_QUANTUM, &tmp, sizeof(tmp));
} else if (strcmp(*argv, "help") == 0) {
- explain2();
- return -1;
+ explain2(true);
} else {
fprintf(stderr, "What is \"%s\"?\n", *argv);
- explain2();
+ explain2(false);
return -1;
}
argc--; argv++;
diff --git a/tc/q_dualpi2.c b/tc/q_dualpi2.c
index dab74203..087051a1 100644
--- a/tc/q_dualpi2.c
+++ b/tc/q_dualpi2.c
@@ -76,21 +76,26 @@ static const char *get_ecn_type_json(uint8_t ect)
}
}
-static void explain(void)
+static void explain(bool help)
{
- fprintf(stderr, "Usage: ... dualpi2\n");
- fprintf(stderr, " [limit PACKETS]\n");
- fprintf(stderr, " [memlimit BYTES]\n");
- fprintf(stderr, " [coupling_factor NUMBER]\n");
- fprintf(stderr, " [step_thresh TIME|PACKETS]\n");
- fprintf(stderr, " [min_qlen_step PACKETS]\n");
- fprintf(stderr, " [drop_on_overload|overflow]\n");
- fprintf(stderr, " [drop_enqueue|drop_dequeue]\n");
- fprintf(stderr, " [classic_protection PERCENTAGE]\n");
- fprintf(stderr, " [max_rtt TIME [typical_rtt TIME]]\n");
- fprintf(stderr, " [target TIME] [tupdate TIME]\n");
- fprintf(stderr, " [alpha ALPHA] [beta BETA]\n");
- fprintf(stderr, " [split_gso|no_split_gso]\n");
+ FILE *fp = help ? stdout : stderr;
+
+ fprintf(fp, "Usage: ... dualpi2\n"
+ " [limit PACKETS]\n"
+ " [memlimit BYTES]\n"
+ " [coupling_factor NUMBER]\n"
+ " [step_thresh TIME|PACKETS]\n"
+ " [min_qlen_step PACKETS]\n"
+ " [drop_on_overload|overflow]\n"
+ " [drop_enqueue|drop_dequeue]\n"
+ " [classic_protection PERCENTAGE]\n"
+ " [max_rtt TIME [typical_rtt TIME]]\n"
+ " [target TIME] [tupdate TIME]\n"
+ " [alpha ALPHA] [beta BETA]\n"
+ " [split_gso|no_split_gso]\n");
+
+ if (help)
+ exit(EXIT_SUCCESS);
}
static int get_packets(uint32_t *val, const char *arg)
@@ -272,11 +277,10 @@ static int dualpi2_parse_opt(const struct qdisc_util *qu, int argc,
return -1;
}
} else if (strcmp(*argv, "help") == 0) {
- explain();
- return -1;
+ explain(true);
} else {
fprintf(stderr, "What is \"%s\"?\n", *argv);
- explain();
+ explain(false);
return -1;
}
--argc;
diff --git a/tc/q_etf.c b/tc/q_etf.c
index 4e89f723..b6c07272 100644
--- a/tc/q_etf.c
+++ b/tc/q_etf.c
@@ -19,11 +19,14 @@
#include "utils.h"
#include "tc_util.h"
-static void explain(void)
+static void explain(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ... etf delta NANOS clockid CLOCKID [offload] [deadline_mode]\n"
"CLOCKID must be a valid SYS-V id (i.e. CLOCK_TAI)\n");
+
+ if (help)
+ exit(EXIT_SUCCESS);
}
static void explain1(const char *arg, const char *val)
@@ -90,11 +93,10 @@ static int etf_parse_opt(const struct qdisc_util *qu, int argc,
opt.flags |= TC_ETF_SKIP_SOCK_CHECK;
} else if (strcmp(*argv, "help") == 0) {
- explain();
- return -1;
+ explain(true);
} else {
fprintf(stderr, "etf: unknown parameter \"%s\"\n", *argv);
- explain();
+ explain(false);
return -1;
}
argc--; argv++;
diff --git a/tc/q_ets.c b/tc/q_ets.c
index dea5f044..5a5aa24e 100644
--- a/tc/q_ets.c
+++ b/tc/q_ets.c
@@ -16,14 +16,21 @@
#include "utils.h"
#include "tc_util.h"
-static void explain(void)
+static void explain(bool help)
{
- fprintf(stderr, "Usage: ... ets [bands NUMBER] [strict NUMBER] [quanta Q1 Q2...] [priomap P1 P2...]\n");
+ fprintf(help ? stdout : stderr,
+ "Usage: ... ets [bands NUMBER] [strict NUMBER] [quanta Q1 Q2...] [priomap P1 P2...]\n");
+
+ if (help)
+ exit(EXIT_SUCCESS);
}
-static void cexplain(void)
+static void cexplain(bool help)
{
- fprintf(stderr, "Usage: ... ets [quantum Q1]\n");
+ fprintf(help ? stdout : stderr, "Usage: ... ets [quantum Q1]\n");
+
+ if (help)
+ exit(EXIT_SUCCESS);
}
static unsigned int parse_quantum(const char *arg)
@@ -109,8 +116,7 @@ static int ets_parse_opt(const struct qdisc_util *qu, int argc, char **argv,
quanta_mode = false;
goto parse_priomap;
} else if (strcmp(*argv, "help") == 0) {
- explain();
- return -1;
+ explain(true);
} else if (quanta_mode) {
unsigned int quantum;
@@ -134,7 +140,7 @@ parse_priomap:
priomap[nprio++] = band;
} else {
fprintf(stderr, "What is \"%s\"?\n", *argv);
- explain();
+ explain(false);
return -1;
}
argc--; argv++;
@@ -144,12 +150,12 @@ parse_priomap:
nbands = nquanta + nstrict;
if (!nbands) {
fprintf(stderr, "One of \"bands\", \"quanta\" or \"strict\" needs to be specified\n");
- explain();
+ explain(false);
return -1;
}
if (nstrict + nquanta > nbands) {
fprintf(stderr, "Not enough total bands to cover all the strict bands and quanta\n");
- explain();
+ explain(false);
return -1;
}
for (tmp = 0; tmp < nprio; tmp++) {
@@ -199,11 +205,10 @@ static int ets_parse_copt(const struct qdisc_util *qu, int argc, char **argv,
if (!quantum)
return -1;
} else if (strcmp(*argv, "help") == 0) {
- cexplain();
- return -1;
+ cexplain(true);
} else {
fprintf(stderr, "What is \"%s\"?\n", *argv);
- cexplain();
+ cexplain(false);
return -1;
}
argc--; argv++;
diff --git a/tc/q_fifo.c b/tc/q_fifo.c
index 489208dc..b61e6d8c 100644
--- a/tc/q_fifo.c
+++ b/tc/q_fifo.c
@@ -17,9 +17,13 @@
#include "utils.h"
#include "tc_util.h"
-static void explain(void)
+static void explain(bool help)
{
- fprintf(stderr, "Usage: ... <[p|b]fifo | pfifo_head_drop> [ limit NUMBER ]\n");
+ fprintf(help ? stdout : stderr,
+ "Usage: ... <[p|b]fifo | pfifo_head_drop> [ limit NUMBER ]\n");
+
+ if (help)
+ exit(EXIT_SUCCESS);
}
static int fifo_parse_opt(const struct qdisc_util *qu, int argc, char **argv,
@@ -37,11 +41,10 @@ static int fifo_parse_opt(const struct qdisc_util *qu, int argc, char **argv,
}
ok++;
} else if (strcmp(*argv, "help") == 0) {
- explain();
- return -1;
+ explain(true);
} else {
fprintf(stderr, "%s: unknown parameter \"%s\"\n", qu->id, *argv);
- explain();
+ explain(false);
return -1;
}
argc--; argv++;
diff --git a/tc/q_fq.c b/tc/q_fq.c
index 13c5a896..56bfa58a 100644
--- a/tc/q_fq.c
+++ b/tc/q_fq.c
@@ -18,9 +18,9 @@
#include "utils.h"
#include "tc_util.h"
-static void explain(void)
+static void explain(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ... fq [ limit PACKETS ] [ flow_limit PACKETS ]\n"
" [ quantum BYTES ] [ initial_quantum BYTES ]\n"
" [ maxrate RATE ] [ buckets NUMBER ]\n"
@@ -34,6 +34,9 @@ static void explain(void)
" [ horizon TIME ]\n"
" [ horizon_{cap|drop} ]\n"
" [ offload_horizon TIME ]\n");
+
+ if (help)
+ exit(EXIT_SUCCESS);
}
static unsigned int ilog2(unsigned int val)
@@ -278,11 +281,10 @@ static int fq_parse_opt(const struct qdisc_util *qu, int argc, char **argv,
}
set_weights = true;
} else if (strcmp(*argv, "help") == 0) {
- explain();
- return -1;
+ explain(true);
} else {
fprintf(stderr, "What is \"%s\"?\n", *argv);
- explain();
+ explain(false);
return -1;
}
argc--; argv++;
diff --git a/tc/q_fq_codel.c b/tc/q_fq_codel.c
index a619d2b3..415780ba 100644
--- a/tc/q_fq_codel.c
+++ b/tc/q_fq_codel.c
@@ -17,9 +17,9 @@
#include "utils.h"
#include "tc_util.h"
-static void explain(void)
+static void explain(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ... fq_codel [ limit PACKETS ] [ flows NUMBER ]\n"
"[ memory_limit BYTES ]\n"
"[ target TIME ] [ interval TIME ]\n"
@@ -27,6 +27,9 @@ static void explain(void)
"[ ce_threshold TIME ]\n"
"[ ce_threshold_selector VALUE/MASK ]\n"
"[ drop_batch SIZE ]\n");
+
+ if (help)
+ exit(EXIT_SUCCESS);
}
static int fq_codel_parse_opt(const struct qdisc_util *qu, int argc, char **argv,
@@ -117,11 +120,10 @@ static int fq_codel_parse_opt(const struct qdisc_util *qu, int argc, char **argv
} else if (strcmp(*argv, "noecn") == 0) {
ecn = 0;
} else if (strcmp(*argv, "help") == 0) {
- explain();
- return -1;
+ explain(true);
} else {
fprintf(stderr, "What is \"%s\"?\n", *argv);
- explain();
+ explain(false);
return -1;
}
argc--; argv++;
diff --git a/tc/q_fq_pie.c b/tc/q_fq_pie.c
index dc2710cd..635d0750 100644
--- a/tc/q_fq_pie.c
+++ b/tc/q_fq_pie.c
@@ -22,15 +22,18 @@
#include "utils.h"
#include "tc_util.h"
-static void explain(void)
+static void explain(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ... fq_pie [ limit PACKETS ] [ flows NUMBER ]\n"
" [ target TIME ] [ tupdate TIME ]\n"
" [ alpha NUMBER ] [ beta NUMBER ]\n"
" [ quantum BYTES ] [ memory_limit BYTES ]\n"
" [ ecn_prob PERCENTAGE ] [ [no]ecn ]\n"
" [ [no]bytemode ] [ [no_]dq_rate_estimator ]\n");
+
+ if (help)
+ exit(EXIT_SUCCESS);
}
#define ALPHA_MAX 32
@@ -124,11 +127,10 @@ static int fq_pie_parse_opt(const struct qdisc_util *qu, int argc, char **argv,
} else if (strcmp(*argv, "no_dq_rate_estimator") == 0) {
dq_rate_estimator = 0;
} else if (strcmp(*argv, "help") == 0) {
- explain();
- return -1;
+ explain(true);
} else {
fprintf(stderr, "What is \"%s\"?\n", *argv);
- explain();
+ explain(false);
return -1;
}
diff --git a/tc/q_gred.c b/tc/q_gred.c
index 95573218..b829c878 100644
--- a/tc/q_gred.c
+++ b/tc/q_gred.c
@@ -29,14 +29,17 @@
#define DPRINTF(format, args...)
#endif
-static void explain(void)
+static void explain(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: tc qdisc { add | replace | change } ... gred setup vqs NUMBER\n"
" default DEFAULT_VQ [ grio ] [ limit BYTES ] [ecn] [harddrop]\n"
" tc qdisc change ... gred vq VQ [ prio VALUE ] limit BYTES\n"
" min BYTES max BYTES avpkt BYTES [ burst PACKETS ]\n"
" [ probability PROBABILITY ] [ bandwidth KBPS ] [ecn] [harddrop]\n");
+
+ if (help)
+ exit(EXIT_SUCCESS);
}
static int init_gred(const struct qdisc_util *qu, int argc, char **argv,
@@ -88,11 +91,10 @@ static int init_gred(const struct qdisc_util *qu, int argc, char **argv,
} else if (strcmp(*argv, "harddrop") == 0) {
opt.flags |= TC_RED_HARDDROP;
} else if (strcmp(*argv, "help") == 0) {
- explain();
- return -1;
+ explain(true);
} else {
fprintf(stderr, "What is \"%s\"?\n", *argv);
- explain();
+ explain(false);
return -1;
}
argc--; argv++;
@@ -214,18 +216,17 @@ static int gred_parse_opt(const struct qdisc_util *qu, int argc, char **argv, st
} else if (strcmp(*argv, "harddrop") == 0) {
flags |= TC_RED_HARDDROP;
} else if (strcmp(*argv, "help") == 0) {
- explain();
- return -1;
+ explain(true);
} else {
fprintf(stderr, "What is \"%s\"?\n", *argv);
- explain();
+ explain(false);
return -1;
}
argc--; argv++;
}
if (!ok) {
- explain();
+ explain(false);
return -1;
}
if (opt.DP == MAX_DPs || !opt.limit || !opt.qth_min || !opt.qth_max ||
diff --git a/tc/q_hfsc.c b/tc/q_hfsc.c
index f68e8351..ec143080 100644
--- a/tc/q_hfsc.c
+++ b/tc/q_hfsc.c
@@ -22,19 +22,22 @@ static int hfsc_get_sc(int *, char ***,
struct tc_service_curve *, const char *);
static void
-explain_qdisc(void)
+explain_qdisc(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ... hfsc [ default CLASSID ]\n"
"\n"
" default: default class for unclassified packets\n"
);
+
+ if (help)
+ exit(EXIT_SUCCESS);
}
static void
-explain_class(void)
+explain_class(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ... hfsc [ [ rt SC ] [ ls SC ] | [ sc SC ] ] [ ul SC ]\n"
"\n"
"SC := [ [ m1 BPS ] d SEC ] m2 BPS\n"
@@ -56,6 +59,9 @@ explain_class(void)
" - 'ul' can only be specified with 'ls' or 'sc'\n"
"\n"
);
+
+ if (help)
+ exit(EXIT_SUCCESS);
}
static void
@@ -82,11 +88,10 @@ hfsc_parse_opt(const struct qdisc_util *qu, int argc, char **argv,
return -1;
}
} else if (matches(*argv, "help") == 0) {
- explain_qdisc();
- return -1;
+ explain_qdisc(true);
} else {
fprintf(stderr, "HFSC: What is \"%s\" ?\n", *argv);
- explain_qdisc();
+ explain_qdisc(false);
return -1;
}
argc--, argv++;
@@ -178,11 +183,10 @@ hfsc_parse_class_opt(const struct qdisc_util *qu, int argc, char **argv,
}
usc_ok = 1;
} else if (matches(*argv, "help") == 0) {
- explain_class();
- return -1;
+ explain_class(true);
} else {
fprintf(stderr, "HFSC: What is \"%s\" ?\n", *argv);
- explain_class();
+ explain_class(false);
return -1;
}
argc--, argv++;
@@ -190,12 +194,12 @@ hfsc_parse_class_opt(const struct qdisc_util *qu, int argc, char **argv,
if (!(rsc_ok || fsc_ok || usc_ok)) {
fprintf(stderr, "HFSC: no parameters given\n");
- explain_class();
+ explain_class(false);
return -1;
}
if (usc_ok && !fsc_ok) {
fprintf(stderr, "HFSC: Upper-limit Service Curve without Link-Share Service Curve\n");
- explain_class();
+ explain_class(false);
return -1;
}
diff --git a/tc/q_hhf.c b/tc/q_hhf.c
index 939e4909..aa62228f 100644
--- a/tc/q_hhf.c
+++ b/tc/q_hhf.c
@@ -15,15 +15,18 @@
#include "utils.h"
#include "tc_util.h"
-static void explain(void)
+static void explain(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ... hhf [ limit PACKETS ] [ quantum BYTES]\n"
" [ hh_limit NUMBER ]\n"
" [ reset_timeout TIME ]\n"
" [ admit_bytes BYTES ]\n"
" [ evict_timeout TIME ]\n"
" [ non_hh_weight NUMBER ]\n");
+
+ if (help)
+ exit(EXIT_SUCCESS);
}
static int hhf_parse_opt(const struct qdisc_util *qu, int argc, char **argv,
@@ -82,11 +85,10 @@ static int hhf_parse_opt(const struct qdisc_util *qu, int argc, char **argv,
return -1;
}
} else if (strcmp(*argv, "help") == 0) {
- explain();
- return -1;
+ explain(true);
} else {
fprintf(stderr, "What is \"%s\"?\n", *argv);
- explain();
+ explain(false);
return -1;
}
argc--; argv++;
diff --git a/tc/q_htb.c b/tc/q_htb.c
index a3ad4215..1b746eda 100644
--- a/tc/q_htb.c
+++ b/tc/q_htb.c
@@ -21,9 +21,10 @@
#error "Different kernel and TC HTB versions"
#endif
-static void explain(void)
+static void explain(FILE *fp)
{
- fprintf(stderr, "Usage: ... qdisc add ... htb [default N] [r2q N]\n"
+ fprintf(fp,
+ "Usage: ... qdisc add ... htb [default N] [r2q N]\n"
" [direct_qlen P] [offload]\n"
" default minor id of class to which unclassified packets are sent {0}\n"
" r2q DRR quantums are computed as rate in Bps/r2q {10}\n"
@@ -50,7 +51,8 @@ static void explain(void)
static void explain1(char *arg)
{
fprintf(stderr, "Illegal \"%s\"\n", arg);
- explain();
+ explain(stderr);
+ exit(EXIT_FAILURE);
}
static int htb_parse_opt(const struct qdisc_util *qu, int argc,
@@ -89,9 +91,12 @@ static int htb_parse_opt(const struct qdisc_util *qu, int argc,
}
} else if (matches(*argv, "offload") == 0) {
offload = true;
+ } else if (strcmp(*argv, "help") == 0) {
+ explain(stdout);
+ exit(EXIT_SUCCESS);
} else {
fprintf(stderr, "What is \"%s\"?\n", *argv);
- explain();
+ explain(stderr);
return -1;
}
argc--; argv++;
@@ -202,11 +207,11 @@ static int htb_parse_class_opt(const struct qdisc_util *qu, int argc, char **arg
return -1;
}
} else if (strcmp(*argv, "help") == 0) {
- explain();
- return -1;
+ explain(stdout);
+ exit(EXIT_SUCCESS);
} else {
fprintf(stderr, "What is \"%s\"?\n", *argv);
- explain();
+ explain(stderr);
return -1;
}
argc--; argv++;
diff --git a/tc/q_ingress.c b/tc/q_ingress.c
index 294b0051..5dad5aea 100644
--- a/tc/q_ingress.c
+++ b/tc/q_ingress.c
@@ -11,9 +11,12 @@
#include "utils.h"
#include "tc_util.h"
-static void explain(void)
+static void explain(bool help)
{
- fprintf(stderr, "Usage: ... ingress\n");
+ fprintf(help ? stdout : stderr, "Usage: ... ingress\n");
+
+ if (help)
+ exit(EXIT_SUCCESS);
}
static int ingress_parse_opt(const struct qdisc_util *qu, int argc, char **argv,
@@ -24,8 +27,11 @@ static int ingress_parse_opt(const struct qdisc_util *qu, int argc, char **argv,
NEXT_ARG();
argc--; argv++;
} else {
- fprintf(stderr, "What is \"%s\"?\n", *argv);
- explain();
+ bool help = strcmp(*argv, "help") == 0;
+
+ if (!help)
+ fprintf(stderr, "What is \"%s\"?\n", *argv);
+ explain(help);
return -1;
}
}
diff --git a/tc/q_mqprio.c b/tc/q_mqprio.c
index 493c6eb5..a1500197 100644
--- a/tc/q_mqprio.c
+++ b/tc/q_mqprio.c
@@ -17,9 +17,9 @@
#include "utils.h"
#include "tc_util.h"
-static void explain(void)
+static void explain(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ... mqprio [num_tc NUMBER] [map P0 P1 ...]\n"
" [queues count1@offset1 count2@offset2 ...] "
"[hw 1|0]\n"
@@ -28,6 +28,9 @@ static void explain(void)
" [shaper bw_rlimit SHAPER_PARAMS]\n"
"Where: SHAPER_PARAMS := { min_rate MIN_RATE1 MIN_RATE2 ...|\n"
" max_rate MAX_RATE1 MAX_RATE2 ... }\n");
+
+ if (help)
+ exit(EXIT_SUCCESS);
}
static void add_tc_entries(struct nlmsghdr *n, __u32 fp[TC_QOPT_MAX_QUEUE],
@@ -198,8 +201,7 @@ static int mqprio_parse_opt(const struct qdisc_util *qu, int argc,
}
flags |= TC_MQPRIO_F_MAX_RATE;
} else if (strcmp(*argv, "help") == 0) {
- explain();
- return -1;
+ explain(true);
} else {
invarg("unknown argument", *argv);
}
diff --git a/tc/q_multiq.c b/tc/q_multiq.c
index 0e8e2f9e..84f75112 100644
--- a/tc/q_multiq.c
+++ b/tc/q_multiq.c
@@ -23,9 +23,12 @@
#include "utils.h"
#include "tc_util.h"
-static void explain(void)
+static void explain(bool help)
{
- fprintf(stderr, "Usage: ... multiq [help]\n");
+ fprintf(help ? stdout : stderr, "Usage: ... multiq [help]\n");
+
+ if (help)
+ exit(EXIT_SUCCESS);
}
static int multiq_parse_opt(const struct qdisc_util *qu, int argc, char **argv,
@@ -35,11 +38,10 @@ static int multiq_parse_opt(const struct qdisc_util *qu, int argc, char **argv,
if (argc) {
if (strcmp(*argv, "help") == 0) {
- explain();
- return -1;
+ explain(true);
} else {
fprintf(stderr, "What is \"%s\"?\n", *argv);
- explain();
+ explain(false);
return -1;
}
}
diff --git a/tc/q_netem.c b/tc/q_netem.c
index 0e47765b..7051aa98 100644
--- a/tc/q_netem.c
+++ b/tc/q_netem.c
@@ -20,9 +20,9 @@
#include "tc_util.h"
#include "tc_common.h"
-static void explain(void)
+static void explain(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ... netem [ limit PACKETS ]\n"
" [ delay TIME [ JITTER [ CORRELATION ] ] ]\n"
" [ distribution {uniform|normal|pareto|paretonormal} ]\n"
@@ -38,6 +38,9 @@ static void explain(void)
" [ slot MIN_DELAY [ MAX_DELAY ] [ packets MAX_PACKETS ] [ bytes MAX_BYTES ] ]\n"
" [ slot distribution {uniform|normal|pareto|paretonormal|custom}\n"
" DELAY JITTER [ packets MAX_PACKETS ] [ bytes MAX_BYTES ] ]\n");
+
+ if (help)
+ exit(EXIT_SUCCESS);
}
static void explain1(const char *arg)
@@ -531,9 +534,11 @@ random_loss_model:
NEXT_ARG();
}
} else {
- if (strcmp(*argv, "help") != 0)
+ bool help = strcmp(*argv, "help") == 0;
+
+ if (!help)
fprintf(stderr, "What is \"%s\"?\n", *argv);
- explain();
+ explain(help);
return -1;
}
}
@@ -543,28 +548,28 @@ random_loss_model:
if (reorder.probability) {
if (latency64 == 0) {
fprintf(stderr, "reordering not possible without specifying some delay\n");
- explain();
+ explain(false);
return -1;
}
if (opt.gap == 0)
opt.gap = 1;
} else if (opt.gap > 0) {
fprintf(stderr, "gap specified without reorder probability\n");
- explain();
+ explain(false);
return -1;
}
if (present[TCA_NETEM_ECN]) {
if (opt.loss <= 0 && loss_type == NETEM_LOSS_UNSPEC) {
fprintf(stderr, "ecn requested without loss model\n");
- explain();
+ explain(false);
return -1;
}
}
if (dist_data && (latency64 == 0 || jitter64 == 0)) {
fprintf(stderr, "distribution specified but no latency and jitter values\n");
- explain();
+ explain(false);
return -1;
}
diff --git a/tc/q_pie.c b/tc/q_pie.c
index 04c9aa61..e5c99432 100644
--- a/tc/q_pie.c
+++ b/tc/q_pie.c
@@ -18,13 +18,16 @@
#include "utils.h"
#include "tc_util.h"
-static void explain(void)
+static void explain(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ... pie [ limit PACKETS ] [ target TIME ]\n"
" [ tupdate TIME ] [ alpha ALPHA ] [ beta BETA ]\n"
" [ bytemode | nobytemode ] [ ecn | noecn ]\n"
" [ dq_rate_estimator | no_dq_rate_estimator ]\n");
+
+ if (help)
+ exit(EXIT_SUCCESS);
}
#define ALPHA_MAX 32
@@ -89,11 +92,10 @@ static int pie_parse_opt(const struct qdisc_util *qu, int argc, char **argv,
} else if (strcmp(*argv, "no_dq_rate_estimator") == 0) {
dq_rate_estimator = 0;
} else if (strcmp(*argv, "help") == 0) {
- explain();
- return -1;
+ explain(true);
} else {
fprintf(stderr, "What is \"%s\"?\n", *argv);
- explain();
+ explain(false);
return -1;
}
argc--;
diff --git a/tc/q_plug.c b/tc/q_plug.c
index 257735a2..3757f72f 100644
--- a/tc/q_plug.c
+++ b/tc/q_plug.c
@@ -17,9 +17,13 @@
#include "utils.h"
#include "tc_util.h"
-static void explain(void)
+static void explain(bool help)
{
- fprintf(stderr, "Usage: ... plug [block | release | release_indefinite | limit NUMBER]\n");
+ fprintf(help ? stdout : stderr,
+ "Usage: ... plug [block | release | release_indefinite | limit NUMBER]\n");
+
+ if (help)
+ exit(EXIT_SUCCESS);
}
static int plug_parse_opt(const struct qdisc_util *qu, int argc, char **argv,
@@ -47,11 +51,10 @@ static int plug_parse_opt(const struct qdisc_util *qu, int argc, char **argv,
}
ok++;
} else if (strcmp(*argv, "help") == 0) {
- explain();
- return -1;
+ explain(true);
} else {
fprintf(stderr, "%s: unknown parameter \"%s\"\n", qu->id, *argv);
- explain();
+ explain(false);
return -1;
}
argc--; argv++;
diff --git a/tc/q_prio.c b/tc/q_prio.c
index 41bd98a5..aee6301f 100644
--- a/tc/q_prio.c
+++ b/tc/q_prio.c
@@ -17,9 +17,13 @@
#include "utils.h"
#include "tc_util.h"
-static void explain(void)
+static void explain(bool help)
{
- fprintf(stderr, "Usage: ... prio bands NUMBER priomap P1 P2...[multiqueue]\n");
+ fprintf(help ? stdout : stderr,
+ "Usage: ... prio bands NUMBER priomap P1 P2...[multiqueue]\n");
+
+ if (help)
+ exit(EXIT_SUCCESS);
}
static int prio_parse_opt(const struct qdisc_util *qu, int argc, char **argv,
@@ -34,7 +38,7 @@ static int prio_parse_opt(const struct qdisc_util *qu, int argc, char **argv,
while (argc > 0) {
if (strcmp(*argv, "bands") == 0) {
if (pmap_mode)
- explain();
+ explain(false);
NEXT_ARG();
if (get_integer(&opt.bands, *argv, 10)) {
fprintf(stderr, "Illegal \"bands\"\n");
@@ -49,14 +53,13 @@ static int prio_parse_opt(const struct qdisc_util *qu, int argc, char **argv,
} else if (strcmp(*argv, "multiqueue") == 0) {
mq = 1;
} else if (strcmp(*argv, "help") == 0) {
- explain();
- return -1;
+ explain(true);
} else {
unsigned int band;
if (!pmap_mode) {
fprintf(stderr, "What is \"%s\"?\n", *argv);
- explain();
+ explain(false);
return -1;
}
if (get_unsigned(&band, *argv, 10)) {
diff --git a/tc/q_qfq.c b/tc/q_qfq.c
index 04061fcc..62d01c29 100644
--- a/tc/q_qfq.c
+++ b/tc/q_qfq.c
@@ -15,9 +15,12 @@
#include "utils.h"
#include "tc_util.h"
-static void explain(void)
+static void explain(bool help)
{
- fprintf(stderr, "Usage: ... qfq\n");
+ fprintf(help ? stdout : stderr, "Usage: ... qfq\n");
+
+ if (help)
+ exit(EXIT_SUCCESS);
}
static void explain1(const char *arg)
@@ -25,18 +28,24 @@ static void explain1(const char *arg)
fprintf(stderr, "Illegal \"%s\"\n", arg);
}
-static void explain_class(void)
+static void explain_class(bool help)
{
- fprintf(stderr, "Usage: ... qfq weight NUMBER maxpkt BYTES\n");
+ fprintf(help ? stdout : stderr,
+ "Usage: ... qfq weight NUMBER maxpkt BYTES\n");
+
+ if (help)
+ exit(EXIT_SUCCESS);
}
static int qfq_parse_opt(const struct qdisc_util *qu, int argc, char **argv,
struct nlmsghdr *n, const char *dev)
{
if (argc > 0) {
- if (matches(*argv, "help") != 0)
+ bool help = matches(*argv, "help") == 0;
+
+ if (!help)
fprintf(stderr, "What is \"%s\"?\n", *argv);
- explain();
+ explain(help);
return -1;
}
@@ -65,11 +74,10 @@ static int qfq_parse_class_opt(const struct qdisc_util *qu, int argc, char **arg
}
addattr32(n, 4096, TCA_QFQ_LMAX, tmp);
} else if (strcmp(*argv, "help") == 0) {
- explain_class();
- return -1;
+ explain_class(true);
} else {
fprintf(stderr, "What is \"%s\"?\n", *argv);
- explain_class();
+ explain_class(false);
return -1;
}
argc--; argv++;
diff --git a/tc/q_red.c b/tc/q_red.c
index 1aa6d2b1..468f8afc 100644
--- a/tc/q_red.c
+++ b/tc/q_red.c
@@ -21,13 +21,16 @@
#include "tc_red.h"
-static void explain(void)
+static void explain(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ... red limit BYTES [min BYTES] [max BYTES] avpkt BYTES [burst PACKETS]\n"
" [adaptive] [probability PROBABILITY] [bandwidth KBPS]\n"
" [ecn] [harddrop] [nodrop]\n"
" [qevent early_drop block IDX] [qevent mark block IDX]\n");
+
+ if (help)
+ exit(EXIT_SUCCESS);
}
#define RED_SUPPORTED_FLAGS (TC_RED_HISTORIC_FLAGS | TC_RED_NODROP)
@@ -122,11 +125,10 @@ static int red_parse_opt(const struct qdisc_util *qu, int argc, char **argv,
return -1;
continue;
} else if (strcmp(*argv, "help") == 0) {
- explain();
- return -1;
+ explain(true);
} else {
fprintf(stderr, "What is \"%s\"?\n", *argv);
- explain();
+ explain(false);
return -1;
}
argc--; argv++;
diff --git a/tc/q_sfb.c b/tc/q_sfb.c
index 6a26b71a..e2be0eef 100644
--- a/tc/q_sfb.c
+++ b/tc/q_sfb.c
@@ -17,13 +17,16 @@
#include "utils.h"
#include "tc_util.h"
-static void explain(void)
+static void explain(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ... sfb [ rehash SECS ] [ db SECS ]\n"
" [ limit PACKETS ] [ max PACKETS ] [ target PACKETS ]\n"
" [ increment FLOAT ] [ decrement FLOAT ]\n"
" [ penalty_rate PPS ] [ penalty_burst PACKETS ]\n");
+
+ if (help)
+ exit(EXIT_SUCCESS);
}
static int get_prob(__u32 *val, const char *arg)
@@ -109,8 +112,11 @@ static int sfb_parse_opt(const struct qdisc_util *qu, int argc, char **argv,
return -1;
}
} else {
- fprintf(stderr, "What is \"%s\"?\n", *argv);
- explain();
+ bool help = strcmp(*argv, "help") == 0;
+
+ if (!help)
+ fprintf(stderr, "What is \"%s\"?\n", *argv);
+ explain(help);
return -1;
}
argc--; argv++;
diff --git a/tc/q_sfq.c b/tc/q_sfq.c
index 37ebd977..29560532 100644
--- a/tc/q_sfq.c
+++ b/tc/q_sfq.c
@@ -19,15 +19,18 @@
#include "tc_util.h"
#include "tc_red.h"
-static void explain(void)
+static void explain(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ... sfq [ limit NUMBER ] [ perturb SECS ] [ quantum BYTES ]\n"
" [ divisor NUMBER ] [ flows NUMBER] [ depth NUMBER ]\n"
" [ headdrop ]\n"
" [ redflowlimit BYTES ] [ min BYTES ] [ max BYTES ]\n"
" [ avpkt BYTES ] [ burst PACKETS ] [ probability P ]\n"
" [ ecn ] [ harddrop ]\n");
+
+ if (help)
+ exit(EXIT_SUCCESS);
}
static int sfq_parse_opt(const struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n, const char *dev)
@@ -138,11 +141,10 @@ static int sfq_parse_opt(const struct qdisc_util *qu, int argc, char **argv, str
opt.flags |= TC_RED_HARDDROP;
red++;
} else if (strcmp(*argv, "help") == 0) {
- explain();
- return -1;
+ explain(true);
} else {
fprintf(stderr, "What is \"%s\"?\n", *argv);
- explain();
+ explain(false);
return -1;
}
argc--; argv++;
diff --git a/tc/q_skbprio.c b/tc/q_skbprio.c
index 910ea998..03406a3e 100644
--- a/tc/q_skbprio.c
+++ b/tc/q_skbprio.c
@@ -18,9 +18,13 @@
#include "utils.h"
#include "tc_util.h"
-static void explain(void)
+static void explain(bool help)
{
- fprintf(stderr, "Usage: ... <skbprio> [ limit NUMBER ]\n");
+ fprintf(help ? stdout : stderr,
+ "Usage: ... <skbprio> [ limit NUMBER ]\n");
+
+ if (help)
+ exit(EXIT_SUCCESS);
}
static int skbprio_parse_opt(const struct qdisc_util *qu, int argc, char **argv,
@@ -41,13 +45,12 @@ static int skbprio_parse_opt(const struct qdisc_util *qu, int argc, char **argv,
ok++;
}
else if (strcmp(*argv, "help") == 0) {
- explain();
- return -1;
+ explain(true);
} else {
fprintf(stderr,
"%s: unknown parameter \"%s\"\n",
qu->id, *argv);
- explain();
+ explain(false);
return -1;
}
argc--; argv++;
diff --git a/tc/q_taprio.c b/tc/q_taprio.c
index 689c7a8f..945e1edf 100644
--- a/tc/q_taprio.c
+++ b/tc/q_taprio.c
@@ -29,9 +29,9 @@ struct sched_entry {
uint8_t cmd;
};
-static void explain(void)
+static void explain(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ... taprio clockid CLOCKID\n"
" [num_tc NUMBER] [map P0 P1 ...]\n"
" [queues COUNT@OFFSET COUNT@OFFSET COUNT@OFFSET ...]\n"
@@ -40,6 +40,9 @@ static void explain(void)
" [fp FP0 FP1 FP2 ...]\n"
"\n"
"CLOCKID must be a valid SYS-V id (i.e. CLOCK_TAI)\n");
+
+ if (help)
+ exit(EXIT_SUCCESS);
}
static void explain_clockid(const char *val)
@@ -328,8 +331,7 @@ static int taprio_parse_opt(const struct qdisc_util *qu, int argc,
}
} else if (strcmp(*argv, "help") == 0) {
- explain();
- return -1;
+ explain(true);
} else {
fprintf(stderr, "Unknown argument\n");
return -1;
diff --git a/tc/q_tbf.c b/tc/q_tbf.c
index cbe11025..dc7f2d90 100644
--- a/tc/q_tbf.c
+++ b/tc/q_tbf.c
@@ -17,12 +17,15 @@
#include "utils.h"
#include "tc_util.h"
-static void explain(void)
+static void explain(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ... tbf limit BYTES burst BYTES[/BYTES] rate KBPS [ mtu BYTES[/BYTES] ]\n"
" [ peakrate KBPS ] [ latency TIME ] "
"[ overhead BYTES ] [ linklayer TYPE ]\n");
+
+ if (help)
+ exit(EXIT_SUCCESS);
}
static void explain1(const char *arg, const char *val)
@@ -155,11 +158,10 @@ static int tbf_parse_opt(const struct qdisc_util *qu, int argc, char **argv,
explain1("linklayer", *argv); return -1;
}
} else if (strcmp(*argv, "help") == 0) {
- explain();
- return -1;
+ explain(true);
} else {
fprintf(stderr, "tbf: unknown parameter \"%s\"\n", *argv);
- explain();
+ explain(false);
return -1;
}
argc--; argv++;
@@ -192,7 +194,7 @@ static int tbf_parse_opt(const struct qdisc_util *qu, int argc, char **argv,
}
if (verdict != 0) {
- explain();
+ explain(false);
return verdict;
}
diff --git a/tc/tc.c b/tc/tc.c
index 7d69e4d5..89723f77 100644
--- a/tc/tc.c
+++ b/tc/tc.c
@@ -186,9 +186,9 @@ noexist:
return q;
}
-static void usage(void)
+static void usage(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: tc [ OPTIONS ] OBJECT { COMMAND | help }\n"
" tc [-force] -batch filename\n"
"where OBJECT := { qdisc | class | filter | chain |\n"
@@ -217,7 +217,7 @@ static int do_cmd(int argc, char **argv)
if (matches(*argv, "exec") == 0)
return do_exec(argc-1, argv+1);
if (matches(*argv, "help") == 0) {
- usage();
+ usage(true);
return 0;
}
@@ -282,7 +282,7 @@ int main(int argc, char **argv)
} else if (matches(argv[1], "-iec") == 0) {
++use_iec;
} else if (matches(argv[1], "-help") == 0) {
- usage();
+ usage(true);
return 0;
} else if (matches(argv[1], "-force") == 0) {
++force;
@@ -335,8 +335,8 @@ int main(int argc, char **argv)
return batch(batch_file);
if (argc <= 1) {
- usage();
- return 0;
+ usage(false);
+ return 1;
}
tc_core_init();
diff --git a/tc/tc_class.c b/tc/tc_class.c
index 82f0f85e..49fa1873 100644
--- a/tc/tc_class.c
+++ b/tc/tc_class.c
@@ -34,11 +34,11 @@ struct graph_node {
static struct hlist_head cls_list = {};
static struct hlist_head root_cls_list = {};
-static void usage(void);
+static void usage(bool help);
-static void usage(void)
+static void usage(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: tc class [ add | del | change | replace | show ] dev STRING\n"
" [ classid CLASSID ] [ root | parent CLASSID ]\n"
" [ [ QDISC_KIND ] [ help | OPTIONS ] ]\n"
@@ -103,7 +103,8 @@ static int tc_class_modify(int cmd, unsigned int flags, int argc, char **argv)
if (parse_estimator(&argc, &argv, &est))
return -1;
} else if (matches(*argv, "help") == 0) {
- usage();
+ usage(true);
+ return 0;
} else {
strncpy(k, *argv, sizeof(k)-1);
@@ -128,8 +129,10 @@ static int tc_class_modify(int cmd, unsigned int flags, int argc, char **argv)
return 1;
} else {
if (argc) {
- if (matches(*argv, "help") == 0)
- usage();
+ if (matches(*argv, "help") == 0) {
+ usage(true);
+ return 0;
+ }
fprintf(stderr, "Garbage instead of arguments \"%s ...\". Try \"tc class help\".", *argv);
return -1;
}
@@ -434,7 +437,8 @@ static int tc_class_list(int argc, char **argv)
invarg("invalid parent ID", *argv);
req.t.tcm_parent = handle;
} else if (matches(*argv, "help") == 0) {
- usage();
+ usage(true);
+ return 0;
} else {
fprintf(stderr, "What is \"%s\"? Try \"tc class help\".\n", *argv);
return -1;
@@ -484,7 +488,7 @@ int do_class(int argc, char **argv)
|| matches(*argv, "lst") == 0)
return tc_class_list(argc-1, argv+1);
if (matches(*argv, "help") == 0) {
- usage();
+ usage(true);
return 0;
}
fprintf(stderr, "Command \"%s\" is unknown, try \"tc class help\".\n", *argv);
diff --git a/tc/tc_exec.c b/tc/tc_exec.c
index fe9fdb1b..edc3c982 100644
--- a/tc/tc_exec.c
+++ b/tc/tc_exec.c
@@ -17,9 +17,9 @@
static struct exec_util *exec_list;
static void *BODY;
-static void usage(void)
+static void usage(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: tc exec [ EXEC_TYPE ] [ help | OPTIONS ]\n"
"Where:\n"
"EXEC_TYPE := { bpf | etc. }\n"
@@ -89,7 +89,7 @@ int do_exec(int argc, char **argv)
}
if (matches(*argv, "help") == 0) {
- usage();
+ usage(true);
return 0;
}
diff --git a/tc/tc_filter.c b/tc/tc_filter.c
index 7b504029..36d51222 100644
--- a/tc/tc_filter.c
+++ b/tc/tc_filter.c
@@ -20,9 +20,9 @@
#include "tc_util.h"
#include "tc_common.h"
-static void usage(void)
+static void usage(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: tc filter [ add | del | change | replace | show ] [ dev STRING ]\n"
" tc filter [ add | del | change | replace | show ] [ block BLOCK_INDEX ]\n"
" tc filter get dev STRING parent CLASSID protocol PROTO handle FILTERID pref PRIO FILTER_TYPE\n"
@@ -40,9 +40,9 @@ static void usage(void)
"OPTIONS := ... try tc filter add <desired FILTER_KIND> help\n");
}
-static void chain_usage(void)
+static void chain_usage(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: tc chain [ add | del | get | show ] [ dev STRING ]\n"
" tc chain [ add | del | get | show ] [ block BLOCK_INDEX ] ]\n");
}
@@ -166,7 +166,7 @@ static int tc_filter_modify(int cmd, unsigned int flags, int argc, char **argv)
if (parse_estimator(&argc, &argv, &est) < 0)
return -1;
} else if (matches(*argv, "help") == 0) {
- usage();
+ usage(true);
return 0;
} else {
strncpy(k, *argv, sizeof(k)-1);
@@ -211,8 +211,10 @@ static int tc_filter_modify(int cmd, unsigned int flags, int argc, char **argv)
return -1;
}
if (argc) {
- if (matches(*argv, "help") == 0)
- usage();
+ if (matches(*argv, "help") == 0) {
+ usage(true);
+ return 0;
+ }
fprintf(stderr,
"Garbage instead of arguments \"%s ...\". Try \"tc filter help\".\n",
*argv);
@@ -491,7 +493,7 @@ static int tc_filter_get(int cmd, unsigned int flags, int argc, char **argv)
invarg("invalid chain index value", *argv);
chain_index_set = 1;
} else if (matches(*argv, "help") == 0) {
- usage();
+ usage(true);
return 0;
} else {
if (!**argv)
@@ -562,8 +564,10 @@ static int tc_filter_get(int cmd, unsigned int flags, int argc, char **argv)
}
if (argc) {
- if (matches(*argv, "help") == 0)
- usage();
+ if (matches(*argv, "help") == 0) {
+ usage(true);
+ return 0;
+ }
fprintf(stderr,
"Garbage instead of arguments \"%s ...\". Try \"tc filter help\".\n",
*argv);
@@ -689,7 +693,8 @@ static int tc_filter_list(int cmd, int argc, char **argv)
filter_chain_index_set = 1;
filter_chain_index = chain_index;
} else if (matches(*argv, "help") == 0) {
- usage();
+ usage(true);
+ return 0;
} else {
fprintf(stderr,
" What is \"%s\"? Try \"tc filter help\"\n",
@@ -769,7 +774,7 @@ int do_filter(int argc, char **argv)
|| matches(*argv, "lst") == 0)
return tc_filter_list(RTM_GETTFILTER, argc-1, argv+1);
if (matches(*argv, "help") == 0) {
- usage();
+ usage(true);
return 0;
}
fprintf(stderr, "Command \"%s\" is unknown, try \"tc filter help\".\n",
@@ -794,7 +799,7 @@ int do_chain(int argc, char **argv)
matches(*argv, "lst") == 0) {
return tc_filter_list(RTM_GETCHAIN, argc - 1, argv + 1);
} else if (matches(*argv, "help") == 0) {
- chain_usage();
+ chain_usage(true);
return 0;
}
fprintf(stderr, "Command \"%s\" is unknown, try \"tc chain help\".\n",
diff --git a/tc/tc_monitor.c b/tc/tc_monitor.c
index 5b9bccbe..c2c8a43c 100644
--- a/tc/tc_monitor.c
+++ b/tc/tc_monitor.c
@@ -20,12 +20,13 @@
#include "tc_common.h"
-static void usage(void) __attribute__((noreturn));
+static void usage(bool help) __attribute__((noreturn));
-static void usage(void)
+static void usage(bool help)
{
- fprintf(stderr, "Usage: tc [-timestamp [-tshort] monitor\n");
- exit(-1);
+ fprintf(help ? stdout : stderr,
+ "Usage: tc [-timestamp [-tshort] monitor\n");
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
@@ -77,7 +78,7 @@ int do_tcmonitor(int argc, char **argv)
file = *argv;
} else {
if (matches(*argv, "help") == 0) {
- usage();
+ usage(true);
} else {
fprintf(stderr, "Argument \"%s\" is unknown, try \"tc monitor help\".\n", *argv);
exit(-1);
diff --git a/tc/tc_qdisc.c b/tc/tc_qdisc.c
index 7c3e7cb3..f089c2fc 100644
--- a/tc/tc_qdisc.c
+++ b/tc/tc_qdisc.c
@@ -21,9 +21,9 @@
#include "tc_util.h"
#include "tc_common.h"
-static int usage(void)
+static int usage(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: tc qdisc [ add | del | replace | change | show ] dev STRING\n"
" [ handle QHANDLE ] [ root | ingress | clsact | parent CLASSID ]\n"
" [ estimator INTERVAL TIME_CONSTANT ]\n"
@@ -37,7 +37,7 @@ static int usage(void)
"OPTIONS := ... try tc qdisc add <desired QDISC_KIND> help\n"
"STAB_OPTIONS := ... try tc qdisc add stab help\n"
"QDISC_ID := { root | ingress | handle QHANDLE | parent CLASSID }\n");
- return -1;
+ return help ? 0 : -1;
}
static int tc_qdisc_modify(int cmd, unsigned int flags, int argc, char **argv)
@@ -131,7 +131,7 @@ static int tc_qdisc_modify(int cmd, unsigned int flags, int argc, char **argv)
if (get_u32(&egress_block, *argv, 0) || !egress_block)
invarg("invalid egress block index value", *argv);
} else if (matches(*argv, "help") == 0) {
- usage();
+ return usage(true);
} else {
strncpy(k, *argv, sizeof(k)-1);
@@ -165,7 +165,7 @@ static int tc_qdisc_modify(int cmd, unsigned int flags, int argc, char **argv)
} else {
if (argc) {
if (matches(*argv, "help") == 0)
- usage();
+ return usage(true);
fprintf(stderr, "Garbage instead of arguments \"%s ...\". Try \"tc qdisc help\".\n", *argv);
return -1;
@@ -397,7 +397,7 @@ static int tc_qdisc_list(int argc, char **argv)
invarg("invalid handle ID", *argv);
filter_handle = handle;
} else if (matches(*argv, "help") == 0) {
- usage();
+ return usage(true);
} else if (strcmp(*argv, "invisible") == 0) {
dump_invisible = true;
} else {
@@ -459,7 +459,7 @@ int do_qdisc(int argc, char **argv)
|| matches(*argv, "lst") == 0)
return tc_qdisc_list(argc-1, argv+1);
if (matches(*argv, "help") == 0) {
- usage();
+ usage(true);
return 0;
}
fprintf(stderr, "Command \"%s\" is unknown, try \"tc qdisc help\".\n", *argv);
diff --git a/tc/tc_stab.c b/tc/tc_stab.c
index a7733726..7cdef0ef 100644
--- a/tc/tc_stab.c
+++ b/tc/tc_stab.c
@@ -22,9 +22,11 @@
#include "tc_core.h"
#include "tc_common.h"
-static void stab_help(void)
+static void stab_help(bool help) __attribute__((noreturn));
+
+static void stab_help(bool help)
{
- fprintf(stderr,
+ fprintf(help ? stdout : stderr,
"Usage: ... stab [ mtu BYTES ] [ tsize SLOTS ] [ mpu BYTES ]\n"
" [ overhead BYTES ] [ linklayer TYPE ] ...\n"
" mtu : max packet size we create rate map for {2047}\n"
@@ -34,6 +36,7 @@ static void stab_help(void)
" linklayer : adapting to a linklayer e.g. atm\n"
"Example: ... stab overhead 20 linklayer atm\n");
+ exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
}
int check_size_table_opts(struct tc_sizespec *s)
@@ -49,10 +52,8 @@ int parse_size_table(int *argcp, char ***argvp, struct tc_sizespec *sp)
struct tc_sizespec s = {};
NEXT_ARG();
- if (matches(*argv, "help") == 0) {
- stab_help();
- return -1;
- }
+ if (matches(*argv, "help") == 0)
+ stab_help(true);
while (argc > 0) {
if (matches(*argv, "mtu") == 0) {
NEXT_ARG();
--
2.53.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-08-07 15:43 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-07 15:42 [PATCH iproute2-next 0/7] cleanup help and exit codes Stephen Hemminger
2026-08-07 15:42 ` [PATCH iproute2-next 1/7] ip: follow Linux convention for help vs usage Stephen Hemminger
2026-08-07 15:42 ` [PATCH iproute2-next 2/7] ip/routel: follow help vs usage convention Stephen Hemminger
2026-08-07 15:42 ` [PATCH iproute2-next 3/7] misc: put help to stdout and usage to stderr Stephen Hemminger
2026-08-07 15:42 ` [PATCH iproute2-next 4/7] netshaper: " Stephen Hemminger
2026-08-07 15:42 ` [PATCH iproute2-next 5/7] bridge: " Stephen Hemminger
2026-08-07 15:42 ` [PATCH iproute2-next 6/7] genl: " Stephen Hemminger
2026-08-07 15:42 ` [PATCH iproute2-next 7/7] tc: " Stephen Hemminger
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox