From: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
To: linux-bluetooth@vger.kernel.org
Subject: [PATCH v2 08/10] shell: Add bt_shell_opt
Date: Fri, 8 Dec 2017 08:52:54 -0200 [thread overview]
Message-ID: <20171208105256.18635-8-luiz.dentz@gmail.com> (raw)
In-Reply-To: <20171208105256.18635-1-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Make use of struct option and getopt_long to parse the options given.
---
client/main.c | 40 ++++++++++++++----------
mesh/main.c | 25 ++++++++++++---
src/shared/shell.c | 81 ++++++++++++++++++++++++++++++++----------------
src/shared/shell.h | 11 ++++++-
tools/bluetooth-player.c | 2 +-
tools/obexctl.c | 2 +-
6 files changed, 111 insertions(+), 50 deletions(-)
diff --git a/client/main.c b/client/main.c
index f0f62fe2a..f3369e89a 100644
--- a/client/main.c
+++ b/client/main.c
@@ -2344,22 +2344,27 @@ static const struct bt_shell_menu main_menu = {
{ } },
};
-static gboolean parse_agent(const char *key, const char *value,
- gpointer user_data, GError **error)
-{
- if (!value)
- return FALSE;
+static const struct option options[] = {
+ { "agent", required_argument, 0, 'a' },
+ { 0, 0, 0, 0 }
+};
- g_free(auto_register_agent);
- auto_register_agent = g_strdup(value);
+static const char *agent_option;
- return TRUE;
-}
+static const char **optargs[] = {
+ &agent_option
+};
+
+static const char *help[] = {
+ "Register agent handler: <capability>"
+};
-static GOptionEntry options[] = {
- { "agent", 'a', 0, G_OPTION_ARG_CALLBACK, parse_agent,
- "Register agent handler", "CAPABILITY" },
- { NULL },
+static const struct bt_shell_opt opt = {
+ .options = options,
+ .optno = sizeof(options) / sizeof(struct option),
+ .optstr = "a:",
+ .optarg = optargs,
+ .help = help,
};
static void client_ready(GDBusClient *client, void *user_data)
@@ -2371,15 +2376,18 @@ int main(int argc, char *argv[])
{
GDBusClient *client;
- auto_register_agent = g_strdup("");
-
- bt_shell_init(&argc, &argv, options);
+ bt_shell_init(argc, argv, &opt);
bt_shell_set_menu(&main_menu);
bt_shell_add_submenu(&advertise_menu);
bt_shell_add_submenu(&scan_menu);
bt_shell_add_submenu(&gatt_menu);
bt_shell_set_prompt(PROMPT_OFF);
+ if (agent_option)
+ auto_register_agent = g_strdup(agent_option);
+ else
+ auto_register_agent = g_strdup("");
+
dbus_conn = g_dbus_setup_bus(DBUS_BUS_SYSTEM, NULL, NULL);
g_dbus_attach_object_manager(dbus_conn);
diff --git a/mesh/main.c b/mesh/main.c
index 05841363f..4d63c5751 100644
--- a/mesh/main.c
+++ b/mesh/main.c
@@ -1925,10 +1925,25 @@ static const struct bt_shell_menu main_menu = {
static const char *mesh_config_dir;
-static GOptionEntry options[] = {
- { "config", 'c', 0, G_OPTION_ARG_STRING, &mesh_config_dir,
- "Read local mesh config JSON files from <directory>" },
- { NULL },
+static const struct option options[] = {
+ { "config", required_argument, 0, 'c' },
+ { 0, 0, 0, 0 }
+};
+
+static const char **optargs[] = {
+ &mesh_config_dir
+};
+
+static const char *help[] = {
+ "Read local mesh config JSON files from <directory>"
+};
+
+static const struct bt_shell_opt opt = {
+ .options = options,
+ .optno = sizeof(options) / sizeof(struct option),
+ .optstr = "c:",
+ .optarg = optargs,
+ .help = help,
};
static void client_ready(GDBusClient *client, void *user_data)
@@ -1942,7 +1957,7 @@ int main(int argc, char *argv[])
int len;
int extra;
- bt_shell_init(&argc, &argv, options);
+ bt_shell_init(argc, argv, &opt);
bt_shell_set_menu(&main_menu);
bt_shell_set_prompt(PROMPT_OFF);
diff --git a/src/shared/shell.c b/src/shared/shell.c
index 7e639ccc3..a4be844b7 100644
--- a/src/shared/shell.c
+++ b/src/shared/shell.c
@@ -33,6 +33,7 @@
#include <signal.h>
#include <sys/signalfd.h>
#include <wordexp.h>
+#include <getopt.h>
#include <readline/readline.h>
#include <readline/history.h>
@@ -54,7 +55,6 @@
cmd, (int)(CMD_LENGTH - strlen(cmd)), "", desc)
static GMainLoop *main_loop;
-static gboolean option_version = FALSE;
static struct {
struct io *input;
@@ -657,12 +657,6 @@ static struct io *setup_signalfd(void)
return io;
}
-static GOptionEntry main_options[] = {
- { "version", 'v', 0, G_OPTION_ARG_NONE, &option_version,
- "Show version information and exit" },
- { NULL },
-};
-
static void rl_init(void)
{
setlinebuf(stdout);
@@ -672,30 +666,65 @@ static void rl_init(void)
rl_callback_handler_install(NULL, rl_handler);
}
-void bt_shell_init(int *argc, char ***argv, GOptionEntry *options)
+static const struct option main_options[] = {
+ { "version", no_argument, 0, 'v' },
+ { "help", no_argument, 0, 'h' },
+};
+
+static void usage(int argc, char **argv, const struct bt_shell_opt *opt)
{
- GOptionContext *context;
- GError *error = NULL;
+ unsigned int i;
- context = g_option_context_new(NULL);
- g_option_context_add_main_entries(context, main_options, NULL);
- if (options)
- g_option_context_add_main_entries(context, options, NULL);
+ printf("%s ver %s\n", argv[0], VERSION);
+ printf("Usage:\n"
+ "\t%s [options]\n", argv[0]);
- if (g_option_context_parse(context, argc, argv, &error) == FALSE) {
- if (error != NULL) {
- g_printerr("%s\n", error->message);
- g_error_free(error);
- } else
- g_printerr("An unknown error occurred\n");
- exit(1);
- }
+ printf("Options:\n");
+
+ for (i = 0; opt && opt->options[i].name; i++)
+ printf("\t--%s \t%s\n", opt->options[i].name, opt->help[i]);
+
+ printf("\t--version \tDisplay version\n"
+ "\t--help \t\tDisplay help\n");
+}
+
+void bt_shell_init(int argc, char **argv, const struct bt_shell_opt *opt)
+{
+ int c, index = 0;
+ struct option options[256];
+ char optstr[256];
+ size_t offset;
+
+ offset = sizeof(main_options) / sizeof(struct option);
- g_option_context_free(context);
+ memcpy(options, main_options, sizeof(struct option) * offset);
- if (option_version == TRUE) {
- g_print("%s\n", VERSION);
- exit(EXIT_SUCCESS);
+ if (opt) {
+ memcpy(options + offset, opt->options,
+ sizeof(struct option) * opt->optno);
+ snprintf(optstr, sizeof(optstr), "+hv%s", opt->optstr);
+ } else
+ snprintf(optstr, sizeof(optstr), "+hv");
+
+ while ((c = getopt_long(argc, argv, optstr, options, &index)) != -1) {
+ switch (c) {
+ case 'v':
+ printf("%s: %s\n", argv[0], VERSION);
+ exit(EXIT_SUCCESS);
+ return;
+ case 'h':
+ usage(argc, argv, opt);
+ exit(EXIT_SUCCESS);
+ return;
+ default:
+ if (c != opt->options[index - offset].val) {
+ usage(argc, argv, opt);
+ exit(EXIT_SUCCESS);
+ return;
+ }
+
+ *opt->optarg[index - offset] = optarg;
+ }
}
main_loop = g_main_loop_new(NULL, FALSE);
diff --git a/src/shared/shell.h b/src/shared/shell.h
index f2eb85474..2b9e918d6 100644
--- a/src/shared/shell.h
+++ b/src/shared/shell.h
@@ -20,6 +20,7 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
+#include <getopt.h>
#define COLOR_OFF "\x1B[0m"
#define COLOR_RED "\x1B[0;91m"
@@ -50,7 +51,15 @@ struct bt_shell_menu {
const struct bt_shell_menu_entry entries[];
};
-void bt_shell_init(int *argc, char ***argv, GOptionEntry *options);
+struct bt_shell_opt {
+ const struct option *options;
+ size_t optno;
+ const char *optstr;
+ const char ***optarg;
+ const char **help;
+};
+
+void bt_shell_init(int argc, char **argv, const struct bt_shell_opt *opt);
void bt_shell_run(void);
diff --git a/tools/bluetooth-player.c b/tools/bluetooth-player.c
index 92235ac8e..f819488f3 100644
--- a/tools/bluetooth-player.c
+++ b/tools/bluetooth-player.c
@@ -1132,7 +1132,7 @@ int main(int argc, char *argv[])
{
GDBusClient *client;
- bt_shell_init(&argc, &argv, NULL);
+ bt_shell_init(argc, argv, NULL);
bt_shell_set_menu(&main_menu);
bt_shell_set_prompt(PROMPT_OFF);
bt_shell_attach(fileno(stdin));
diff --git a/tools/obexctl.c b/tools/obexctl.c
index f5ab29612..c4c7686c1 100644
--- a/tools/obexctl.c
+++ b/tools/obexctl.c
@@ -2153,7 +2153,7 @@ int main(int argc, char *argv[])
{
GDBusClient *client;
- bt_shell_init(&argc, &argv, NULL);
+ bt_shell_init(argc, argv, NULL);
bt_shell_set_menu(&main_menu);
bt_shell_set_prompt(PROMPT_OFF);
bt_shell_attach(fileno(stdin));
--
2.13.6
next prev parent reply other threads:[~2017-12-08 10:52 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-12-08 10:52 [PATCH v2 01/10] shared/shell: Omit menu command if there are no submenus Luiz Augusto von Dentz
2017-12-08 10:52 ` [PATCH v2 02/10] shared/shell: Don't remove command from arguments Luiz Augusto von Dentz
2017-12-08 10:52 ` [PATCH v2 03/10] mesh: Make meshctl use bt_shell helpers Luiz Augusto von Dentz
2017-12-08 10:52 ` [PATCH v2 04/10] tools/obexctl: Use " Luiz Augusto von Dentz
2017-12-08 10:52 ` [PATCH v2 05/10] tools/bluetooth-player: " Luiz Augusto von Dentz
2017-12-08 10:52 ` [PATCH v2 06/10] tools/bluetooth-player: Fix arg format for search command Luiz Augusto von Dentz
2017-12-08 10:52 ` [PATCH v2 07/10] client: Fix arguments of set-filter-clear Luiz Augusto von Dentz
2017-12-08 10:52 ` Luiz Augusto von Dentz [this message]
2017-12-08 10:52 ` [PATCH v2 09/10] mesh: Rework set_scan_filter_uuids parameters Luiz Augusto von Dentz
2017-12-08 10:52 ` [PATCH v2 10/10] mesh: Remove cmd_scan Luiz Augusto von Dentz
2017-12-08 11:10 ` [PATCH v2 01/10] shared/shell: Omit menu command if there are no submenus Johan Hedberg
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=20171208105256.18635-8-luiz.dentz@gmail.com \
--to=luiz.dentz@gmail.com \
--cc=linux-bluetooth@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;
as well as URLs for NNTP newsgroup(s).