cli: taking my revenge for forcing "geo-replication" into commandline
Accept unambigous initial fragments of keywords, eg. gluster vol geo stat is recognized. Compared to readline integration: - no external dependency - works in shell too - works for inner keywords of operations (as in above example, or "vol crea <vol> repl 3 ...") - you save pressing tabs :) If not desired in customer builds, can be disabled by an #ifdef (not integrated into build system as of now); however, I think folks in house could like it. Signed-off-by: Csaba Henk <csaba@gluster.com> Signed-off-by: Anand Avati <avati@gluster.com> BUG: 2757 (refactory gsync/gsyncd/syncdaemon/whatever to geo-replication) URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=2757
This commit is contained in:
parent
0652f9f921
commit
86c818a98a
@ -36,6 +36,20 @@
|
||||
#include "protocol-common.h"
|
||||
#include "cli1-xdr.h"
|
||||
|
||||
|
||||
static const char *
|
||||
id_sel (void *wcon)
|
||||
{
|
||||
return (const char *)wcon;
|
||||
}
|
||||
|
||||
static char *
|
||||
str_getunamb (const char *tok, char **opwords)
|
||||
{
|
||||
return (char *)cli_getunamb (tok, (void **)opwords, id_sel);
|
||||
}
|
||||
|
||||
|
||||
int32_t
|
||||
cli_cmd_bricks_parse (const char **words, int wordcount, int brick_index,
|
||||
char **bricks, int *brick_count)
|
||||
@ -150,13 +164,13 @@ cli_cmd_volume_create_parse (const char **words, int wordcount, dict_t **options
|
||||
int32_t index = 0;
|
||||
char *bricks = NULL;
|
||||
int32_t brick_count = 0;
|
||||
char *opwords_cl[] = { "replica", "stripe", NULL };
|
||||
char *opwords_tr[] = { "transport", NULL };
|
||||
char *w = NULL;
|
||||
|
||||
GF_ASSERT (words);
|
||||
GF_ASSERT (options);
|
||||
|
||||
GF_ASSERT ((strcmp (words[0], "volume")) == 0);
|
||||
GF_ASSERT ((strcmp (words[1], "create")) == 0);
|
||||
|
||||
dict = dict_new ();
|
||||
|
||||
if (!dict)
|
||||
@ -199,7 +213,11 @@ cli_cmd_volume_create_parse (const char **words, int wordcount, dict_t **options
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
if ((strcasecmp (words[3], "replica")) == 0) {
|
||||
w = str_getunamb (words[3], opwords_cl);
|
||||
if (!w) {
|
||||
type = GF_CLUSTER_TYPE_NONE;
|
||||
brick_index = 3;
|
||||
} else if ((strcmp (w, "replica")) == 0) {
|
||||
type = GF_CLUSTER_TYPE_REPLICATE;
|
||||
if (wordcount < 5) {
|
||||
ret = -1;
|
||||
@ -215,7 +233,7 @@ cli_cmd_volume_create_parse (const char **words, int wordcount, dict_t **options
|
||||
if (ret)
|
||||
goto out;
|
||||
brick_index = 5;
|
||||
} else if ((strcasecmp (words[3], "stripe")) == 0) {
|
||||
} else if ((strcmp (w, "stripe")) == 0) {
|
||||
type = GF_CLUSTER_TYPE_STRIPE;
|
||||
if (wordcount < 5) {
|
||||
ret = -1;
|
||||
@ -231,10 +249,8 @@ cli_cmd_volume_create_parse (const char **words, int wordcount, dict_t **options
|
||||
if (ret)
|
||||
goto out;
|
||||
brick_index = 5;
|
||||
} else {
|
||||
type = GF_CLUSTER_TYPE_NONE;
|
||||
brick_index = 3;
|
||||
}
|
||||
} else
|
||||
GF_ASSERT (!"opword mismatch");
|
||||
|
||||
ret = dict_set_int32 (dict, "type", type);
|
||||
if (ret)
|
||||
@ -250,7 +266,7 @@ cli_cmd_volume_create_parse (const char **words, int wordcount, dict_t **options
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (strcasecmp(words[index], "transport") == 0) {
|
||||
if (str_getunamb (words[index], opwords_tr)) {
|
||||
brick_index = index+2;
|
||||
if (wordcount < (index + 2)) {
|
||||
ret = -1;
|
||||
@ -331,9 +347,6 @@ cli_cmd_volume_reset_parse (const char **words, int wordcount, dict_t **options)
|
||||
GF_ASSERT (words);
|
||||
GF_ASSERT (options);
|
||||
|
||||
GF_ASSERT ((strcmp (words[0], "volume")) == 0);
|
||||
GF_ASSERT ((strcmp (words[1], "reset")) == 0);
|
||||
|
||||
dict = dict_new ();
|
||||
|
||||
if (!dict)
|
||||
@ -387,13 +400,13 @@ cli_cmd_quota_parse (const char **words, int wordcount, dict_t **options)
|
||||
char key[20] = {0, };
|
||||
uint64_t value = 0;
|
||||
gf_quota_type type = GF_QUOTA_OPTION_TYPE_NONE;
|
||||
char *opwords[] = { "enable", "disable", "limit-usage",
|
||||
"remove", "list", "version", NULL };
|
||||
char *w = NULL;
|
||||
|
||||
GF_ASSERT (words);
|
||||
GF_ASSERT (options);
|
||||
|
||||
GF_ASSERT ((strcmp (words[0], "volume")) == 0);
|
||||
GF_ASSERT ((strcmp (words[1], "quota")) == 0);
|
||||
|
||||
dict = dict_new ();
|
||||
|
||||
if (!dict)
|
||||
@ -434,18 +447,23 @@ cli_cmd_quota_parse (const char **words, int wordcount, dict_t **options)
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
w = str_getunamb (words[3], opwords);
|
||||
if (!w) {
|
||||
ret = - 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((strcasecmp (words[3], "enable")) == 0 && wordcount == 4) {
|
||||
if ((strcmp (w, "enable")) == 0 && wordcount == 4) {
|
||||
type = GF_QUOTA_OPTION_TYPE_ENABLE;
|
||||
goto set_type;
|
||||
}
|
||||
|
||||
if (strcasecmp (words[3], "disable") == 0 && wordcount == 4) {
|
||||
if (strcmp (w, "disable") == 0 && wordcount == 4) {
|
||||
type = GF_QUOTA_OPTION_TYPE_DISABLE;
|
||||
goto set_type;
|
||||
}
|
||||
|
||||
if (strcasecmp (words[3], "limit-usage") == 0) {
|
||||
if (strcmp (w, "limit-usage") == 0) {
|
||||
if (wordcount != 6) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
@ -480,7 +498,7 @@ cli_cmd_quota_parse (const char **words, int wordcount, dict_t **options)
|
||||
|
||||
goto set_type;
|
||||
}
|
||||
if (strcasecmp (words[3], "remove") == 0) {
|
||||
if (strcmp (w, "remove") == 0) {
|
||||
if (wordcount != 5) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
@ -500,7 +518,7 @@ cli_cmd_quota_parse (const char **words, int wordcount, dict_t **options)
|
||||
goto set_type;
|
||||
}
|
||||
|
||||
if (strcasecmp (words[3], "list") == 0) {
|
||||
if (strcmp (w, "list") == 0) {
|
||||
if (wordcount < 4) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
@ -524,13 +542,11 @@ cli_cmd_quota_parse (const char **words, int wordcount, dict_t **options)
|
||||
goto set_type;
|
||||
}
|
||||
|
||||
if (strcasecmp (words[3], "version") == 0) {
|
||||
if (strcmp (w, "version") == 0) {
|
||||
type = GF_QUOTA_OPTION_TYPE_VERSION;
|
||||
|
||||
} else {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
} else
|
||||
GF_ASSERT (!"opword mismatch");
|
||||
|
||||
set_type:
|
||||
ret = dict_set_int32 (dict, "type", type);
|
||||
@ -562,9 +578,6 @@ cli_cmd_volume_set_parse (const char **words, int wordcount, dict_t **options)
|
||||
GF_ASSERT (words);
|
||||
GF_ASSERT (options);
|
||||
|
||||
GF_ASSERT ((strcmp (words[0], "volume")) == 0);
|
||||
GF_ASSERT ((strcmp (words[1], "set")) == 0);
|
||||
|
||||
dict = dict_new ();
|
||||
|
||||
if (!dict)
|
||||
@ -636,9 +649,6 @@ cli_cmd_volume_add_brick_parse (const char **words, int wordcount,
|
||||
GF_ASSERT (words);
|
||||
GF_ASSERT (options);
|
||||
|
||||
GF_ASSERT ((strcmp (words[0], "volume")) == 0);
|
||||
GF_ASSERT ((strcmp (words[1], "add-brick")) == 0);
|
||||
|
||||
dict = dict_new ();
|
||||
|
||||
if (!dict)
|
||||
@ -707,9 +717,6 @@ cli_cmd_volume_remove_brick_parse (const char **words, int wordcount,
|
||||
GF_ASSERT (words);
|
||||
GF_ASSERT (options);
|
||||
|
||||
GF_ASSERT ((strcmp (words[0], "volume")) == 0);
|
||||
GF_ASSERT ((strcmp (words[1], "remove-brick")) == 0);
|
||||
|
||||
dict = dict_new ();
|
||||
|
||||
if (!dict)
|
||||
@ -819,17 +826,16 @@ cli_cmd_volume_replace_brick_parse (const char **words, int wordcount,
|
||||
dict_t *dict = NULL;
|
||||
char *volname = NULL;
|
||||
int ret = -1;
|
||||
char *op = NULL;
|
||||
int op_index = 0;
|
||||
char *delimiter = NULL;
|
||||
gf1_cli_replace_op replace_op = GF_REPLACE_OP_NONE;
|
||||
char *opwords[] = { "start", "commit", "pause", "abort", "status",
|
||||
NULL };
|
||||
char *w = NULL;
|
||||
|
||||
GF_ASSERT (words);
|
||||
GF_ASSERT (options);
|
||||
|
||||
GF_ASSERT ((strcmp (words[0], "volume")) == 0);
|
||||
GF_ASSERT ((strcmp (words[1], "replace-brick")) == 0);
|
||||
|
||||
dict = dict_new ();
|
||||
|
||||
if (!dict)
|
||||
@ -895,19 +901,21 @@ cli_cmd_volume_replace_brick_parse (const char **words, int wordcount,
|
||||
goto out;
|
||||
}
|
||||
|
||||
op = (char *) words[op_index];
|
||||
w = str_getunamb (words[op_index], opwords);
|
||||
|
||||
if (!strcasecmp ("start", op)) {
|
||||
if (!w) {
|
||||
} else if (!strcmp ("start", w)) {
|
||||
replace_op = GF_REPLACE_OP_START;
|
||||
} else if (!strcasecmp ("commit", op)) {
|
||||
} else if (!strcmp ("commit", w)) {
|
||||
replace_op = GF_REPLACE_OP_COMMIT;
|
||||
} else if (!strcasecmp ("pause", op)) {
|
||||
} else if (!strcmp ("pause", w)) {
|
||||
replace_op = GF_REPLACE_OP_PAUSE;
|
||||
} else if (!strcasecmp ("abort", op)) {
|
||||
} else if (!strcmp ("abort", w)) {
|
||||
replace_op = GF_REPLACE_OP_ABORT;
|
||||
} else if (!strcasecmp ("status", op)) {
|
||||
} else if (!strcmp ("status", w)) {
|
||||
replace_op = GF_REPLACE_OP_STATUS;
|
||||
}
|
||||
} else
|
||||
GF_ASSERT (!"opword mismatch");
|
||||
|
||||
/* commit force option */
|
||||
op_index = 6;
|
||||
@ -918,8 +926,7 @@ cli_cmd_volume_replace_brick_parse (const char **words, int wordcount,
|
||||
}
|
||||
|
||||
if (wordcount == (op_index + 1)) {
|
||||
op = (char *) words[op_index];
|
||||
if (!strcasecmp ("force", op)) {
|
||||
if (!strcmp ("force", words[op_index])) {
|
||||
replace_op = GF_REPLACE_OP_COMMIT_FORCE;
|
||||
}
|
||||
}
|
||||
@ -961,10 +968,6 @@ cli_cmd_log_filename_parse (const char **words, int wordcount, dict_t **options)
|
||||
GF_ASSERT (words);
|
||||
GF_ASSERT (options);
|
||||
|
||||
GF_ASSERT ((strcmp (words[0], "volume")) == 0);
|
||||
GF_ASSERT ((strcmp (words[1], "log")) == 0);
|
||||
GF_ASSERT ((strcmp (words[2], "filename")) == 0);
|
||||
|
||||
dict = dict_new ();
|
||||
if (!dict)
|
||||
goto out;
|
||||
@ -1023,10 +1026,6 @@ cli_cmd_log_locate_parse (const char **words, int wordcount, dict_t **options)
|
||||
GF_ASSERT (words);
|
||||
GF_ASSERT (options);
|
||||
|
||||
GF_ASSERT ((strcmp (words[0], "volume")) == 0);
|
||||
GF_ASSERT ((strcmp (words[1], "log")) == 0);
|
||||
GF_ASSERT ((strcmp (words[2], "locate")) == 0);
|
||||
|
||||
dict = dict_new ();
|
||||
if (!dict)
|
||||
goto out;
|
||||
@ -1076,10 +1075,6 @@ cli_cmd_log_rotate_parse (const char **words, int wordcount, dict_t **options)
|
||||
GF_ASSERT (words);
|
||||
GF_ASSERT (options);
|
||||
|
||||
GF_ASSERT ((strcmp (words[0], "volume")) == 0);
|
||||
GF_ASSERT ((strcmp (words[1], "log")) == 0);
|
||||
GF_ASSERT ((strcmp (words[2], "rotate")) == 0);
|
||||
|
||||
dict = dict_new ();
|
||||
if (!dict)
|
||||
goto out;
|
||||
@ -1136,13 +1131,13 @@ cli_cmd_gsync_set_parse (const char **words, int wordcount, dict_t **options)
|
||||
unsigned masteri = 0;
|
||||
unsigned slavei = 0;
|
||||
unsigned cmdi = 0;
|
||||
char *opwords[] = { "status", "start", "stop", "config",
|
||||
NULL };
|
||||
char *w = NULL;
|
||||
|
||||
GF_ASSERT (words);
|
||||
GF_ASSERT (options);
|
||||
|
||||
GF_ASSERT ((strcmp (words[0], "volume")) == 0);
|
||||
GF_ASSERT ((strcmp (words[1], GEOREP)) == 0);
|
||||
|
||||
dict = dict_new ();
|
||||
if (!dict)
|
||||
goto out;
|
||||
@ -1191,28 +1186,32 @@ cli_cmd_gsync_set_parse (const char **words, int wordcount, dict_t **options)
|
||||
if (slavei && !gsyncd_url_check (words[slavei]))
|
||||
goto out;
|
||||
|
||||
if (strcmp (words[cmdi], "status") == 0) {
|
||||
w = str_getunamb (words[cmdi], opwords);
|
||||
if (!w)
|
||||
goto out;
|
||||
|
||||
if (strcmp (w, "status") == 0) {
|
||||
type = GF_GSYNC_OPTION_TYPE_STATUS;
|
||||
|
||||
if (slavei && !masteri)
|
||||
goto out;
|
||||
} else if (strcmp (words[cmdi], "config") == 0) {
|
||||
} else if (strcmp (w, "config") == 0) {
|
||||
type = GF_GSYNC_OPTION_TYPE_CONFIG;
|
||||
|
||||
if (!slavei)
|
||||
goto out;
|
||||
} else if (strcmp (words[cmdi], "start") == 0) {
|
||||
} else if (strcmp (w, "start") == 0) {
|
||||
type = GF_GSYNC_OPTION_TYPE_START;
|
||||
|
||||
if (!masteri || !slavei)
|
||||
goto out;
|
||||
} else if (strcmp (words[cmdi], "stop") == 0) {
|
||||
} else if (strcmp (w, "stop") == 0) {
|
||||
type = GF_GSYNC_OPTION_TYPE_STOP;
|
||||
|
||||
if (!masteri || !slavei)
|
||||
goto out;
|
||||
} else
|
||||
goto out;
|
||||
GF_ASSERT (!"opword mismatch");
|
||||
|
||||
if (type != GF_GSYNC_OPTION_TYPE_CONFIG && cmdi < wordcount - 1)
|
||||
goto out;
|
||||
@ -1296,13 +1295,12 @@ cli_cmd_volume_profile_parse (const char **words, int wordcount,
|
||||
char *volname = NULL;
|
||||
int ret = -1;
|
||||
gf1_cli_stats_op op = GF_CLI_STATS_NONE;
|
||||
char *opwords[] = { "start", "stop", "info", NULL };
|
||||
char *w = NULL;
|
||||
|
||||
GF_ASSERT (words);
|
||||
GF_ASSERT (options);
|
||||
|
||||
GF_ASSERT ((strcmp (words[0], "volume")) == 0);
|
||||
GF_ASSERT ((strcmp (words[1], "profile")) == 0);
|
||||
|
||||
dict = dict_new ();
|
||||
if (!dict)
|
||||
goto out;
|
||||
@ -1316,16 +1314,19 @@ cli_cmd_volume_profile_parse (const char **words, int wordcount,
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (strcmp (words[3], "start") == 0) {
|
||||
op = GF_CLI_STATS_START;
|
||||
} else if (strcmp (words[3], "stop") == 0) {
|
||||
op = GF_CLI_STATS_STOP;
|
||||
} else if (strcmp (words[3], "info") == 0) {
|
||||
op = GF_CLI_STATS_INFO;
|
||||
} else {
|
||||
w = str_getunamb (words[3], opwords);
|
||||
if (!w) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
if (strcmp (w, "start") == 0) {
|
||||
op = GF_CLI_STATS_START;
|
||||
} else if (strcmp (w, "stop") == 0) {
|
||||
op = GF_CLI_STATS_STOP;
|
||||
} else if (strcmp (w, "info") == 0) {
|
||||
op = GF_CLI_STATS_INFO;
|
||||
} else
|
||||
GF_ASSERT (!"opword mismatch");
|
||||
ret = dict_set_int32 (dict, "op", (int32_t)op);
|
||||
*options = dict;
|
||||
out:
|
||||
@ -1351,13 +1352,14 @@ cli_cmd_volume_top_parse (const char **words, int wordcount,
|
||||
int32_t blk_size = 0;
|
||||
int32_t count = 0;
|
||||
char *delimiter = NULL;
|
||||
char *opwords[] = { "open", "read", "write", "opendir",
|
||||
"readdir", "read-perf", "write-perf",
|
||||
NULL };
|
||||
char *w = NULL;
|
||||
|
||||
GF_ASSERT (words);
|
||||
GF_ASSERT (options);
|
||||
|
||||
GF_ASSERT ((strcmp (words[0], "volume")) == 0);
|
||||
GF_ASSERT ((strcmp (words[1], "top")) == 0);
|
||||
|
||||
dict = dict_new ();
|
||||
if (!dict)
|
||||
goto out;
|
||||
@ -1376,26 +1378,29 @@ cli_cmd_volume_top_parse (const char **words, int wordcount,
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (strcmp (words[3], "open") == 0) {
|
||||
top_op = GF_CLI_TOP_OPEN;
|
||||
} else if (strcmp (words[3], "read") == 0) {
|
||||
top_op = GF_CLI_TOP_READ;
|
||||
} else if (strcmp (words[3], "write") == 0) {
|
||||
top_op = GF_CLI_TOP_WRITE;
|
||||
} else if (strcmp (words[3], "opendir") == 0) {
|
||||
top_op = GF_CLI_TOP_OPENDIR;
|
||||
} else if (strcmp (words[3], "readdir") == 0) {
|
||||
top_op = GF_CLI_TOP_READDIR;
|
||||
} else if (strcmp (words[3], "read-perf") == 0) {
|
||||
top_op = GF_CLI_TOP_READ_PERF;
|
||||
perf = 1;
|
||||
} else if (strcmp (words[3], "write-perf") == 0) {
|
||||
top_op = GF_CLI_TOP_WRITE_PERF;
|
||||
perf = 1;
|
||||
} else {
|
||||
w = str_getunamb (words[3], opwords);
|
||||
if (!w) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
if (strcmp (w, "open") == 0) {
|
||||
top_op = GF_CLI_TOP_OPEN;
|
||||
} else if (strcmp (w, "read") == 0) {
|
||||
top_op = GF_CLI_TOP_READ;
|
||||
} else if (strcmp (w, "write") == 0) {
|
||||
top_op = GF_CLI_TOP_WRITE;
|
||||
} else if (strcmp (w, "opendir") == 0) {
|
||||
top_op = GF_CLI_TOP_OPENDIR;
|
||||
} else if (strcmp (w, "readdir") == 0) {
|
||||
top_op = GF_CLI_TOP_READDIR;
|
||||
} else if (strcmp (w, "read-perf") == 0) {
|
||||
top_op = GF_CLI_TOP_READ_PERF;
|
||||
perf = 1;
|
||||
} else if (strcmp (w, "write-perf") == 0) {
|
||||
top_op = GF_CLI_TOP_WRITE_PERF;
|
||||
perf = 1;
|
||||
} else
|
||||
GF_ASSERT (!"opword mismatch");
|
||||
ret = dict_set_int32 (dict, "top-op", (int32_t)top_op);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
@ -150,6 +150,10 @@ typedef ssize_t (*cli_serialize_t) (struct iovec outmsg, void *args);
|
||||
|
||||
extern struct cli_state *global_state; /* use only in readline callback */
|
||||
|
||||
typedef const char *(*cli_selector_t) (void *wcon);
|
||||
|
||||
void *cli_getunamb (const char *tok, void **choices, cli_selector_t sel);
|
||||
|
||||
int cli_cmd_register (struct cli_cmd_tree *tree, struct cli_cmd *cmd);
|
||||
int cli_cmds_register (struct cli_state *state);
|
||||
|
||||
|
@ -260,29 +260,49 @@ err:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *
|
||||
cli_getunamb (const char *tok, void **choices, cli_selector_t sel)
|
||||
{
|
||||
void **wcon = NULL;
|
||||
char *w = NULL;
|
||||
unsigned mn = 0;
|
||||
void *ret = NULL;
|
||||
|
||||
if (!choices || !*tok)
|
||||
return NULL;
|
||||
|
||||
for (wcon = choices; *wcon; wcon++) {
|
||||
w = strtail ((char *)sel (*wcon), tok);
|
||||
if (!w)
|
||||
/* no match */
|
||||
continue;
|
||||
if (!*w)
|
||||
/* exact match */
|
||||
return *wcon;
|
||||
|
||||
ret = *wcon;
|
||||
mn++;
|
||||
}
|
||||
|
||||
#ifdef FORCE_MATCH_EXACT
|
||||
return NULL;
|
||||
#else
|
||||
return (mn == 1) ? ret : NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static const char *
|
||||
sel_cmd_word (void *wcon)
|
||||
{
|
||||
return ((struct cli_cmd_word *)wcon)->word;
|
||||
}
|
||||
|
||||
struct cli_cmd_word *
|
||||
cli_cmd_nextword (struct cli_cmd_word *word, const char *token)
|
||||
{
|
||||
struct cli_cmd_word *next = NULL;
|
||||
struct cli_cmd_word **trav = NULL;
|
||||
int ret = 0;
|
||||
|
||||
if (!word->nextwords)
|
||||
return NULL;
|
||||
|
||||
for (trav = word->nextwords; (next = *trav); trav++) {
|
||||
if (next->match) {
|
||||
// ret = next->match ();
|
||||
} else {
|
||||
ret = strcmp (next->word, token);
|
||||
}
|
||||
|
||||
if (ret == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
return next;
|
||||
return (struct cli_cmd_word *)cli_getunamb (token,
|
||||
(void **)word->nextwords,
|
||||
sel_cmd_word);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user