Print this page
4585 dladm(1m) needs a 'help' subcommand
3755 dladm show-aggr documentation
3374 usage of 'dladm' does not match to its man page

@@ -81,10 +81,11 @@
 #define MAXLINELEN              1024
 #define SMF_UPGRADE_FILE                "/var/svc/profile/upgrade"
 #define SMF_UPGRADEDATALINK_FILE        "/var/svc/profile/upgrade_datalink"
 #define SMF_DLADM_UPGRADE_MSG           " # added by dladm(1M)"
 #define DLADM_DEFAULT_COL       80
+#define DLADM_DEFAULT_CMD       "show-link"
 
 /*
  * used by the wifi show-* commands to set up ofmt_field_t structures.
  */
 #define WIFI_CMD_SCAN           0x00000001

@@ -217,10 +218,11 @@
 static cmdfunc_t do_show_usage;
 static cmdfunc_t do_create_bridge, do_modify_bridge, do_delete_bridge;
 static cmdfunc_t do_add_bridge, do_remove_bridge, do_show_bridge;
 static cmdfunc_t do_create_iptun, do_modify_iptun, do_delete_iptun;
 static cmdfunc_t do_show_iptun, do_up_iptun, do_down_iptun;
+static cmdfunc_t do_help;
 
 static void     do_up_vnic_common(int, char **, const char *, boolean_t);
 
 static int show_part(dladm_handle_t, datalink_id_t, void *);
 

