CNDP  22.08.0
cli.h
Go to the documentation of this file.
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright (c) 2019-2022 Intel Corporation.
3  */
4 
5 #ifndef _CLI_H_
6 #define _CLI_H_
7 
14 #include <libgen.h>
15 #include <sys/queue.h> // for TAILQ_HEAD, CIRCLEQ_HEAD, TAILQ_ENTRY
16 #include <cne_common.h> // for CNDP_API, __cne_cache_aligned
17 #include <cne_log.h> // for CNE_ASSERT
18 #include <cli_common.h>
19 #include <cli_env.h> // for cli_sfunc_t
20 #include <cli_search.h>
21 #include <cli_file.h>
22 #include <cli_gapbuf.h>
23 #include <cli_help.h>
24 #include <cli_history.h>
25 #include <cli_map.h>
26 #include <cne_strings.h>
27 #include <stdint.h> // for uint32_t, uint16_t, uint8_t
28 #include <string.h> // for strcat, NULL, strcpy, strdup, size_t
29 
30 #include "cne_stdio.h" // for cne_printf
31 
32 #ifdef __cplusplus
33 extern "C" {
34 #endif
35 
36 #define CLI_ROOT_NAME "/"
37 #define CLI_BIN_NAME "bin"
38 
39 enum {
45  CLI_NAME_LEN = 64,
47  CLI_MAX_BINS = 32,
49  CLI_SCREEN_WIDTH = 80
50 };
51 
52 #define CLI_RECURSE_FLAG (1 << 0)
53 #define CLI_LONG_LIST_FLAG (1 << 1)
54 
56 typedef enum {
57  CLI_UNK_NODE = 0x0000,
58  CLI_DIR_NODE = 0x0001,
59  CLI_CMD_NODE = 0x0002,
60  CLI_FILE_NODE = 0x0004,
61  CLI_ALIAS_NODE = 0x0008,
62  CLI_STR_NODE = 0x0010,
63 } node_type_t;
64 
65 /* Keep this list in sync with the node_type_t enum above */
66 #define CLI_NODE_TYPES \
67  { \
68  "Unknown", "Directory", "Command", "File", "Alias", "String", NULL \
69  }
70 
71 enum {
72  CLI_EXE_TYPE = (CLI_CMD_NODE | CLI_ALIAS_NODE),
73  CLI_ALL_TYPE = (CLI_EXE_TYPE | CLI_FILE_NODE | CLI_DIR_NODE),
74  CLI_OTHER_TYPE = (CLI_DIR_NODE | CLI_FILE_NODE)
75 };
76 
77 struct cli;
78 struct cli_node;
79 
80 typedef int (*cli_cfunc_t)(int argc, char **argv);
82 typedef int (*cli_ffunc_t)(struct cli_node *node, char *buff, int len, uint32_t opt);
85 typedef int (*cli_prompt_t)(int continuation);
86 typedef int (*cli_tree_t)(void);
89 /* Generic node structure for all node types in the directory tree */
90 struct cli_node {
91  TAILQ_ENTRY(cli_node) next;
92  struct cli_node *parent;
93  char name[CLI_NAME_LEN];
94  uint16_t name_sz;
95  uint16_t fstate;
96  uint16_t fflags;
97  uint16_t pad0;
98  node_type_t type;
99  union {
100  cli_cfunc_t cfunc;
101  cli_ffunc_t ffunc;
102  cli_sfunc_t sfunc;
103  };
104  const char *short_desc;
105  const char *alias_str;
106  size_t foffset;
107  size_t file_size;
108  char *file_data;
109  TAILQ_HEAD(, cli_node) items;
112 #define MAX_CMD_FILES 16
113 
114 typedef struct {
115  char *filename[MAX_CMD_FILES];
116  uint32_t idx;
117 } cli_files_t;
118 
119 struct cli_cfg {
120  int nb_nodes;
121  int nb_hist;
122 };
123 
124 struct cli {
125  TAILQ_HEAD(, cli_node) root;
126  CIRCLEQ_HEAD(, cli_hist) hd_hist;
128  uint32_t flags;
129  uint32_t nb_nodes;
131  uint8_t plen;
132  uint8_t tab_cnt;
134  uint32_t nb_hist;
135  struct cli_hist *curr_hist;
136  struct cli_node *bins[CLI_MAX_BINS];
138  struct cli_node *exe_node;
140  struct cli_env *env;
141  struct gapbuf *gb;
142  struct cli_vt100 *vt;
143  char **argv;
145  cli_prompt_t prompt;
146  char *scratch;
147  char *kill;
149  struct cli_node *node_mem;
150  struct cli_hist *hist_mem;
152  TAILQ_HEAD(, help_node) help_nodes;
153  TAILQ_HEAD(, cli_node) free_nodes;
154  CIRCLEQ_HEAD(, cli_hist) free_hist;
155  void *user_state;
157 
158 extern struct cli *this_cli;
159 extern cli_files_t cli_cmd_files;
161 /* cli.flags */
162 #define CLEAR_TO_EOL (1 << 0)
163 #define DISPLAY_PROMPT (1 << 1)
164 #define PROMPT_CONTINUE (1 << 2)
165 #define DELETE_CHAR (1 << 3)
166 #define CLEAR_LINE (1 << 4)
167 
168 #define CLI_USE_TIMERS (1 << 8)
169 #define CLI_NODES_UNLIMITED (1 << 9)
170 #define CLI_YIELD_IO (1 << 10)
171 #define CLI_DEFAULT_TREE (1 << 11)
172 
173 static inline void
174 cli_set_flag(uint32_t x)
175 {
176  this_cli->flags |= x;
177 }
178 
179 static inline void
180 cli_clr_flag(uint32_t x)
181 {
182  this_cli->flags &= ~x;
183 }
184 
185 static inline int
186 cli_tst_flag(uint32_t x)
187 {
188  return this_cli->flags & x;
189 }
190 
191 typedef union {
192  cli_cfunc_t cfunc;
193  cli_ffunc_t ffunc;
194  cli_sfunc_t sfunc;
195 } cli_funcs_t; /* Internal: Used in argument list for adding nodes */
196 
197 struct cli_dir {
198  const char *name;
199  uint8_t bin;
200 };
201 
202 struct cli_cmd {
203  const char *name;
205  const char *short_desc;
206 };
208 struct cli_alias {
209  const char *name;
210  const char *alias_atr;
211  const char *short_desc;
212 };
214 struct cli_file {
215  const char *name;
217  const char *short_desc;
218 };
220 struct cli_str {
221  const char *name;
223  const char *string;
224 };
226 struct cli_tree {
227  node_type_t type;
228  union {
229  struct cli_dir dir;
230  struct cli_cmd cmd;
231  struct cli_file file;
232  struct cli_alias alias;
233  struct cli_str str;
234  };
235 };
236 
237 // clang-format off
239 #define c_dir(n) { CLI_DIR_NODE, .dir = {.name = (n), .bin = 0} }
240 #define c_bin(n) { CLI_DIR_NODE, .dir = {.name = (n), .bin = 1} }
241 #define c_cmd(n, f, h) { CLI_CMD_NODE, .cmd = {.name = (n), .cfunc = (f), .short_desc = (h)} }
242 #define c_file(n, rw, h) { CLI_FILE_NODE, .file = {.name = (n), .ffunc = (rw), .short_desc = (h)} }
243 #define c_alias(n, l, h) { CLI_ALIAS_NODE, .alias = {.name = (n), .alias_atr = (l), .short_desc = (h)} }
244 #define c_str(n, f, s) { CLI_STR_NODE, .str = {.name = (n), .sfunc = (f), .string = (s)} }
245 #define c_end() { CLI_UNK_NODE, .dir = { NULL } }
246 // clang-format on
247 
248 static inline void
249 cli_set_user_state(void *val)
250 {
251  this_cli->user_state = val;
252 }
253 
260 static inline struct cli_node *
261 get_root(void)
262 {
263  CNE_ASSERT(this_cli != NULL);
264  return this_cli->root.tqh_first;
265 }
266 
273 static inline struct cli_node *
274 get_cwd(void)
275 {
276  CNE_ASSERT(this_cli != NULL);
277  return this_cli->bins[0];
278 }
279 
286 static inline void
287 set_cwd(struct cli_node *node)
288 {
289  CNE_ASSERT(this_cli != NULL);
290  this_cli->bins[0] = node;
291 }
292 
299 static inline int
301 {
302  return (this_cli) ? 1 : 0;
303 }
304 
315 static inline int
316 is_match(const char *s1, const char *s2)
317 {
318  if (!s1 || !s2)
319  return 0;
320 
321  while ((*s1 != '\0') && (*s2 != '\0')) {
322  if (*s1++ != *s2++)
323  return 0;
324  }
325  if (*s1 != *s2)
326  return 0;
327 
328  return 1;
329 }
330 
341 static inline int
342 is_node(struct cli_node *node, uint32_t types)
343 {
344  return node->type & types;
345 }
346 
355 static inline int
356 is_command(struct cli_node *node)
357 {
358  return is_node(node, CLI_CMD_NODE);
359 }
360 
369 static inline int
370 is_alias(struct cli_node *node)
371 {
372  return is_node(node, CLI_ALIAS_NODE);
373 }
374 
383 static inline int
384 is_file(struct cli_node *node)
385 {
386  return is_node(node, CLI_FILE_NODE);
387 }
388 
397 static inline int
398 is_directory(struct cli_node *node)
399 {
400  return is_node(node, CLI_DIR_NODE);
401 }
402 
411 static inline int
412 is_executable(struct cli_node *node)
413 {
414  return is_command(node) || is_alias(node);
415 }
416 
423 static inline int
425 {
426  if (this_cli && this_cli->exe_node) {
427  const char *p = this_cli->exe_node->short_desc;
428 
429  cne_printf(" Usage: %s\n", (p) ? p : "No description found");
430  }
431  return -1;
432 }
433 
442 static inline const char *
443 cli_node_type(struct cli_node *node)
444 {
445  const char *node_str[] = CLI_NODE_TYPES;
446  switch (node->type) {
447  case CLI_UNK_NODE:
448  default:
449  break;
450  case CLI_DIR_NODE:
451  return node_str[1];
452  case CLI_CMD_NODE:
453  return node_str[2];
454  case CLI_FILE_NODE:
455  return node_str[3];
456  case CLI_ALIAS_NODE:
457  return node_str[4];
458  }
459  return node_str[0];
460 }
461 
473 static inline char *
474 cli_path_string(struct cli_node *node, char *path)
475 {
476  if (!path)
477  path = this_cli->scratch;
478 
479  if (!node)
480  node = get_cwd();
481 
482  if (node->parent) {
483  cli_path_string(node->parent, path);
484  strcat(path, node->name);
485  strcat(path, "/");
486  } else
487  strcpy(path, "/");
488 
489  return path;
490 }
491 
498 static inline char *
500 {
501  return cli_path_string(get_cwd(), NULL);
502 }
503 
511 static inline void
512 cli_pwd(struct cli_node *node)
513 {
514  cne_printf("%s", cli_path_string(node, NULL));
515 }
516 
525 static inline int
526 cli_set_history_size(uint32_t nb_hist)
527 {
528  return cli_set_history(nb_hist);
529 }
530 
537 static inline uint32_t
539 {
540  return this_cli->nb_hist;
541 }
542 
547 static inline void
549 {
551 }
552 
559 static inline struct cli_node *
561 {
562  return this_cli->root.tqh_first;
563 }
564 
573 CNDP_API int cli_create(struct cli_cfg *cfg);
574 
583 CNDP_API int cli_create_with_defaults(struct cli_cfg *cfg);
584 
595 CNDP_API int cli_setup(cli_prompt_t prompt, cli_tree_t default_func);
596 
603 CNDP_API int cli_setup_with_defaults(void);
604 
614 CNDP_API int cli_setup_with_tree(cli_tree_t tree);
615 
625 
636 CNDP_API struct cli_node *cli_create_root(const char *dirname);
637 
644 CNDP_API int cli_default_tree_init(void);
645 
650 CNDP_API void cli_destroy(void);
651 
658 CNDP_API void cli_start(const char *msg);
659 
666 CNDP_API void cli_start_with_timers(const char *msg);
667 
674 CNDP_API int cli_execute(void);
675 
684 CNDP_API int cli_add_bin(struct cli_node *node);
685 
694 CNDP_API int cli_del_bin(struct cli_node *node);
695 
704 CNDP_API int cli_add_bin_path(const char *path);
705 
716 CNDP_API struct cli_node *cli_add_dir(const char *dirname, struct cli_node *parent);
717 
732 CNDP_API struct cli_node *cli_add_cmd(const char *name, struct cli_node *dir, cli_cfunc_t func,
733  const char *short_desc);
734 
749 CNDP_API struct cli_node *cli_add_alias(const char *name, struct cli_node *dir, const char *line,
750  const char *short_desc);
751 
766 CNDP_API struct cli_node *cli_add_file(const char *name, struct cli_node *dir, cli_ffunc_t func,
767  const char *short_desc);
768 
781 CNDP_API int cli_add_str(const char *name, cli_sfunc_t func, const char *str);
782 
793 CNDP_API int cli_add_tree(struct cli_node *dir, struct cli_tree *tree);
794 
803 static inline int
804 cli_add_cmdfile(const char *filename)
805 {
806  if (cli_cmd_files.idx >= MAX_CMD_FILES)
807  return -1;
808 
809  cli_cmd_files.filename[cli_cmd_files.idx++] = strdup(filename);
810 
811  return 0;
812 }
813 
822 CNDP_API int cli_execute_cmdfile(const char *path);
823 
830 CNDP_API int cli_execute_cmdfiles(void);
831 
840 CNDP_API int cli_remove_node(struct cli_node *node);
841 
845 CNDP_API void cli_use_timers(void);
846 
853 CNDP_API int cli_nodes_unlimited(void);
854 
865 CNDP_API int cli_execute_cmd(int argc, char **argv);
866 
873 CNDP_API int cli_get_quit_flag(void);
874 
879 CNDP_API void cli_set_quit_flag(void);
880 
881 #ifdef __cplusplus
882 }
883 #endif
884 
885 #endif /* _CLI_H_ */
CNDP_API struct cli_node * cli_create_root(const char *dirname)
CNDP_API int cli_setup_with_defaults(void)
static int cli_add_cmdfile(const char *filename)
Definition: cli.h:804
static int cli_usage(void)
Definition: cli.h:424
static struct cli_node * cli_root_node(void)
Definition: cli.h:560
int(* cli_cfunc_t)(int argc, char **argv)
Definition: cli.h:80
CNDP_API struct cli_node * cli_add_alias(const char *name, struct cli_node *dir, const char *line, const char *short_desc)
static void set_cwd(struct cli_node *node)
Definition: cli.h:287
CNDP_API struct cli_node * cli_add_file(const char *name, struct cli_node *dir, cli_ffunc_t func, const char *short_desc)
static char * cli_path_string(struct cli_node *node, char *path)
Definition: cli.h:474
static int is_node(struct cli_node *node, uint32_t types)
Definition: cli.h:342
CNDP_API int cli_default_tree_init(void)
CNDP_API void cli_start(const char *msg)
CNDP_API int cli_add_bin(struct cli_node *node)
CNDP_API void cli_set_quit_flag(void)
static int is_command(struct cli_node *node)
Definition: cli.h:356
static int is_executable(struct cli_node *node)
Definition: cli.h:412
static int is_file(struct cli_node *node)
Definition: cli.h:384
CNDP_API int cli_del_bin(struct cli_node *node)
CNDP_API void cli_use_timers(void)
static int is_cli_valid(void)
Definition: cli.h:300
CNDP_API int cli_setup_with_tree(cli_tree_t tree)
static int is_match(const char *s1, const char *s2)
Definition: cli.h:316
CNDP_API int cli_remove_node(struct cli_node *node)
CNDP_API void cli_destroy(void)
int(* cli_prompt_t)(int continuation)
Definition: cli.h:85
int(* cli_ffunc_t)(struct cli_node *node, char *buff, int len, uint32_t opt)
Definition: cli.h:82
CNDP_API int cli_create(struct cli_cfg *cfg)
int(* cli_tree_t)(void)
Definition: cli.h:86
static char * cli_cwd_path(void)
Definition: cli.h:499
static int cli_set_history_size(uint32_t nb_hist)
Definition: cli.h:526
CNDP_API int cli_execute_cmdfile(const char *path)
CNDP_API int cli_add_tree(struct cli_node *dir, struct cli_tree *tree)
CNDP_API int cli_add_bin_path(const char *path)
CNDP_API int cli_setup(cli_prompt_t prompt, cli_tree_t default_func)
CNDP_API int cli_execute_cmdfiles(void)
static struct cli_node * get_cwd(void)
Definition: cli.h:274
CNDP_API int cli_get_quit_flag(void)
@ CLI_DEFAULT_NB_NODES
Definition: cli.h:41
@ CLI_MAX_SCRATCH_LENGTH
Definition: cli.h:44
@ CLI_SCREEN_WIDTH
Definition: cli.h:49
@ CLI_MAX_LIST_NODES
Definition: cli.h:46
@ CLI_MAX_BINS
Definition: cli.h:47
@ CLI_DEFAULT_NODES
Definition: cli.h:48
@ CLI_MAX_ARGVS
Definition: cli.h:40
@ CLI_MAX_PATH_LENGTH
Definition: cli.h:43
@ CLI_NAME_LEN
Definition: cli.h:45
@ CLI_DEFAULT_HIST_LINES
Definition: cli.h:42
node_type_t
Definition: cli.h:56
@ CLI_ALIAS_NODE
Definition: cli.h:61
@ CLI_STR_NODE
Definition: cli.h:62
@ CLI_UNK_NODE
Definition: cli.h:57
@ CLI_CMD_NODE
Definition: cli.h:59
@ CLI_DIR_NODE
Definition: cli.h:58
@ CLI_FILE_NODE
Definition: cli.h:60
CNDP_API struct cli_node * cli_add_cmd(const char *name, struct cli_node *dir, cli_cfunc_t func, const char *short_desc)
static int is_directory(struct cli_node *node)
Definition: cli.h:398
CNDP_API int cli_execute_cmd(int argc, char **argv)
static void cli_history_list(void)
Definition: cli.h:548
CNDP_API void cli_start_with_timers(const char *msg)
static const char * cli_node_type(struct cli_node *node)
Definition: cli.h:443
struct cli_node __cne_cache_aligned
CNDP_API int cli_add_str(const char *name, cli_sfunc_t func, const char *str)
cli_files_t cli_cmd_files
static int is_alias(struct cli_node *node)
Definition: cli.h:370
static struct cli_node * get_root(void)
Definition: cli.h:261
CNDP_API cli_prompt_t cli_set_prompt(cli_prompt_t prompt)
CNDP_API int cli_execute(void)
static uint32_t cli_get_history_size(void)
Definition: cli.h:538
static void cli_pwd(struct cli_node *node)
Definition: cli.h:512
CNDP_API int cli_create_with_defaults(struct cli_cfg *cfg)
CNDP_API struct cli_node * cli_add_dir(const char *dirname, struct cli_node *parent)
CNDP_API int cli_nodes_unlimited(void)
char *(* cli_sfunc_t)(const char *str)
Definition: cli_env.h:22
CNDP_API int cli_set_history(uint32_t nb_hist)
CNDP_API void cli_history_dump(void)
CNDP_API int cne_printf(const char *fmt,...)
TAILQ_HEAD(pktdev_driver_list, pktdev_driver)
Definition: cli.h:208
const char * short_desc
Definition: cli.h:211
const char * name
Definition: cli.h:209
const char * alias_atr
Definition: cli.h:210
Definition: cli.h:202
const char * short_desc
Definition: cli.h:205
cli_cfunc_t cfunc
Definition: cli.h:204
const char * name
Definition: cli.h:203
Definition: cli.h:214
const char * short_desc
Definition: cli.h:217
const char * name
Definition: cli.h:215
cli_ffunc_t ffunc
Definition: cli.h:216
Definition: cli.h:220
const char * name
Definition: cli.h:221
cli_sfunc_t sfunc
Definition: cli.h:222
const char * string
Definition: cli.h:223