Skip to content

Commit e65c38c

Browse files
authored
Merge pull request #46 from RobSanders/optarg_updates
Optarg updates
2 parents 57c2fec + 399d055 commit e65c38c

5 files changed

Lines changed: 38 additions & 23 deletions

File tree

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ install: $(TARGET_LIBS)
7979
rpmprep:
8080
rm -rf libcli-$(MAJOR).$(MINOR).$(REVISION)
8181
mkdir libcli-$(MAJOR).$(MINOR).$(REVISION)
82-
cp -R libcli.{c,h} libcli.spec clitest.c Makefile COPYING README libcli-$(MAJOR).$(MINOR).$(REVISION)
82+
cp -R libcli.{c,h} libcli.spec clitest.c Makefile COPYING README.md doc libcli-$(MAJOR).$(MINOR).$(REVISION)
8383
tar zcvf libcli-$(MAJOR).$(MINOR).$(REVISION).tar.gz --exclude CVS --exclude *.tar.gz libcli-$(MAJOR).$(MINOR).$(REVISION)
8484
rm -rf libcli-$(MAJOR).$(MINOR).$(REVISION)
8585

clitest.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,9 +254,11 @@ int shape_transient_eval(struct cli_def *cli, const char *name, const char *valu
254254
printf("shape_transient_eval called with <%s>\n", value);
255255
if (!strcmp(value, "rectangle")) {
256256
cli_set_transient_mode(cli, MODE_POLYGON_RECTANGLE);
257+
cli_set_optarg_value(cli, "duplicateShapeValue", value, 0);
257258
return CLI_OK;
258259
} else if (!strcmp(value, "triangle")) {
259260
cli_set_transient_mode(cli, MODE_POLYGON_TRIANGLE);
261+
cli_set_optarg_value(cli, "duplicateShapeValue", value, 0);
260262
return CLI_OK;
261263
}
262264
cli_error(cli, "unrecognized value for setting %s -> %s", name, value);

libcli.c

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,6 @@ static void cli_int_parse_optargs(struct cli_def *cli, struct cli_pipeline_stage
141141
static int cli_int_enter_buildmode(struct cli_def *cli, struct cli_pipeline_stage *stage, char *mode_text);
142142
static char *cli_int_buildmode_extend_cmdline(char *, char *word);
143143
static void cli_int_free_buildmode(struct cli_def *cli);
144-
static int cli_int_add_optarg_value(struct cli_def *cli, const char *name, const char *value, int allow_multiple);
145144
static void cli_free_command(struct cli_def *cli, struct cli_command *cmd);
146145
static int cli_int_unregister_command_core(struct cli_def *cli, const char *command, int command_type);
147146
static int cli_int_unregister_buildmode_command(struct cli_def *cli, const char *command) __attribute__((unused));
@@ -2183,7 +2182,7 @@ void cli_int_unset_optarg_value(struct cli_def *cli, const char *name) {
21832182
}
21842183
}
21852184

2186-
int cli_int_add_optarg_value(struct cli_def *cli, const char *name, const char *value, int allow_multiple) {
2185+
int cli_set_optarg_value(struct cli_def *cli, const char *name, const char *value, int allow_multiple) {
21872186
struct cli_optarg_pair *optarg_pair, **anchor;
21882187
int rc = CLI_ERROR;
21892188

@@ -2452,7 +2451,7 @@ int cli_int_buildmode_flag_cback(struct cli_def *cli, const char *command, char
24522451
cli_error(cli, "Extra arguments on command line, command ignored.");
24532452
rc = CLI_ERROR;
24542453
}
2455-
if (cli_int_add_optarg_value(cli, command, command, 0)) {
2454+
if (cli_set_optarg_value(cli, command, command, 0)) {
24562455
cli_error(cli, "Problem setting value for optional flag %s", command);
24572456
rc = CLI_ERROR;
24582457
}
@@ -2467,7 +2466,7 @@ int cli_int_buildmode_flag_multiple_cback(struct cli_def *cli, const char *comma
24672466
cli_error(cli, "Extra arguments on command line, command ignored.");
24682467
rc = CLI_ERROR;
24692468
}
2470-
if (cli_int_add_optarg_value(cli, command, command, CLI_CMD_OPTION_MULTIPLE)) {
2469+
if (cli_set_optarg_value(cli, command, command, CLI_CMD_OPTION_MULTIPLE)) {
24712470
cli_error(cli, "Problem setting value for optional flag %s", command);
24722471
rc = CLI_ERROR;
24732472
}
@@ -2842,7 +2841,8 @@ static void cli_get_optarg_comphelp(struct cli_def *cli, struct cli_optarg *opta
28422841
char *allow_buildmode = BUILDMODE_NO;
28432842
int (*get_completions)(struct cli_def *, const char *, const char *, struct cli_comphelp *) = NULL;
28442843
char *tptr = NULL;
2845-
2844+
char *tname = NULL;
2845+
28462846
// If we've already seen a value by this exact name, skip it, unless the multiple flag is set
28472847
if (cli_find_optarg_value(cli, optarg->name, NULL) && !(optarg->flags & (CLI_CMD_OPTION_MULTIPLE))) return;
28482848

@@ -2885,16 +2885,17 @@ static void cli_get_optarg_comphelp(struct cli_def *cli, struct cli_optarg *opta
28852885
}
28862886

28872887
// Fill in with help text or completor value(s) as indicated
2888-
if (lastchar == '?' && asprintf(&tptr, "%s%s%s", delim_start, optarg->name, delim_end) != -1) {
2888+
if (lastchar == '?' && asprintf(&tname, "%s%s%s", delim_start, optarg->name, delim_end) != -1) {
28892889
if (optarg->flags & CLI_CMD_ALLOW_BUILDMODE) allow_buildmode = BUILDMODE_YES;
2890-
if (help_insert && (asprintf(&tptr, " %-20s enter '%s' to %s%s", tptr, optarg->name,
2890+
if (help_insert && (asprintf(&tptr, " %-20s enter '%s' to %s%s", tname, optarg->name,
28912891
(optarg->help) ? optarg->help : "", allow_buildmode) != -1)) {
28922892
cli_add_comphelp_entry(comphelp, tptr);
28932893
free_z(tptr);
2894-
} else if (asprintf(&tptr, " %-20s %s%s", tptr, (optarg->help) ? optarg->help : "", allow_buildmode) != -1) {
2894+
} else if (asprintf(&tptr, " %-20s %s%s", tname, (optarg->help) ? optarg->help : "", allow_buildmode) != -1) {
28952895
cli_add_comphelp_entry(comphelp, tptr);
28962896
free_z(tptr);
28972897
}
2898+
free_z(tname);
28982899
} else if (lastchar == CTRL('I')) {
28992900
if (get_completions) {
29002901
(*get_completions)(cli, optarg->name, next_word, comphelp);
@@ -2916,6 +2917,8 @@ static void cli_int_parse_optargs(struct cli_def *cli, struct cli_pipeline_stage
29162917
int is_last_word = 0;
29172918
int (*validator)(struct cli_def *, const char *name, const char *value);
29182919

2920+
if (cli->buildmode) cli->found_optargs = cli->buildmode->found_optargs;
2921+
else cli->found_optargs = stage->found_optargs;
29192922
/*
29202923
* Tab completion and help are *only* allowed at end of string, but we need to process the entire command to know what
29212924
* has already been found. There should be no ambiguities before the 'last' word.
@@ -2960,7 +2963,7 @@ static void cli_int_parse_optargs(struct cli_def *cli, struct cli_pipeline_stage
29602963
if (stage->status != CLI_OK) {
29612964
stage->error_word = stage->words[word_idx];
29622965
cli_reprompt(cli);
2963-
return;
2966+
goto done;
29642967
}
29652968
} else if (stage->words[word_idx] && (oaptr->flags & (CLI_CMD_OPTIONAL_FLAG | CLI_CMD_OPTIONAL_ARGUMENT)) &&
29662969
!strcmp(oaptr->name, stage->words[word_idx])) {
@@ -2992,7 +2995,7 @@ static void cli_int_parse_optargs(struct cli_def *cli, struct cli_pipeline_stage
29922995
stage->error_word = stage->words[word_idx];
29932996
stage->status = CLI_AMBIGUOUS;
29942997
cli_error(cli, "Ambiguous option/argument for command %s", stage->command->command);
2995-
return;
2998+
goto done;
29962999
}
29973000

29983001
/*
@@ -3021,7 +3024,7 @@ static void cli_int_parse_optargs(struct cli_def *cli, struct cli_pipeline_stage
30213024
// If we were 'end-of-word' and looked for completions/help, return to user
30223025
if (called_comphelp) {
30233026
stage->status = CLI_OK;
3024-
return;
3027+
goto done;
30253028
}
30263029
}
30273030

@@ -3041,7 +3044,7 @@ static void cli_int_parse_optargs(struct cli_def *cli, struct cli_pipeline_stage
30413044
cli_error(cli, "Optional argument %s requires a value", stage->words[word_idx]);
30423045
stage->error_word = stage->words[word_idx];
30433046
stage->status = CLI_MISSING_VALUE;
3044-
return;
3047+
goto done;
30453048
}
30463049
value = stage->words[word_idx + 1];
30473050
}
@@ -3064,10 +3067,10 @@ static void cli_int_parse_optargs(struct cli_def *cli, struct cli_pipeline_stage
30643067
if (oaptr->flags & CLI_CMD_REMAINDER_OF_LINE) {
30653068
char *combined = NULL;
30663069
combined = join_words(stage->num_words - word_idx, stage->words + word_idx);
3067-
set_value_return = cli_int_add_optarg_value(cli, oaptr->name, combined, 0);
3070+
set_value_return = cli_set_optarg_value(cli, oaptr->name, combined, 0);
30683071
free_z(combined);
30693072
} else {
3070-
set_value_return = cli_int_add_optarg_value(cli, oaptr->name, value, oaptr->flags & CLI_CMD_OPTION_MULTIPLE);
3073+
set_value_return = cli_set_optarg_value(cli, oaptr->name, value, oaptr->flags & CLI_CMD_OPTION_MULTIPLE);
30713074
}
30723075

30733076
if (set_value_return != CLI_OK) {
@@ -3076,7 +3079,7 @@ static void cli_int_parse_optargs(struct cli_def *cli, struct cli_pipeline_stage
30763079
cli_reprompt(cli);
30773080
stage->error_word = stage->words[word_idx];
30783081
stage->status = CLI_ERROR;
3079-
return;
3082+
goto done;
30803083
}
30813084
}
30823085
} else {
@@ -3085,20 +3088,20 @@ static void cli_int_parse_optargs(struct cli_def *cli, struct cli_pipeline_stage
30853088
cli_reprompt(cli);
30863089
stage->error_word = stage->words[word_idx];
30873090
stage->status = CLI_ERROR;
3088-
return;
3091+
goto done;
30893092
}
30903093

30913094
// If this optarg can set the transient mode, then evaluate it if we're not at last word
30923095
if (oaptr->transient_mode && oaptr->transient_mode(cli, oaptr->name, value)) {
30933096
stage->error_word = stage->words[word_idx];
30943097
stage->status = CLI_ERROR;
3095-
return;
3098+
goto done;
30963099
}
30973100

30983101
// Only do buildmode optargs if we're a executing a command, parsing command (stage 0), and this is the last word
30993102
if ((stage->status == CLI_OK) && (oaptr->flags & CLI_CMD_ALLOW_BUILDMODE) && is_last_word) {
31003103
stage->status = cli_int_enter_buildmode(cli, stage, value);
3101-
return;
3104+
goto done;
31023105
}
31033106

31043107
// Optional flags and arguments can appear multiple times, but true arguments only once. Advance our optarg
@@ -3121,10 +3124,14 @@ static void cli_int_parse_optargs(struct cli_def *cli, struct cli_pipeline_stage
31213124
if (optarg->flags & CLI_CMD_ARGUMENT) {
31223125
cli_error(cli, "Incomplete command, missing required argument '%s'", optarg->name);
31233126
stage->status = CLI_MISSING_ARGUMENT;
3124-
return;
3127+
goto done;
31253128
}
31263129
}
31273130
}
3131+
3132+
done:
3133+
if (cli->buildmode) cli->buildmode->found_optargs = cli->found_optargs;
3134+
else stage->found_optargs = cli->found_optargs;
31283135
return;
31293136
}
31303137

libcli.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,7 @@ char *cli_find_optarg_value(struct cli_def *cli, char *name, char *find_after);
241241
struct cli_optarg_pair *cli_get_all_found_optargs(struct cli_def *cli);
242242
int cli_unregister_optarg(struct cli_command *cmd, const char *name);
243243
char *cli_get_optarg_value(struct cli_def *cli, const char *name, char *find_after);
244+
int cli_set_optarg_value(struct cli_def *cli, const char *name, const char *value, int allow_multiple);
244245
void cli_unregister_all_optarg(struct cli_command *c);
245246
void cli_unregister_all_filters(struct cli_def *cli);
246247
void cli_unregister_all_commands(struct cli_def *cli);

libcli.spec

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Version: 1.10.0
22
Summary: Cisco-like telnet command-line library
33
Name: libcli
4-
Release: 1
4+
Release: 2
55
License: LGPL
66
Group: Library/Communication
77
Source: %{name}-%{version}.tar.gz
@@ -60,14 +60,19 @@ rm -rf $RPM_BUILD_ROOT
6060
%defattr(-, root, root)
6161

6262
%files devel
63-
%doc README
63+
%doc README.md doc/developers-guide.md
6464
%{_libdir}/*.so*
6565
%{_libdir}/*.a
6666
%{_includedir}/*.h
6767
%defattr(-, root, root)
6868

6969
%changelog
70-
* Mon Jul 16 2019 Rob Sanders <rsanders@forcepoint.com> 1.10.0-1
70+
* Tue Jul 23 2019 Rob Sanders <rsanders@forcepoint.com> 1.10.0-2
71+
- Fix spec file and rpm build issues
72+
- Fix 2 memory leaks (tab completion and help formatting)
73+
- Expose cli_set_optarg_value() for external use
74+
75+
* Tue Jul 16 2019 Rob Sanders <rsanders@forcepoint.com> 1.10.0-1
7176
- Add support for named arguments, optional flags, and optional arguments
7277
- Support help and tab complete for options/arguments
7378
- Enable users to add custom 'filters', including support for options/arguments

0 commit comments

Comments
 (0)