]> git.ipfire.org Git - thirdparty/iw.git/commitdiff
separate commands into sections
authorJohannes Berg <johannes@sipsolutions.net>
Mon, 24 Aug 2009 10:53:34 +0000 (12:53 +0200)
committerJohannes Berg <johannes@sipsolutions.net>
Mon, 24 Aug 2009 11:28:55 +0000 (13:28 +0200)
The ad-hoc way of parsing the command "tree" didn't
really work out, so separate the commands better
into sections and parse by that.

13 files changed:
Makefile
connect.c
ibss.c
info.c
interface.c
iw.c
iw.h
link.c
mpath.c
reg.c
scan.c
sections.c [new file with mode: 0644]
station.c

index e356ae49a6d5e2266ac5624f3f358ec278fe49b6..cb5fcc1aa8509862bfaee9f3ad979f68c03ec961 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -18,6 +18,7 @@ OBJS = iw.o genl.o event.o info.o phy.o \
        interface.o ibss.o station.o util.o \
        mesh.o mpath.o scan.o reg.o version.o \
        reason.o status.o connect.o link.o
+OBJS += sections.o
 ALL = iw
 
 NL1FOUND := $(shell $(PKG_CONFIG) --atleast-version=1 libnl-1 && echo Y)
index 91be62ac16af68556eeadb2cfdb48573a758c955..ced289fad961393717966d4a8bad8ea3b063751b 100644 (file)
--- a/connect.c
+++ b/connect.c
@@ -67,7 +67,6 @@ static int disconnect(struct nl80211_state *state,
 TOPLEVEL(disconnect, NULL,
        NL80211_CMD_DISCONNECT, 0, CIB_NETDEV, disconnect,
        "Disconnect from the current network.");
-HIDDEN(conn, establish, "", NL80211_CMD_CONNECT, 0, CIB_NETDEV, iw_conn);
 
 static int iw_connect(struct nl80211_state *state, struct nl_cb *cb,
                      struct nl_msg *msg, int argc, char **argv)
@@ -97,7 +96,7 @@ static int iw_connect(struct nl80211_state *state, struct nl_cb *cb,
        if (!conn_argv)
                return -ENOMEM;
        conn_argv[0] = dev;
-       conn_argv[1] = "conn";
+       conn_argv[1] = "connect";
        conn_argv[2] = "establish";
        for (i = 0; i < argc; i++)
                conn_argv[i + 3] = argv[i];
@@ -138,3 +137,4 @@ TOPLEVEL(connect, "[-w] <SSID> [<freq in MHz>] [<bssid>] [key 0:abcde d:1:616263
        0, 0, CIB_NETDEV, iw_connect,
        "Join the network with the given SSID (and frequency, BSSID).\n"
        "With -w, wait for the connect to finish or fail.");
+HIDDEN(connect, establish, "", NL80211_CMD_CONNECT, 0, CIB_NETDEV, iw_conn);
diff --git a/ibss.c b/ibss.c
index 8785e7acaffd68fa0767f00e48f2cb500ae74b53..4715ac81b65ec6819c7d16d70475138f12999e71 100644 (file)
--- a/ibss.c
+++ b/ibss.c
@@ -9,6 +9,8 @@
 #include "nl80211.h"
 #include "iw.h"
 
+SECTION(ibss);
+
 static int join_ibss(struct nl80211_state *state,
                     struct nl_cb *cb,
                     struct nl_msg *msg,
diff --git a/info.c b/info.c
index 1b5e44315f3606bcef2cb3dda29097d54fe97af6..7bca69dc6e83fe1ecbc0a7461fb255c02981a045 100644 (file)
--- a/info.c
+++ b/info.c
@@ -282,7 +282,7 @@ static int handle_info(struct nl80211_state *state,
 
        return 0;
 }
-TOPLEVEL(info, NULL, NL80211_CMD_GET_WIPHY, 0, CIB_PHY, handle_info,
+__COMMAND(NULL, info, "info", NULL, NL80211_CMD_GET_WIPHY, 0, 0, CIB_PHY, handle_info,
         "Show capabilities for the specified wireless device.");
 TOPLEVEL(list, NULL, NL80211_CMD_GET_WIPHY, NLM_F_DUMP, CIB_NONE, handle_info,
         "List all wireless devices and their capabilities.");
index d3f6e2def30efcc259ffabbc0f56bd8082c121ce..bf1335adb1a5c8e8e7227b593d62ac7bafc4d242 100644 (file)
@@ -18,6 +18,8 @@
                        "otherbss: show frames from other BSSes\n"\
                        "cook:     use cooked mode"
 
+SECTION(interface);
+
 static char *mntr_flags[NL80211_MNTR_FLAG_MAX + 1] = {
        "none",
        "fcsfail",
diff --git a/iw.c b/iw.c
index 2525492e18446a982f081f6ff4438417237037c2..8fcf2f61a2c560cccb5b6eaea70cf3d44d4d8e47 100644 (file)
--- a/iw.c
+++ b/iw.c
@@ -94,12 +94,17 @@ static void nl80211_cleanup(struct nl80211_state *state)
        nl_socket_free(state->nl_sock);
 }
 
-__COMMAND(NULL, NULL, "", NULL, 0, 0, 0, CIB_NONE, NULL, NULL);
-__COMMAND(NULL, NULL, "", NULL, 1, 0, 0, CIB_NONE, NULL, NULL);
-
 static int cmd_size;
 
-static void __usage_cmd(struct cmd *cmd, char *indent, bool full)
+extern struct cmd __start___cmd;
+extern struct cmd __stop___cmd;
+
+#define for_each_cmd(_cmd)                                     \
+       for (_cmd = &__start___cmd; _cmd < &__stop___cmd;               \
+            _cmd = (const struct cmd *)((char *)_cmd + cmd_size))
+
+
+static void __usage_cmd(const struct cmd *cmd, char *indent, bool full)
 {
        const char *start, *lend, *end;
 
@@ -115,8 +120,8 @@ static void __usage_cmd(struct cmd *cmd, char *indent, bool full)
                printf("dev <devname> ");
                break;
        }
-       if (cmd->section)
-               printf("%s ", cmd->section);
+       if (cmd->parent && cmd->parent->name)
+               printf("%s ", cmd->parent->name);
        printf("%s", cmd->name);
        if (cmd->args)
                printf(" %s", cmd->args);
@@ -156,17 +161,26 @@ static const char *argv0;
 
 static void usage(bool full)
 {
-       struct cmd *cmd;
+       const struct cmd *section, *cmd;
 
        printf("Usage:\t%s [options] command\n", argv0);
        usage_options();
        printf("\t--version\tshow version (%s)\n", iw_version);
        printf("Commands:\n");
-       for (cmd = &__start___cmd; cmd < &__stop___cmd;
-            cmd = (struct cmd *)((char *)cmd + cmd_size)) {
-               if (!cmd->handler || cmd->hidden)
+       for_each_cmd(section) {
+               if (section->parent)
                        continue;
-               __usage_cmd(cmd, "\t", full);
+
+               if (section->handler && !section->hidden)
+                       __usage_cmd(section, "\t", full);
+
+               for_each_cmd(cmd) {
+                       if (section != cmd->parent)
+                               continue;
+                       if (!cmd->handler || cmd->hidden)
+                               continue;
+                       __usage_cmd(cmd, "\t", full);
+               }
        }
        printf("\nYou can omit the 'phy' or 'dev' if "
                        "the identification is unique,\n"
@@ -186,7 +200,7 @@ static int print_help(struct nl80211_state *state,
 TOPLEVEL(help, NULL, 0, 0, CIB_NONE, print_help,
         "Print usage for each command.");
 
-static void usage_cmd(struct cmd *cmd)
+static void usage_cmd(const struct cmd *cmd)
 {
        printf("Usage:\t%s [options] ", argv0);
        __usage_cmd(cmd, "", true);
@@ -238,9 +252,9 @@ static int ack_handler(struct nl_msg *msg, void *arg)
 }
 
 static int __handle_cmd(struct nl80211_state *state, enum id_input idby,
-                       int argc, char **argv, struct cmd **cmdout)
+                       int argc, char **argv, const struct cmd **cmdout)
 {
-       struct cmd *cmd, *match = NULL;
+       const struct cmd *cmd, *match = NULL, *sectcmd;
        struct nl_cb *cb;
        struct nl_msg *msg;
        int devidx = 0;
@@ -285,44 +299,61 @@ static int __handle_cmd(struct nl80211_state *state, enum id_input idby,
        if (devidx < 0)
                return -errno;
 
-       section = command = *argv;
+       section = *argv;
        argc--;
        argv++;
 
-       for (cmd = &__start___cmd; cmd < &__stop___cmd;
-            cmd = (struct cmd *)((char *)cmd + cmd_size)) {
-               if (!cmd->handler)
+       for_each_cmd(sectcmd) {
+               if (sectcmd->parent)
                        continue;
-               if (cmd->idby != command_idby)
+               /* ok ... bit of a hack for the dupe 'info' section */
+               if (match && sectcmd->idby != command_idby)
                        continue;
-               if (cmd->section) {
-                       if (strcmp(cmd->section, section))
+               if (strcmp(sectcmd->name, section) == 0)
+                       match = sectcmd;
+       }
+
+       sectcmd = match;
+       match = NULL;
+       if (!sectcmd)
+               return 1;
+
+       if (argc > 0) {
+               command = *argv;
+
+               for_each_cmd(cmd) {
+                       if (!cmd->handler)
                                continue;
-                       /* this is a bit icky ... */
-                       if (command == section) {
-                               if (argc <= 0) {
-                                       if (match)
-                                               break;
-                                       return 1;
-                               }
-                               command = *argv;
-                               argc--;
-                               argv++;
-                       }
-               } else if (section != command)
-                       continue;
-               if (strcmp(cmd->name, command))
-                       continue;
-               if (argc && !cmd->args)
-                       continue;
+                       if (cmd->parent != sectcmd)
+                               continue;
+                       if (cmd->idby != command_idby)
+                               continue;
+                       if (strcmp(cmd->name, command))
+                               continue;
+                       if (argc > 1 && !cmd->args)
+                               continue;
+                       match = cmd;
+                       break;
+               }
 
-               match = cmd;
+               if (match) {
+                       argc--;
+                       argv++;
+               }
        }
 
-       cmd = match;
-
-       if (!cmd)
-               return 1;
+       if (match)
+               cmd = match;
+       else {
+               /* Use the section itself, if possible. */
+               cmd = sectcmd;
+               if (argc && !cmd->args)
+                       return 1;
+               if (cmd->idby != command_idby)
+                       return 1;
+               if (!cmd->handler)
+                       return 1;
+       }
 
        if (cmdout)
                *cmdout = cmd;
@@ -396,11 +427,10 @@ int main(int argc, char **argv)
 {
        struct nl80211_state nlstate;
        int err;
-       struct cmd *cmd = NULL;
+       const struct cmd *cmd = NULL;
 
        /* calculate command size including padding */
-       cmd_size = abs((long)&__cmd_NULL_NULL_1_CIB_NONE_0
-                    - (long)&__cmd_NULL_NULL_0_CIB_NONE_0);
+       cmd_size = abs((long)&__section_set - (long)&__section_get);
        /* strip off self */
        argc--;
        argv0 = *argv++;
diff --git a/iw.h b/iw.h
index 94948ec9646b32a7fdf4129f515513d17bc82be8..511a1db2a395843f6a9b78aff93a674c6a877936 100644 (file)
--- a/iw.h
+++ b/iw.h
@@ -35,7 +35,6 @@ enum id_input {
 };
 
 struct cmd {
-       const char *section;
        const char *name;
        const char *args;
        const char *help;
@@ -52,6 +51,7 @@ struct cmd {
                       struct nl_cb *cb,
                       struct nl_msg *msg,
                       int argc, char **argv);
+       const struct cmd *parent;
 };
 
 #define ARRAY_SIZE(ar) (sizeof(ar)/sizeof(ar[0]))
@@ -60,7 +60,6 @@ struct cmd {
        static const struct cmd                                         \
        __cmd ## _ ## _symname ## _ ## _handler ## _ ## _nlcmd ## _ ## _idby ## _ ## _hidden\
        __attribute__((used)) __attribute__((section("__cmd"))) = {     \
-               .section = (_section),                                  \
                .name = (_name),                                        \
                .args = (_args),                                        \
                .cmd = (_nlcmd),                                        \
@@ -69,15 +68,34 @@ struct cmd {
                .idby = (_idby),                                        \
                .handler = (_handler),                                  \
                .help = (_help),                                        \
+               .parent = _section,                                     \
         }
 #define COMMAND(section, name, args, cmd, flags, idby, handler, help)  \
-       __COMMAND(#section, name, #name, args, cmd, flags, 0, idby, handler, help)
+       __COMMAND(&(__section ## _ ## section), name, #name, args, cmd, flags, 0, idby, handler, help)
 #define HIDDEN(section, name, args, cmd, flags, idby, handler)         \
-       __COMMAND(#section, name, #name, args, cmd, flags, 1, idby, handler, NULL)
-#define TOPLEVEL(name, args, cmd, flags, idby, handler, help)          \
-       __COMMAND(NULL, name, #name, args, cmd, flags, 0, idby, handler, help)
-extern struct cmd __start___cmd;
-extern struct cmd __stop___cmd;
+       __COMMAND(&(__section ## _ ## section), name, #name, args, cmd, flags, 1, idby, handler, NULL)
+
+#define TOPLEVEL(_name, _args, _nlcmd, _flags, _idby, _handler, _help) \
+       const struct cmd                                                \
+       __section ## _ ## _name                                         \
+       __attribute__((used)) __attribute__((section("__cmd"))) = {     \
+               .name = (#_name),                                       \
+               .args = (_args),                                        \
+               .cmd = (_nlcmd),                                        \
+               .nl_msg_flags = (_flags),                               \
+               .idby = (_idby),                                        \
+               .handler = (_handler),                                  \
+               .help = (_help),                                        \
+        }
+#define SECTION(_name)                                                 \
+       const struct cmd __section ## _ ## _name                        \
+       __attribute__((used)) __attribute__((section("__cmd"))) = {     \
+               .name = (#_name),                                       \
+               .hidden = 1,                                            \
+       }
+
+#define DECLARE_SECTION(_name)                                         \
+       extern const struct cmd __section ## _ ## _name;
 
 extern const char iw_version[];
 
@@ -125,4 +143,8 @@ enum print_ie_type {
 void print_ies(unsigned char *ie, int ielen, bool unknown,
               enum print_ie_type ptype);
 
+
+DECLARE_SECTION(set);
+DECLARE_SECTION(get);
+
 #endif /* __IW_H */
diff --git a/link.c b/link.c
index 03acf581f2d3fddc813d83d4e9c03946ed5b97cc..c17f0555a5f9425eabb55d6e48a3b43cbadf49bb 100644 (file)
--- a/link.c
+++ b/link.c
@@ -105,8 +105,6 @@ static int handle_scan_for_link(struct nl80211_state *state,
        nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, link_bss_handler, &lr);
        return 0;
 }
-HIDDEN(link, get_bss, NULL, NL80211_CMD_GET_SCAN, NLM_F_DUMP,
-       CIB_NETDEV, handle_scan_for_link);
 
 static int print_link_sta(struct nl_msg *msg, void *arg)
 {
@@ -213,8 +211,6 @@ static int handle_link_sta(struct nl80211_state *state,
  nla_put_failure:
        return -ENOBUFS;
 }
-HIDDEN(link, get_sta, "", NL80211_CMD_GET_STATION, 0,
-       CIB_NETDEV, handle_link_sta);
 
 static int handle_link(struct nl80211_state *state, struct nl_cb *cb,
                       struct nl_msg *msg, int argc, char **argv)
@@ -255,3 +251,7 @@ static int handle_link(struct nl80211_state *state, struct nl_cb *cb,
 }
 TOPLEVEL(link, NULL, 0, 0, CIB_NETDEV, handle_link,
         "Print information about the current link, if any.");
+HIDDEN(link, get_sta, "", NL80211_CMD_GET_STATION, 0,
+       CIB_NETDEV, handle_link_sta);
+HIDDEN(link, get_bss, NULL, NL80211_CMD_GET_SCAN, NLM_F_DUMP,
+       CIB_NETDEV, handle_scan_for_link);
diff --git a/mpath.c b/mpath.c
index d590cfff52340665530af859e07c7c7b5bcb106a..e8484816bf24268497d63980ff25141315cf2114 100644 (file)
--- a/mpath.c
+++ b/mpath.c
@@ -11,6 +11,8 @@
 #include "nl80211.h"
 #include "iw.h"
 
+SECTION(mpath);
+
 enum plink_state {
        LISTEN,
        OPN_SNT,
diff --git a/reg.c b/reg.c
index a6bd74c5502272d41500d032f89952bf9cff1c08..7f82e0838c27962b5c185b7e6033e4b2eb3f88fc 100644 (file)
--- a/reg.c
+++ b/reg.c
@@ -12,6 +12,8 @@
 #include "nl80211.h"
 #include "iw.h"
 
+SECTION(reg);
+
 #define MHZ_TO_KHZ(freq) ((freq) * 1000)
 #define KHZ_TO_MHZ(freq) ((freq) / 1000)
 #define DBI_TO_MBI(gain) ((gain) * 100)
diff --git a/scan.c b/scan.c
index b2d986b625fae8b86902e09779a331d6ec983474..9941775e5dc2e3a2e1a39fb94e4f6883724340ed 100644 (file)
--- a/scan.c
+++ b/scan.c
@@ -108,10 +108,6 @@ static int handle_scan(struct nl80211_state *state,
        nlmsg_free(freqs);
        return err;
 }
-COMMAND(scan, trigger, "[freq <freq>*] [ssid <ssid>*|passive]",
-       NL80211_CMD_TRIGGER_SCAN, 0, CIB_NETDEV, handle_scan,
-        "Trigger a scan on the given frequencies with probing for the given\n"
-        "SSIDs (or wildcard if not given) unless passive scanning is requested.");
 
 static void tab_on_first(bool *first)
 {
@@ -877,10 +873,6 @@ static int handle_scan_dump(struct nl80211_state *state,
                  &scan_params);
        return 0;
 }
-COMMAND(scan, dump, "[-u]",
-       NL80211_CMD_GET_SCAN, NLM_F_DUMP, CIB_NETDEV, handle_scan_dump,
-       "Dump the current scan results. If -u is specified, print unknown\n"
-       "data in scan results.");
 
 static int handle_scan_combined(struct nl80211_state *state,
                                struct nl_cb *cb,
@@ -959,3 +951,11 @@ TOPLEVEL(scan, "[-u] [freq <freq>*] [ssid <ssid>*|passive]", 0, 0,
         "Scan on the given frequencies and probe for the given SSIDs\n"
         "(or wildcard if not given) unless passive scanning is requested.\n"
         "If -u is specified print unknown data in the scan results.");
+COMMAND(scan, dump, "[-u]",
+       NL80211_CMD_GET_SCAN, NLM_F_DUMP, CIB_NETDEV, handle_scan_dump,
+       "Dump the current scan results. If -u is specified, print unknown\n"
+       "data in scan results.");
+COMMAND(scan, trigger, "[freq <freq>*] [ssid <ssid>*|passive]",
+       NL80211_CMD_TRIGGER_SCAN, 0, CIB_NETDEV, handle_scan,
+        "Trigger a scan on the given frequencies with probing for the given\n"
+        "SSIDs (or wildcard if not given) unless passive scanning is requested.");
diff --git a/sections.c b/sections.c
new file mode 100644 (file)
index 0000000..38095f6
--- /dev/null
@@ -0,0 +1,4 @@
+#include "iw.h"
+
+SECTION(get);
+SECTION(set);
index 33a9cadebd1eddb819967da32c6f1f86e2e35fb1..0fff92d6e34f5892050894b579f7f0dac501f2a2 100644 (file)
--- a/station.c
+++ b/station.c
@@ -11,6 +11,8 @@
 #include "nl80211.h"
 #include "iw.h"
 
+SECTION(station);
+
 enum plink_state {
        LISTEN,
        OPN_SNT,