Netdev List
 help / color / mirror / Atom feed
From: Stephen Hemminger <stephen@networkplumber.org>
To: Dmitri Seletski <drjoms@gmail.com>
Cc: netdev@vger.kernel.org
Subject: Re: [PATCH iproute2-next] "ip help" wrong output, exit code.
Date: Thu, 25 Jun 2026 14:34:35 -0700	[thread overview]
Message-ID: <20260625143435.6147e1d9@phoenix.local> (raw)
In-Reply-To: <65f53987-c992-41b9-9603-9e9a448e469d@gmail.com>

On Thu, 25 Jun 2026 16:54:29 +0100
Dmitri Seletski <drjoms@gmail.com> wrote:

> I am confused.
> 
> Whats the next step here?
> 
> Regards
> 
> Dmitri
> 
> On 6/22/26 18:47, Dmitri Seletski wrote:
> > Hello David,
> >
> >
> > Based on change introduced:
> >
> > Two samples of "ip help" with demonstration of exit code and standard 
> > output are below.
> >
> > This is in line with what expect.
> >
> >
> > dimkosPC~/compiled/iproute2-next #if ./ip/ip help a >>/dev/null  ; 
> > then echo help triggered  ; else echo error code triggered  ;fi  #this 
> > redirects standard output  to /dev/null, so text missing is not error,
> > but standard text
> > help triggered
> >
> > dimkosPC~/compiled/iproute2-next #if ./ip/ip help   ; then echo help 
> > triggered  ; else echo error code triggered  ;fi
> > Usage: ip [ OPTIONS ] OBJECT { COMMAND | help }
> >       ip [ -force ] -batch filename
> > where  OBJECT := { address | addrlabel | fou | help | ila | ioam | 
> > l2tp | link |
> >                   macsec | maddress | monitor | mptcp | mroute | mrule |
> >                   neighbor | neighbour | netconf | netns | nexthop | 
> > ntable |
> >                   ntbl | route | rule | sr | stats | tap | tcpmetrics |
> >                   token | tunnel | tuntap | vrf | xfrm }
> >       OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] | -r[esolve] |
> >                    -h[uman-readable] | -iec | -j[son] | -p[retty] |
> >                    -f[amily] { inet | inet6 | mpls | bridge | link } |
> >                    -4 | -6 | -M | -B | -0 |
> >                    -l[oops] { maximum-addr-flush-attempts } | -echo | 
> > -br[ief] |
> >                    -o[neline] | -t[imestamp] | -ts[hort] | -b[atch] 
> > [filename] |
> >                    -rc[vbuf] [size] | -n[etns] name | -N[umeric] | 
> > -a[ll] |
> >                    -c[olor]}
> > help triggered
> >
> > Two samples of command that is broken on purpose.
> >
> > dimkosPC~/compiled/iproute2-next #if ./ip/ip idontexist   ; then echo 
> > help triggered  ; else echo error code triggered  ;fi
> > Object "idontexist" is unknown, try "ip help".
> > error code triggered
> >
> > dimkosPC~/compiled/iproute2-next #if ./ip/ip idontexist  >>/dev/null 
> >  ; then echo help triggered  ; else echo error code triggered  ;fi 
> >  #this redirects standard output  to /dev/null, so text missing is not 
> > error, but standard text
> > Object "idontexist" is unknown, try "ip help".
> > error code triggered
> >
> > This works as expected as per my understanding.
> >
> >
> > Not everything is fixed, but chunk of things fixed is better than non 
> > of it.
> >
> > for example:
> >
> > if ip  add help    ; then echo help triggered  ; else echo error code 
> > triggered  ;fi  #this redirects standard output  to /dev/null, so text 
> > missing is not error, but standard text
> > Usage: ip address {add|change|replace} IFADDR dev IFNAME [ LIFETIME ]
> >                                                      [ CONFFLAG-LIST ]
> >       ip address del IFADDR dev IFNAME [mngtmpaddr]
> >       ip address {save|flush} [ dev IFNAME ] [ scope SCOPE-ID ] [ to 
> > PREFIX ]
> >                            [ FLAG-LIST ] [ label LABEL ] [ { up | down 
> > } ]
> >       ip address [ show [ dev IFNAME ] [ scope SCOPE-ID ] [ master 
> > DEVICE ]
> >                         [ nomaster ]
> >                         [ type TYPE ] [ to PREFIX ] [ FLAG-LIST ]
> >                         [ label LABEL ] [ { up | down } ] [ vrf NAME ]
> >                         [ proto ADDRPROTO ] ]
> >       ip address {showdump|restore}
> > IFADDR := PREFIX | ADDR peer PREFIX
> >          [ broadcast ADDR ] [ anycast ADDR ]
> >          [ label IFNAME ] [ scope SCOPE-ID ] [ metric METRIC ]
> >          [ proto ADDRPROTO ]
> > SCOPE-ID := [ host | link | global | NUMBER ]
> > FLAG-LIST := [ FLAG-LIST ] FLAG
> > FLAG  := [ permanent | dynamic | secondary | primary |
> >           [-]tentative | [-]deprecated | [-]dadfailed | temporary |
> >           CONFFLAG-LIST ]
> > CONFFLAG-LIST := [ CONFFLAG-LIST ] CONFFLAG
> > CONFFLAG  := [ home | nodad | mngtmpaddr | noprefixroute | autojoin ]
> > LIFETIME := [ valid_lft LFT ] [ preferred_lft LFT ]
> > LFT := forever | SECONDS
> > ADDRPROTO := [ NAME | NUMBER ]
> > TYPE := { amt | bareudp | bond | bond_slave | bridge | bridge_slave |
> >          dsa | dummy | erspan | geneve | gre | gretap | gtp | hsr |
> >          ifb | ip6erspan | ip6gre | ip6gretap | ip6tnl |
> >          ipip | ipoib | ipvlan | ipvtap |
> >          macsec | macvlan | macvtap | netdevsim |
> >          netkit | nlmon | pfcp | rmnet | sit | team | team_slave |
> >          vcan | veth | vlan | vrf | vti | vxcan | vxlan | wwan |
> >          xfrm | virt_wifi }
> > error code triggered
> >
> > This is still problematic.
> >
> >
> > But so far code leaves "ip help" command/argument in better shape than 
> > it found it in.
> >
> >
> > I may try improve things more, but lets submit what we already have 
> > "better", please.
> >
> > Kind Regards
> >
> > Dmitri Seletski
> >
> >
> > On 6/22/26 17:44, David Laight wrote:  
> >> On Mon, 22 Jun 2026 07:57:00 -0700
> >> Stephen Hemminger <stephen@networkplumber.org> wrote:
> >>  
> >>> On Sun, 21 Jun 2026 22:48:59 +0100
> >>> Dmitri Seletski <drjoms@gmail.com> wrote:
> >>>  
> >>>>  From 0805e07105cd15c5b94271a4706e50e3c65dbde5 Mon Sep 17 00:00:00 
> >>>> 2001
> >>>> From: Dmitri Seletski <drjoms@gmail.com>
> >>>> Date: Sun, 21 Jun 2026 22:12:43 +0100
> >>>> Subject: [PATCH iproute2-next]  "ip help" wrong output, exit code.
> >>>>
> >>>> Changed output of "ip help" from standard error to standard output. 
> >>>> And
> >>>> Exit is now 0 instead of -1. "ip help|grep bridge" - now gives bridge
> >>>> syntax instead of flooding user with everything from "ip help".
> >>>> ---
> >>>> ip/ip.c | 4 ++--
> >>>> 1 file changed, 2 insertions(+), 2 deletions(-)
> >>>>
> >>>> diff --git a/ip/ip.c b/ip/ip.c
> >>>> index e4b71bde..4627b61c 100644
> >>>> --- a/ip/ip.c
> >>>> +++ b/ip/ip.c
> >>>> @@ -56,7 +56,7 @@ static void usage(void) __attribute__((noreturn));
> >>>>
> >>>> static void usage(void)
> >>>> {
> >>>> -fprintf(stderr,
> >>>> +fprintf(stdout,
> >>>> "Usage: ip [ OPTIONS ] OBJECT { COMMAND | help }\n"
> >>>> "       ip [ -force ] -batch filename\n"
> >>>> "where  OBJECT := { address | addrlabel | fou | help | ila | ioam | 
> >>>> l2tp
> >>>> | link |\n"
> >>>> @@ -72,7 +72,7 @@ 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(0);
> >>>> }  
> >>> Your mailer damages white space.
> >>>  
> >> The output also needs to depend on whether these is a 'usage' error or
> >> if 'help' is requested.
> >> Code code is correct for the former - except it should do exit(1).
> >>
> >>     David
> >>
> >>  
> 

We need to have a broad solution that doesn't look ugly.
There are a couple problems with current code:
  1. Help should exit with 0 (ok); invalid argument should exit with non-zero
     by Gnu convention that is 2 but other commands like git use 129
  2. help should go to stdout; usage on error should go to stderr

The solution should work across iproute2 commands: ip, tc, dpll, tipc, bridge, ...
and the sub commands.

So far the mailing list patches were kind of messy and limited.

  reply	other threads:[~2026-06-25 21:34 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-20  9:36 "ip help" output is an error Dmitri Seletski
2026-06-21 15:21 ` Stephen Hemminger
2026-06-21 21:51   ` Dmitri Seletski
2026-06-22  7:49   ` David Laight
2026-06-22 10:39     ` Dmitri Seletski
     [not found]   ` <069b13e1-f689-410b-bd40-b5e5831b67e7@gmail.com>
2026-06-22 14:57     ` [PATCH iproute2-next] "ip help" wrong output, exit code Stephen Hemminger
2026-06-22 16:44       ` David Laight
2026-06-22 17:47         ` Dmitri Seletski
2026-06-25 15:54           ` Dmitri Seletski
2026-06-25 21:34             ` Stephen Hemminger [this message]
  -- strict thread matches above, loose matches on Subject: below --
2026-06-21 21:56 Dmitri Seletski

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=20260625143435.6147e1d9@phoenix.local \
    --to=stephen@networkplumber.org \
    --cc=drjoms@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