[sheepdog] [PATCH 5/6] sheep: show auto-generate help when invalid options are specified

morita.kazutaka at gmail.com morita.kazutaka at gmail.com
Mon Nov 5 11:52:02 CET 2012


From: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>

Signed-off-by: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
---
 include/option.h          |    2 ++
 lib/option.c              |   35 ++++++++++++++++++++++++++++++++++-
 sheep/cluster.h           |    1 +
 sheep/cluster/accord.c    |    1 +
 sheep/cluster/corosync.c  |    1 +
 sheep/cluster/local.c     |    1 +
 sheep/cluster/zookeeper.c |    1 +
 sheep/sheep.c             |   23 ++++++++++++++++-------
 8 files changed, 57 insertions(+), 8 deletions(-)

diff --git a/include/option.h b/include/option.h
index 5fdca82..34f40b4 100644
--- a/include/option.h
+++ b/include/option.h
@@ -52,6 +52,8 @@ struct sd_option {
 	struct sd_opt_value arg;
 };
 
+void sd_opt_usage(struct sd_option *opt, const char *arg,
+		  const char *desc);
 bool sd_opt_is_number(const struct sd_opt_value *val);
 bool sd_opt_is_bool(const struct sd_opt_value *val);
 bool sd_opt_is_size(const struct sd_opt_value *val);
diff --git a/lib/option.c b/lib/option.c
index b8b969f..6253f5f 100644
--- a/lib/option.c
+++ b/lib/option.c
@@ -23,6 +23,37 @@
 #define SD_OPT_BOOL     0x04
 #define SD_OPT_SIZE     0x08
 
+void sd_opt_usage(struct sd_option *opt, const char *arg,
+		  const char *desc)
+{
+	struct sd_opt_param *param;
+	bool header_is_printed = false;
+
+	if (!opt->params)
+		return;
+
+	fprintf(stderr, "\n");
+	fprintf(stderr, "%s\n", desc);
+
+	sd_for_each_opt_param(param, opt->params) {
+		char s[256];
+		if (strcmp(param->arg, arg) != 0)
+			continue;
+
+		if (!header_is_printed) {
+			fprintf(stderr, "  -%c %s[:option[,option[,...]]]\n",
+				opt->ch, arg);
+			fprintf(stderr, "  OPTIONS:\n");
+			header_is_printed = true;
+		}
+		snprintf(s, sizeof(s), "%s=%s", param->key, param->usage);
+		fprintf(stderr, "    %-32s%s\n", s, param->desc);
+	}
+
+	if (!header_is_printed)
+		fprintf(stderr, "  -%c %s\n", opt->ch, arg);
+}
+
 bool sd_opt_is_number(const struct sd_opt_value *val)
 {
 	return !!(val->type & SD_OPT_NUMBER);
@@ -211,8 +242,10 @@ static void parse_sd_option(struct sd_option *opt, char *str)
 		int ret;
 
 		ret = parse_sd_opt_params(opt->params, arg, str);
-		if (ret < 0)
+		if (ret < 0) {
+			sd_opt_usage(opt, arg, "Usage:");
 			exit(1);
+		}
 	}
 }
 
