From: Stephen Hemminger <stephen@networkplumber.org>
To: netdev@vger.kernel.org
Cc: dsahern@gmail.com, Stephen Hemminger <stephen@networkplumber.org>
Subject: [PATCH iproute2-next 5/7] bridge: put help to stdout and usage to stderr
Date: Fri, 7 Aug 2026 08:42:28 -0700 [thread overview]
Message-ID: <20260807154306.111200-6-stephen@networkplumber.org> (raw)
In-Reply-To: <20260807154306.111200-1-stephen@networkplumber.org>
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
next prev parent reply other threads:[~2026-08-07 15:43 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
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-11 14:23 ` David Ahern
2026-08-07 15:42 ` [PATCH iproute2-next 4/7] netshaper: " Stephen Hemminger
2026-08-07 15:42 ` Stephen Hemminger [this message]
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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260807154306.111200-6-stephen@networkplumber.org \
--to=stephen@networkplumber.org \
--cc=dsahern@gmail.com \
--cc=netdev@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.