@@ -265,12 +267,12 @@
 
 static cmd_t    cmds[] = {
         { "rename-link",        do_rename_link,
             "    rename-link      <oldlink> <newlink>"                  },
         { "show-link",          do_show_link,
-            "    show-link        [-pP] [-o <field>,..] [-s [-i <interval>]] "
-            "[<link>]\n"                                                },
+            "    show-link        [-P] [[-p] -o <field>,..] "
+            "[-s [-i <interval>]] [<link>]"                             },
         { "create-aggr",        do_create_aggr,
             "    create-aggr      [-t] [-P <policy>] [-L <mode>] [-T <time>] "
             "[-u <address>]\n"
             "\t\t     -l <link> [-l <link>...] <link>"                  },
         { "delete-aggr",        do_delete_aggr,

@@ -282,87 +284,87 @@
         { "modify-aggr",        do_modify_aggr,
             "    modify-aggr      [-t] [-P <policy>] [-L <mode>] [-T <time>] "
             "[-u <address>]\n"
             "\t\t     <link>"                                           },
         { "show-aggr",          do_show_aggr,
-            "    show-aggr        [-pPLx] [-o <field>,..] [-s [-i <interval>]] "
-            "[<link>]\n"                                                },
+            "    show-aggr        [-PLx] [[-p] -o <field>,..] "
+            "[-s [-i <interval>]] [<link>]"                             },
         { "up-aggr",            do_up_aggr,     NULL                    },
         { "scan-wifi",          do_scan_wifi,
-            "    scan-wifi        [-p] [-o <field>,...] [<link>]"       },
+            "    scan-wifi        [[-p] -o <field>,...] [<link>]"       },
         { "connect-wifi",       do_connect_wifi,
             "    connect-wifi     [-e <essid>] [-i <bssid>] [-k <key>,...] "
             "[-s wep|wpa]\n"
             "\t\t     [-a open|shared] [-b bss|ibss] [-c] [-m a|b|g] "
             "[-T <time>]\n"
             "\t\t     [<link>]"                                         },
         { "disconnect-wifi",    do_disconnect_wifi,
             "    disconnect-wifi  [-a] [<link>]"                        },
         { "show-wifi",          do_show_wifi,
-            "    show-wifi        [-p] [-o <field>,...] [<link>]\n"     },
+            "    show-wifi        [[-p] -o <field>,...] [<link>]"       },
         { "set-linkprop",       do_set_linkprop,
             "    set-linkprop     [-t] -p <prop>=<value>[,...] <name>"  },
         { "reset-linkprop",     do_reset_linkprop,
             "    reset-linkprop   [-t] [-p <prop>,...] <name>"          },
         { "show-linkprop",      do_show_linkprop,
             "    show-linkprop    [-cP] [-o <field>,...] [-p <prop>,...] "
-            "<name>\n"                                                  },
+            "<name>"                                                    },
         { "show-ether",         do_show_ether,
-            "    show-ether       [-px][-o <field>,...] <link>\n"       },
+            "    show-ether       [-x] [[-p] -o <field>,...] <link>"    },
         { "create-secobj",      do_create_secobj,
             "    create-secobj    [-t] [-f <file>] -c <class> <secobj>" },
         { "delete-secobj",      do_delete_secobj,
             "    delete-secobj    [-t] <secobj>[,...]"                  },
         { "show-secobj",        do_show_secobj,
-            "    show-secobj      [-pP] [-o <field>,...] [<secobj>,...]\n" },
+            "    show-secobj      [-P] [[-p] -o <field>,...] [<secobj>,...]" },
         { "init-linkprop",      do_init_linkprop,       NULL            },
         { "init-secobj",        do_init_secobj,         NULL            },
         { "create-vlan",        do_create_vlan,
             "    create-vlan      [-ft] -l <link> -v <vid> [link]"      },
         { "delete-vlan",        do_delete_vlan,
             "    delete-vlan      [-t] <link>"                          },
         { "show-vlan",          do_show_vlan,
-            "    show-vlan        [-pP] [-o <field>,..] [<link>]\n"     },
+            "    show-vlan        [-P] [[-p] -o <field>,...] [<link>]"  },
         { "up-vlan",            do_up_vlan,             NULL            },
         { "create-iptun",       do_create_iptun,
             "    create-iptun     [-t] -T <type> "
             "[-a {local|remote}=<addr>,...] <link>]" },
         { "delete-iptun",       do_delete_iptun,
             "    delete-iptun     [-t] <link>"                          },
         { "modify-iptun",       do_modify_iptun,
             "    modify-iptun     [-t] -a {local|remote}=<addr>,... <link>" },
         { "show-iptun",         do_show_iptun,
-            "    show-iptun       [-pP] [-o <field>,..] [<link>]\n"     },
+            "    show-iptun       [-P] [[-p] -o <field>,...] [<link>]"  },
         { "up-iptun",           do_up_iptun,            NULL            },
         { "down-iptun",         do_down_iptun,          NULL            },
         { "delete-phys",        do_delete_phys,
             "    delete-phys      <link>"                               },
         { "show-phys",          do_show_phys,
-            "    show-phys        [-pP] [-o <field>,..] [-H] [<link>]\n"},
+            "    show-phys        [-P] [[-p] -o <field>,...] [-H] [<link>]" },
         { "init-phys",          do_init_phys,           NULL            },
         { "show-linkmap",       do_show_linkmap,        NULL            },
         { "create-vnic",        do_create_vnic,
             "    create-vnic      [-t] -l <link> [-m <value> | auto |\n"
             "\t\t     {factory [-n <slot-id>]} | {random [-r <prefix>]} |\n"
             "\t\t     {vrrp -V <vrid> -A {inet | inet6}} [-v <vid> [-f]]\n"
-            "\t\t     [-p <prop>=<value>[,...]] <vnic-link>"    },
+            "\t\t     [-p <prop>=<value>[,...]] [-R root-dir] <vnic-link>" },
         { "delete-vnic",        do_delete_vnic,
             "    delete-vnic      [-t] <vnic-link>"                     },
         { "show-vnic",          do_show_vnic,
-            "    show-vnic        [-pP] [-l <link>] [-s [-i <interval>]] "
-            "[<link>]\n"                                                },
+            "    show-vnic        [-P] [[-p] -o <field>,...] [-l <link>] "
+            "[-s [-i <interval>]] [<link>]"                             },
         { "up-vnic",            do_up_vnic,             NULL            },
         { "create-part",        do_create_part,
             "    create-part      [-t] [-f] -l <link> [-P <pkey>]\n"
             "\t\t     [-R <root-dir>] <part-link>"                      },
         { "delete-part",        do_delete_part,
             "    delete-part      [-t] [-R <root-dir>] <part-link>"},
         { "show-part",          do_show_part,
-            "    show-part        [-pP] [-o <field>,...][-l <linkover>]\n"
+            "    show-part        [-P] [[-p] -o <field>,...] [-l <linkover>]\n"
             "\t\t     [<part-link>]"            },
         { "show-ib",            do_show_ib,
-            "    show-ib          [-p] [-o <field>,...] [<link>]\n"     },
+            "    show-ib          [[-p] -o <field>,...] [<link>]"       },
         { "up-part",            do_up_part,             NULL            },
         { "create-etherstub",   do_create_etherstub,
             "    create-etherstub [-t] <link>"                          },
         { "delete-etherstub",   do_delete_etherstub,
             "    delete-etherstub [-t] <link>"                          },

