Netdev List
 help / color / mirror / Atom feed
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


  parent reply	other threads:[~2026-08-07 15:43 UTC|newest]

Thread overview: 8+ 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-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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox