Skip to content

Commit 6954851

Browse files
authored
Merge pull request #43 from RobSanders/optargs
Optargs
2 parents 96c4e40 + 65d21d7 commit 6954851

5 files changed

Lines changed: 1949 additions & 448 deletions

File tree

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ DESTDIR =
1010
PREFIX = /usr/local
1111

1212
MAJOR = 1
13-
MINOR = 9
14-
REVISION = 8
13+
MINOR = 10
14+
REVISION = 0
1515
LIB = libcli.so
1616
LIB_STATIC = libcli.a
1717

clitest.c

Lines changed: 185 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#include <errno.h>
2+
#include <limits.h>
13
#include <stdio.h>
24
#include <sys/types.h>
35
#ifdef WIN32
@@ -174,22 +176,137 @@ void pc(UNUSED(struct cli_def *cli), const char *string) {
174176
printf("%s\n", string);
175177
}
176178

177-
int main() {
178-
struct cli_command *c;
179-
struct cli_def *cli;
180-
int s, x;
181-
struct sockaddr_in addr;
182-
int on = 1;
179+
#define MODE_POLYGON_TRIANGLE 20
180+
#define MODE_POLYGON_RECTANGLE 21
183181

184-
#ifndef WIN32
185-
signal(SIGCHLD, SIG_IGN);
186-
#endif
187-
#ifdef WIN32
188-
if (!winsock_init()) {
189-
printf("Error initialising winsock\n");
190-
return 1;
182+
int cmd_perimeter(struct cli_def *cli, const char *command, char *argv[], int argc) {
183+
struct cli_optarg_pair *optargs = cli_get_all_found_optargs(cli);
184+
int i = 1, numSides = 0;
185+
int perimeter = 0;
186+
int verbose_count = 0;
187+
char *verboseArg = NULL;
188+
char *shapeName = NULL;
189+
190+
cli_print(cli, "perimeter callback, with %d args", argc);
191+
for (; optargs; optargs = optargs->next) cli_print(cli, "%d, %s=%s", i++, optargs->name, optargs->value);
192+
193+
if ((verboseArg = cli_get_optarg_value(cli, "verbose", verboseArg))) {
194+
do {
195+
verbose_count++;
196+
} while ((verboseArg = cli_get_optarg_value(cli, "verbose", verboseArg)));
191197
}
192-
#endif
198+
cli_print(cli, "verbose argument was seen %d times", verbose_count);
199+
200+
shapeName = cli_get_optarg_value(cli, "shape", NULL);
201+
if (!shapeName) {
202+
cli_error(cli, "No shape name given");
203+
return CLI_ERROR;
204+
} else if (strcmp(shapeName, "triangle") == 0) {
205+
numSides = 3;
206+
} else if (strcmp(shapeName, "rectangle") == 0) {
207+
numSides = 4;
208+
} else {
209+
cli_error(cli, "Unrecognized shape given");
210+
return CLI_ERROR;
211+
}
212+
for (i = 1; i <= numSides; i++) {
213+
char sidename[50], *value;
214+
int length;
215+
snprintf(sidename, 50, "side_%d", i);
216+
value = cli_get_optarg_value(cli, sidename, NULL);
217+
length = strtol(value, NULL, 10);
218+
perimeter += length;
219+
}
220+
cli_print(cli, "Perimeter is %d", perimeter);
221+
return CLI_OK;
222+
}
223+
224+
const char *KnownShapes[] = {"rectangle", "triangle", NULL};
225+
226+
int shape_completor(struct cli_def *cli, const char *name, const char *value, struct cli_comphelp *comphelp) {
227+
const char **shape;
228+
int rc = CLI_OK;
229+
printf("shape_completor called with <%s>\n", value);
230+
for (shape = KnownShapes; *shape && (rc == CLI_OK); shape++) {
231+
if (!value || !strncmp(*shape, value, strlen(value))) {
232+
rc = cli_add_comphelp_entry(comphelp, *shape);
233+
}
234+
}
235+
return rc;
236+
}
237+
238+
int shape_validator(struct cli_def *cli, const char *name, const char *value) {
239+
const char **shape;
240+
241+
printf("shape_validator called with <%s>\n", value);
242+
for (shape = KnownShapes; *shape; shape++) {
243+
if (!strcmp(value, *shape)) return CLI_OK;
244+
}
245+
return CLI_ERROR;
246+
}
247+
248+
int verbose_validator(struct cli_def *cli, const char *name, const char *value) {
249+
printf("verbose_validator called\n");
250+
return CLI_OK;
251+
}
252+
253+
int shape_transient_eval(struct cli_def *cli, const char *name, const char *value) {
254+
printf("shape_transient_eval called with <%s>\n", value);
255+
if (!strcmp(value, "rectangle")) {
256+
cli_set_transient_mode(cli, MODE_POLYGON_RECTANGLE);
257+
return CLI_OK;
258+
} else if (!strcmp(value, "triangle")) {
259+
cli_set_transient_mode(cli, MODE_POLYGON_TRIANGLE);
260+
return CLI_OK;
261+
}
262+
cli_error(cli, "unrecognized value for setting %s -> %s", name, value);
263+
return CLI_ERROR;
264+
}
265+
266+
const char *KnownColors[] = {"black", "white", "gray", "red", "blue",
267+
"green", "lightred", "lightblue", "lightgreen", "darkred",
268+
"darkblue", "darkgree", "lavender", "yellow", NULL};
269+
270+
int color_completor(struct cli_def *cli, const char *name, const char *word, struct cli_comphelp *comphelp) {
271+
// Attempt to show matches against the following color strings
272+
const char **color;
273+
int rc = CLI_OK;
274+
printf("color_completor called with <%s>\n", word);
275+
for (color = KnownColors; *color && (rc == CLI_OK); color++) {
276+
if (!word || !strncmp(*color, word, strlen(word))) {
277+
rc = cli_add_comphelp_entry(comphelp, *color);
278+
}
279+
}
280+
return rc;
281+
}
282+
283+
int color_validator(struct cli_def *cli, const char *name, const char *value) {
284+
const char **color;
285+
int rc = CLI_ERROR;
286+
printf("color_validator called for %s\n", name);
287+
for (color = KnownColors; *color; color++) {
288+
if (!strcmp(value, *color)) return CLI_OK;
289+
}
290+
return rc;
291+
}
292+
293+
int side_length_validator(struct cli_def *cli, const char *name, const char *value) {
294+
// Verify 'value' is a positive number
295+
long len;
296+
char *endptr;
297+
int rc = CLI_OK;
298+
299+
printf("side_length_validator called\n");
300+
errno = 0;
301+
len = strtol(value, &endptr, 10);
302+
if ((endptr == value) || (*endptr != '\0') || ((errno == ERANGE) && ((len == LONG_MIN) || (len == LONG_MAX))))
303+
return CLI_ERROR;
304+
return rc;
305+
}
306+
307+
void run_child(int x) {
308+
struct cli_command *c;
309+
struct cli_def *cli;
193310

194311
// Prepare a small user context
195312
char mymessage[] = "I contain user data!";
@@ -202,8 +319,12 @@ int main() {
202319
cli_set_hostname(cli, "router");
203320
cli_telnet_protocol(cli, 1);
204321
cli_regular(cli, regular_callback);
205-
cli_regular_interval(cli, 5); // Defaults to 1 second
206-
cli_set_idle_timeout_callback(cli, 60, idle_timeout); // 60 second idle timeout
322+
323+
// change regular update to 5 seconds rather than default of 1 second
324+
cli_regular_interval(cli, 5);
325+
326+
// set 60 second idle timeout
327+
cli_set_idle_timeout_callback(cli, 60, idle_timeout);
207328
cli_register_command(cli, NULL, "test", cmd_test, PRIVILEGE_UNPRIVILEGED, MODE_EXEC, NULL);
208329
cli_register_command(cli, NULL, "simple", NULL, PRIVILEGE_UNPRIVILEGED, MODE_EXEC, NULL);
209330
cli_register_command(cli, NULL, "simon", NULL, PRIVILEGE_UNPRIVILEGED, MODE_EXEC, NULL);
@@ -223,6 +344,34 @@ int main() {
223344
cli_register_command(cli, c, "regular", cmd_debug_regular, PRIVILEGE_UNPRIVILEGED, MODE_EXEC,
224345
"Enable cli_regular() callback debugging");
225346

347+
// Register some commands/subcommands to demonstrate opt/arg and buildmode operations
348+
349+
c = cli_register_command(cli, NULL, "perimeter", cmd_perimeter, PRIVILEGE_UNPRIVILEGED, MODE_EXEC,
350+
"Calculate perimeter of polygon");
351+
cli_register_optarg(c, "transparent", CLI_CMD_OPTIONAL_FLAG, PRIVILEGE_UNPRIVILEGED, MODE_EXEC,
352+
"Set transparent flag", NULL, NULL, NULL);
353+
cli_register_optarg(c, "verbose", CLI_CMD_OPTIONAL_FLAG | CLI_CMD_OPTION_MULTIPLE, PRIVILEGE_UNPRIVILEGED, MODE_EXEC,
354+
"Set transparent flag", NULL, NULL, NULL);
355+
cli_register_optarg(c, "shape", CLI_CMD_ARGUMENT | CLI_CMD_ALLOW_BUILDMODE, PRIVILEGE_UNPRIVILEGED, MODE_EXEC,
356+
"Specify shape to calclate perimeter for", shape_completor, shape_validator,
357+
shape_transient_eval);
358+
cli_register_optarg(c, "color", CLI_CMD_OPTIONAL_ARGUMENT, PRIVILEGE_UNPRIVILEGED, MODE_EXEC, "Set color",
359+
color_completor, color_validator, NULL);
360+
cli_register_optarg(c, "side_1", CLI_CMD_ARGUMENT, PRIVILEGE_UNPRIVILEGED, MODE_POLYGON_TRIANGLE,
361+
"Specify side 1 length", NULL, side_length_validator, NULL);
362+
cli_register_optarg(c, "side_1", CLI_CMD_ARGUMENT, PRIVILEGE_UNPRIVILEGED, MODE_POLYGON_RECTANGLE,
363+
"Specify side 1 length", NULL, side_length_validator, NULL);
364+
cli_register_optarg(c, "side_2", CLI_CMD_ARGUMENT, PRIVILEGE_UNPRIVILEGED, MODE_POLYGON_TRIANGLE,
365+
"Specify side 2 length", NULL, side_length_validator, NULL);
366+
cli_register_optarg(c, "side_2", CLI_CMD_ARGUMENT, PRIVILEGE_UNPRIVILEGED, MODE_POLYGON_RECTANGLE,
367+
"Specify side 2 length", NULL, side_length_validator, NULL);
368+
cli_register_optarg(c, "side_3", CLI_CMD_ARGUMENT, PRIVILEGE_UNPRIVILEGED, MODE_POLYGON_TRIANGLE,
369+
"Specify side 3 length", NULL, side_length_validator, NULL);
370+
cli_register_optarg(c, "side_3", CLI_CMD_ARGUMENT, PRIVILEGE_UNPRIVILEGED, MODE_POLYGON_RECTANGLE,
371+
"Specify side 3 length", NULL, side_length_validator, NULL);
372+
cli_register_optarg(c, "side_4", CLI_CMD_ARGUMENT, PRIVILEGE_UNPRIVILEGED, MODE_POLYGON_RECTANGLE,
373+
"Specify side 4 length", NULL, side_length_validator, NULL);
374+
226375
// Set user context and its command
227376
cli_set_context(cli, (void *)&myctx);
228377
cli_register_command(cli, NULL, "context", cmd_context, PRIVILEGE_UNPRIVILEGED, MODE_EXEC,
@@ -242,6 +391,24 @@ int main() {
242391
fclose(fh);
243392
}
244393
}
394+
cli_loop(cli, x);
395+
cli_done(cli);
396+
}
397+
398+
int main() {
399+
int s, x;
400+
struct sockaddr_in addr;
401+
int on = 1;
402+
403+
#ifndef WIN32
404+
signal(SIGCHLD, SIG_IGN);
405+
#endif
406+
#ifdef WIN32
407+
if (!winsock_init()) {
408+
printf("Error initialising winsock\n");
409+
return 1;
410+
}
411+
#endif
245412

246413
if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
247414
perror("socket");
@@ -287,15 +454,14 @@ int main() {
287454

288455
/* child */
289456
close(s);
290-
cli_loop(cli, x);
457+
run_child(x);
291458
exit(0);
292459
#else
293-
cli_loop(cli, x);
460+
run_child(x);
294461
shutdown(x, SD_BOTH);
295462
close(x);
296463
#endif
297464
}
298465

299-
cli_done(cli);
300466
return 0;
301467
}

0 commit comments

Comments
 (0)