@@ -390,22 +392,24 @@
             "<bridge>"                                                  },
         { "remove-bridge",      do_remove_bridge,
             "    remove-bridge    [-R <root-dir>] -l <link> [-l <link>]... "
             "<bridge>"                                                  },
         { "show-bridge",        do_show_bridge,
-            "    show-bridge      [-p] [-o <field>,...] [-s [-i <interval>]] "
+            "    show-bridge      [[-p] -o <field>,...] [-s [-i <interval>]] "
             "[<bridge>]\n"
-            "    show-bridge      -l [-p] [-o <field>,...] [-s [-i <interval>]]"
+            "    show-bridge      -l [[-p] -o <field>,...] [-s [-i <interval>]]"
             " <bridge>\n"
-            "    show-bridge      -f [-p] [-o <field>,...] [-s [-i <interval>]]"
+            "    show-bridge      -f [[-p] -o <field>,...] [-s [-i <interval>]]"
             " <bridge>\n"
-            "    show-bridge      -t [-p] [-o <field>,...] [-s [-i <interval>]]"
-            " <bridge>\n"                                               },
+            "    show-bridge      -t [[-p] -o <field>,...] [-s [-i <interval>]]"
+            " <bridge>"                                                 },
         { "show-usage",         do_show_usage,
             "    show-usage       [-a] [-d | -F <format>] "
             "[-s <DD/MM/YYYY,HH:MM:SS>]\n"
-            "\t\t     [-e <DD/MM/YYYY,HH:MM:SS>] -f <logfile> [<link>]" }
+            "\t\t     [-e <DD/MM/YYYY,HH:MM:SS>] -f <logfile> [<link>]" },
+        { "help",               do_help,
+            "    help             [<subcommand>]"                       }
 };
 
 static const struct option lopts[] = {
         {"vlan-id",     required_argument,      0, 'v'},
         {"output",      required_argument,      0, 'o'},

@@ -1134,11 +1138,10 @@
 { "BANDWIDTH",  15,
         offsetof(usage_fields_buf_t, usage_bandwidth), print_default_cb},
 { NULL,         0, 0, NULL}}
 ;
 
-
 /*
  * structures for 'dladm show-usage link'
  */
 
 typedef struct  usage_l_fields_buf_s {

@@ -1437,19 +1440,12 @@
 #define DLADM_IS_ETHERSTUB(id)  (id == DATALINK_INVALID_LINKID)
 
 static void
 usage(void)
 {
-        int     i;
-        cmd_t   *cmdp;
-        (void) fprintf(stderr, gettext("usage:  dladm <subcommand> <args> ..."
-            "\n"));
-        for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) {
-                cmdp = &cmds[i];
-                if (cmdp->c_usage != NULL)
-                        (void) fprintf(stderr, "%s\n", gettext(cmdp->c_usage));
-        }
+        (void) fprintf(stderr, gettext("For more information, run: %s help\n"),
+            progname);
 
         /* close dladm handle if it was opened */
         if (handle != NULL)
                 dladm_close(handle);
 

@@ -1469,12 +1465,14 @@
 #endif
         (void) textdomain(TEXT_DOMAIN);
 
         progname = argv[0];
 
-        if (argc < 2)
-                usage();
+        if (argc < 2) {
+                argv[1] = DLADM_DEFAULT_CMD;
+                argc++;
+        }
 
         for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) {
                 cmdp = &cmds[i];
                 if (strcmp(argv[1], cmdp->c_name) == 0) {
                         /* Open the libdladm handle */

@@ -1494,10 +1492,68 @@
             progname, argv[1]);
         usage();
         return (EXIT_FAILURE);
 }
 
+static int
+help_compare(const void *cmd1, const void *cmd2)
+{
+        cmd_t   *cmd1p = (cmd_t *)cmd1;
+        cmd_t   *cmd2p = (cmd_t *)cmd2;
+
+        return (strcmp(cmd1p->c_name, cmd2p->c_name));
+}
+
+static void
+do_help(int argc, char *argv[], const char *use)
+{
+        size_t          nelems;
+        int             i, j, ncols = 3;
+        boolean_t       found = B_FALSE;
+
+        _NOTE(ARGUNUSED(use));
+
+        nelems = sizeof (cmds) / sizeof (cmd_t);
+
+        if (argc < 2) {
+                qsort(cmds, nelems, sizeof (cmd_t), help_compare);
+
+                (void) fprintf(stderr, gettext(
+                    "usage: dladm help <subcommand>\n"
+                    "Subcommands are:\n"));
+
+                for (i = 0, j = 0; i < nelems; i++) {
+                        if (cmds[i].c_usage == NULL)
+                                continue;
+
+                        (void) fprintf(stderr, "%-20s", cmds[i].c_name);
+
+                        if (++j % ncols == 0)
+                                (void) putc('\n', stderr);
+                }
+
+                if (j % ncols != 0)
+                        (void) putc('\n', stderr);
+        } else {
+                for (i = 0; i < nelems; i++) {
+                        if (strcmp(argv[1], cmds[i].c_name) == 0) {
+                                (void) fprintf(stderr, "usage:\n%s\n",
+                                    gettext(cmds[i].c_usage));
+                                found = B_TRUE;
+                                break;
+                        }
+                }
+
+                if (!found) {
+                        (void) fprintf(stderr, gettext(
+                            "%s: unknown subcommand '%s'\n"),
+                            progname, argv[1]);
+                        usage();
+                }
+        }
+}
+
 /*ARGSUSED*/
 static int
 show_usage_date(dladm_usage_t *usage, void *arg)
 {
         show_usage_state_t      *state = (show_usage_state_t *)arg;