Never consume more than one token when parsing a binary flag.
Basically, your choices are --foo=false, --foo=true, and just --foo.
However, only 1 token will ever be examined.
Signed-off-by: Colin McCabe <colin.mccabe@dreamhost.com>
#include "msg/msg_types.h"
#include <deque>
+#include <errno.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string>
#include <string.h>
+#include <sstream>
#include <vector>
/*
}
}
+bool ceph_argparse_binary_flag(std::vector<const char*> &args,
+ std::vector<const char*>::iterator &i, int *ret,
+ std::ostringstream *oss, ...)
+{
+ const char *first = *i;
+ char tmp[strlen(first)+1];
+ dashes_to_underscores(first, tmp);
+ first = tmp;
+ const char *a;
+ va_list ap;
+ int strlen_a;
+
+ // does this argument match any of the possibilities?
+ va_start(ap, oss);
+ while (1) {
+ a = va_arg(ap, char*);
+ if (a == NULL)
+ return false;
+ strlen_a = strlen(a);
+ char a2[strlen_a+1];
+ dashes_to_underscores(a, a2);
+ if (strncmp(a2, first, strlen(a2)) == 0) {
+ if (first[strlen_a] == '=') {
+ i = args.erase(i);
+ const char *val = first + strlen_a + 1;
+ if (strcmp(val, "true") == 0) {
+ *ret = 1;
+ return true;
+ }
+ else if (strcmp(val, "false") == 0) {
+ *ret = 0;
+ return true;
+ }
+ if (oss) {
+ (*oss) << "Parse error parsing binary flag " << a
+ << ". Expected true or false, but got '" << val << "'\n";
+ }
+ *ret = -EINVAL;
+ return true;
+ }
+ else if (first[strlen_a] == '\0') {
+ i = args.erase(i);
+ *ret = 1;
+ return true;
+ }
+ }
+ }
+}
+
bool ceph_argparse_witharg(std::vector<const char*> &args,
std::vector<const char*>::iterator &i, std::string *ret, ...)
{
std::vector<const char*>::iterator &i, ...);
bool ceph_argparse_witharg(std::vector<const char*> &args,
std::vector<const char*>::iterator &i, std::string *ret, ...);
+bool ceph_argparse_binary_flag(std::vector<const char*> &args,
+ std::vector<const char*>::iterator &i, int *ret,
+ std::ostringstream *oss, ...);
extern CephInitParameters ceph_argparse_early_args
(std::vector<const char*>& args, uint32_t module_type, int flags,
std::string *conf_file_list);
using std::map;
using std::multimap;
+using std::ostringstream;
using std::pair;
using std::set;
using std::string;
const config_option *opt = config_optionsp + o;
std::string as_option("--");
as_option += opt->name;
- if ((opt->type == OPT_BOOL) &&
- ceph_argparse_flag(args, i, as_option.c_str(), (char*)NULL)) {
- set_val_impl("true", opt);
- break;
+ if (opt->type == OPT_BOOL) {
+ int res;
+ if (ceph_argparse_binary_flag(args, i, &res, oss, as_option.c_str(),
+ (char*)NULL)) {
+ if (res == 0)
+ set_val_impl("false", opt);
+ else if (res == 1)
+ set_val_impl("true", opt);
+ else
+ ret = res;
+ break;
+ }
}
else if (ceph_argparse_witharg(args, i, &val,
as_option.c_str(), (char*)NULL)) {
// parse error
std::ostringstream chat4;
- injection = "--debug 1 --log_to_syslog=falsey --debug-ms 40";
+ injection = "--debug 1 --log_to_syslog=falsey --debug-ms 42";
ret = g_ceph_context->_conf->injectargs(injection, &chat3);
ASSERT_EQ(ret, -EINVAL);
ret = g_ceph_context->_conf->get_val("log_to_syslog", &tmp, sizeof(buf));
ASSERT_EQ(ret, 0);
ASSERT_EQ(string("true"), string(buf));
+
+ // debug-ms should still become 42...
+ memset(buf, 0, sizeof(buf));
+ ret = g_ceph_context->_conf->get_val("debug_ms", &tmp, sizeof(buf));
+ ASSERT_EQ(ret, 0);
+ ASSERT_EQ(string("42"), string(buf));
}
TEST(DaemonConfig, InjectArgsLogfile) {