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