diff --git a/sheep/cluster.h b/sheep/cluster.h
index 1016d9e..471b289 100644
--- a/sheep/cluster.h
+++ b/sheep/cluster.h
@@ -39,6 +39,7 @@ enum cluster_join_result {
 
 struct cluster_driver {
 	const char *name;
+	const char *desc;
 
 	/*
 	 * Initialize the cluster driver
diff --git a/sheep/cluster/accord.c b/sheep/cluster/accord.c
index af4190b..d7f49cd 100644
--- a/sheep/cluster/accord.c
+++ b/sheep/cluster/accord.c
@@ -581,6 +581,7 @@ static int accord_init(struct sd_opt_param *option)
 
 static struct cluster_driver cdrv_accord = {
 	.name       = "accord",
+	.desc       = "Accord cluster driver",
 
 	.init       = accord_init,
 	.join       = accord_join,
diff --git a/sheep/cluster/corosync.c b/sheep/cluster/corosync.c
index 0088e0d..b65354e 100644
--- a/sheep/cluster/corosync.c
+++ b/sheep/cluster/corosync.c
@@ -819,6 +819,7 @@ again:
 
 static struct cluster_driver cdrv_corosync = {
 	.name		= "corosync",
+	.desc		= "Corosync cluster driver",
 
 	.init		= corosync_init,
 	.get_local_addr	= corosync_get_local_addr,
diff --git a/sheep/cluster/local.c b/sheep/cluster/local.c
index 79a29ab..736c392 100644
--- a/sheep/cluster/local.c
+++ b/sheep/cluster/local.c
@@ -562,6 +562,7 @@ static int local_init(struct sd_opt_param *option)
 
 static struct cluster_driver cdrv_local = {
 	.name		= "local",
+	.desc		= "Local cluster driver",
 
 	.init		= local_init,
 	.get_local_addr	= local_get_local_addr,
diff --git a/sheep/cluster/zookeeper.c b/sheep/cluster/zookeeper.c
index 826ef74..7031d1f 100644
--- a/sheep/cluster/zookeeper.c
+++ b/sheep/cluster/zookeeper.c
@@ -838,6 +838,7 @@ static int zk_init(struct sd_opt_param *option)
 
 static struct cluster_driver cdrv_zookeeper = {
 	.name       = "zookeeper",
+	.desc       = "ZooKeeper cluster driver",
 
 	.init       = zk_init,
 	.join       = zk_join,
diff --git a/sheep/sheep.c b/sheep/sheep.c
index b86b815..ce8d28e 100644
--- a/sheep/sheep.c
+++ b/sheep/sheep.c
@@ -235,21 +235,30 @@ static int init_cache_type(struct sd_option *opt)
 
 	struct cache_type {
 		const char *name;
+		const char *desc;
 		int (*set)(struct sd_opt_param *);
 	};
 	struct cache_type cache_types[] = {
-		{ "object", object_cache_set },
-		{ "disk", disk_cache_set },
+		{ "object", "Object cache", object_cache_set },
+		{ "disk", "Disk cache", disk_cache_set },
 		{ NULL, NULL },
 	};
 
 	for (i = 0; cache_types[i].name; i++) {
 		const char *n = cache_types[i].name;
+		int ret;
 
-		if (!strncmp(opt->arg.str, n, strlen(n)))
-			return cache_types[i].set(opt->params);
+		if (!strncmp(opt->arg.str, n, strlen(n))) {
+			ret = cache_types[i].set(opt->params);
+			if (ret < 0)
+				sd_opt_usage(opt, n, cache_types[i].desc);
+			return ret;
+		}
 	}
 	fprintf(stderr, "invalid cache type: %s\n", opt->arg.str);
+	fprintf(stderr, "Valid cache types are:\n");
+	for (i = 0; cache_types[i].name; i++)
+		sd_opt_usage(opt, cache_types[i].name, cache_types[i].desc);
 
 	return -1;
 }
@@ -350,11 +359,11 @@ int main(int argc, char **argv)
 			if (!sys->cdrv) {
 				fprintf(stderr, "Invalid cluster driver '%s'\n",
 					opt->arg.str);
-				fprintf(stderr, "Supported drivers:");
+				fprintf(stderr, "Supported drivers:\n");
 				FOR_EACH_CLUSTER_DRIVER(cdrv) {
-					fprintf(stderr, " %s", cdrv->name);
+					sd_opt_usage(opt, cdrv->name,
+						     cdrv->desc);
 				}
-				fprintf(stderr, "\n");
 				exit(1);
 			}
 
-- 
1.7.9.5




More information about the sheepdog mailing list