The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
command.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 2 of the License, or
5  * (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15  */
16 
17 /**
18  * $Id: 98890f987989f0a9ed7705ab1055515f56f5a968 $
19  *
20  * @file command.c
21  * @brief Internal commands for the server
22  *
23  * @copyright 2018 The FreeRADIUS server project
24  * @copyright 2018 Alan DeKok (aland@freeradius.org)
25  */
26 RCSID("$Id: 98890f987989f0a9ed7705ab1055515f56f5a968 $")
27 
28 #include <freeradius-devel/server/command.h>
29 #include <freeradius-devel/server/log.h>
30 #include <freeradius-devel/util/debug.h>
31 
32 #include <freeradius-devel/util/misc.h>
33 
34 /*
35  * Registration hooks for radmin.
36  */
37 static int fr_command_register(UNUSED TALLOC_CTX *talloc_ctx, UNUSED char const *name, UNUSED void *ctx, UNUSED fr_cmd_table_t *table)
38 {
39  return 0;
40 }
41 
43 
44 typedef struct fr_cmd_argv_s fr_cmd_argv_t;
45 struct fr_cmd_argv_s {
46  char const *name;
50 };
51 
52 struct fr_cmd_s {
53  char const *name;
54 
55  struct fr_cmd_s *next;
56  struct fr_cmd_s *child; //!< if there are subcommands
57 
58  char const *syntax; //!< only for terminal nodes
59  char const *help; //!< @todo - long / short help
60 
61  fr_cmd_argv_t *syntax_argv; //!< arguments and types
62 
63  void *ctx;
66 
67  bool read_only;
68  bool intermediate; //!< intermediate commands can't have callbacks
69  bool live; //!< is this entry live?
70  bool added_name; //!< was this name added?
71 };
72 
73 
74 static int fr_command_verify_argv(fr_cmd_info_t *info, int start, int verify, int argc, fr_cmd_argv_t **argv_p, bool optional) CC_HINT(nonnull);
75 static bool fr_command_valid_name(char const *name);
76 static int split(char **input, char **output, bool syntax_string);
77 
78 /*
79  * Hacks for simplicity. These data types aren't allowed as
80  * parameters, so we can reuse them for something else.
81  */
82 
83 // our fixed string. Any data type LESS than this must be a real data type
84 #define FR_TYPE_FIXED FR_TYPE_TIME_DELTA
85 
86 #define FR_TYPE_VARARGS FR_TYPE_TLV
87 #define FR_TYPE_OPTIONAL FR_TYPE_STRUCT
88 #define FR_TYPE_ALTERNATE FR_TYPE_VSA
89 #define FR_TYPE_ALTERNATE_CHOICE FR_TYPE_GROUP
90 
91 /** Find a command
92  *
93  * @param head the head of the list
94  * @param name of the command to find
95  * @param insert where the new command should be inserted
96  * @return
97  * - NULL for "not found". In which case "head" is the insertion point for the new command
98  * - !NULL for the command which was found.
99  */
100 static fr_cmd_t *fr_command_find(fr_cmd_t **head, char const *name, fr_cmd_t ***insert)
101 {
102  fr_cmd_t *cmd, **where = head;
103 
104  if (!head || !name) return NULL;
105 
106  if (!*head) {
107  if (insert) *insert = head;
108  return NULL;
109  }
110 
111  for (cmd = *head; cmd != NULL; cmd = cmd->next) {
112  int status;
113 
114  status = strcmp(cmd->name, name);
115 
116  /*
117  * Not found yet.
118  */
119  if (status < 0) {
120  where = &(cmd->next);
121  continue;
122  }
123 
124  /*
125  * Not in the list.
126  */
127  if (status > 0) break;
128 
129  /*
130  * Was found, return it.
131  */
132  return cmd;
133  }
134 
135  if (insert) *insert = where;
136 
137  return NULL;
138 }
139 
140 /** Allocate an fr_cmd_t structure
141  *
142  * We presume that this allocation is done after a call to fr_command_find()
143  *
144  * @param ctx talloc ctx for the allocation
145  * @param head of the command list (singly linked)
146  * @param name of the command to allocate
147  * @return
148  * - fr_cmd_t structure which has been allocated. Only "name" is filled in.
149  */
150 static fr_cmd_t *fr_command_alloc(TALLOC_CTX *ctx, fr_cmd_t **head, char const *name)
151 
152 {
153  fr_cmd_t *cmd;
154 
155  MEM(cmd = talloc_zero(ctx, fr_cmd_t));
156  cmd->name = talloc_strdup(ctx, name);
157  cmd->intermediate = true;
158  cmd->live = false;
159 
160  cmd->next = *head;
161  cmd->read_only = true;
162  *head = cmd;
163 
164  return cmd;
165 }
166 
167 
168 /*
169  * Validate a name (or syntax)
170  *
171  * We have to be careful here, because some commands are taken
172  * from module names, which can be almost anything.
173  */
174 static bool fr_command_valid_name(char const *name)
175 {
176  uint8_t const *p;
177 
178  for (p = (uint8_t const *) name; *p != '\0'; p++) {
179  if (*p < ' ') {
180  fr_strerror_const("Invalid control character in name");
181  return false;
182  }
183 
184  if (((*p >= ' ') && (*p <= ',')) ||
185  ((*p >= ':') && (*p <= '@')) ||
186  ((*p >= '[') && (*p <= '^')) ||
187  ((*p > 'z') && (*p <= 0xf7)) ||
188  (*p == '`')) {
189  fr_strerror_const("Invalid special character");
190  return false;
191  }
192 
193  /*
194  * Allow valid UTF-8 characters.
195  */
196  if (fr_utf8_char(p, -1)) continue;
197 
198  fr_strerror_const("Invalid non-UTF8 character in name");
199  }
200 
201  return true;
202 }
203 
205 {
206  char const *p;
207  bool lowercase = false;
208  bool uppercase = false;
209 
210  argv->type = FR_TYPE_FIXED;
211 
212  if (!fr_command_valid_name(argv->name)) {
213  return false;
214  }
215 
216  for (p = argv->name; *p != '\0'; p++) {
217  if (isupper((uint8_t) *p)) uppercase = true;
218  if (islower((uint8_t) *p)) lowercase = true;
219  }
220 
221  /*
222  * No alphabetical characters, that's a
223  * problem.
224  */
225  if (!uppercase && !lowercase) {
226  fr_strerror_printf("Syntax command '%s' has no alphabetical characters", argv->name);
227  return false;
228  }
229 
230  /*
231  * Mixed case is not allowed in a syntax.
232  */
233  if (uppercase && lowercase) {
234  fr_strerror_printf("Syntax command '%s' has invalid mixed case", argv->name);
235  return false;
236  }
237 
238  /*
239  * All-uppercase words MUST be valid data
240  * types.
241  */
242  if (uppercase) {
243  fr_type_t type;
244 
246  switch (type) {
247  case FR_TYPE_MAX:
248  case FR_TYPE_NULL:
249  case FR_TYPE_STRUCTURAL:
250  case FR_TYPE_VALUE_BOX:
251  case FR_TYPE_VOID:
252  fr_strerror_printf("Syntax command '%s' has unknown data type", argv->name);
253  return false;
254 
255  default:
256  break;
257  }
258 
259  argv->type = type;
260  }
261 
262  return true;
263 }
264 
265 /*
266  * Like split, but is alternation aware.
267  */
268 static int split_alternation(char **input, char **output)
269 {
270  char quote;
271  char *str = *input;
272  char *word;
273 
274  /*
275  * String is empty, we're done.
276  */
277  if (!*str) return 0;
278 
279  /*
280  * Skip leading whitespace.
281  */
282  while ((*str == ' ') ||
283  (*str == '\t') ||
284  (*str == '\r') ||
285  (*str == '\n'))
286  *(str++) = '\0';
287 
288  /*
289  * String is empty, we're done.
290  */
291  if (!*str) return 0;
292 
293  /*
294  * Remember the start of the word.
295  */
296  word = str;
297 
298  if ((*str == '[') || (*str == '(')) {
299  char end;
300  int count = 0;
301 
302  quote = *(str++);
303 
304  if (quote == '[') {
305  end = ']';
306  } else {
307  end = ')';
308  }
309 
310  /*
311  * Don't allow backslashes here. This piece is
312  * only for parsing syntax strings, which CANNOT
313  * have quotes in them.
314  */
315  while ((*str != end) || (count > 0)) {
316  if (!*str) {
317  fr_strerror_const("String ends before closing brace.");
318  return -1;
319  }
320 
321  if (*str == quote) count++;
322  if (*str == end) count--;
323 
324  str++;
325  }
326 
327  /*
328  * Skip the final "quotation" mark.
329  */
330  str++;
331 
332  /*
333  * [foo bar]baz is invalid.
334  */
335  if ((*str != '\0') &&
336  (*str != ' ') &&
337  (*str != '|') &&
338  (*str != '\t')) {
339  fr_strerror_const("Invalid text after quoted string.");
340  return -1;
341  }
342  } else {
343  int count = 0;
344 
345  /*
346  * Skip until we reach the next alternation,
347  * ignoring | in nested alternation.
348  *
349  */
350  while (*str) {
351  if (*str == '(') {
352  count++;
353  } else if (*str == ')') {
354  count--;
355  } else if (count == 0) {
356  if (*str == '|') break;
357  }
358  str++;
359  }
360  }
361 
362  /*
363  * One of the above characters is after the word.
364  * Over-write it with NUL. If *str==0, then we leave it
365  * alone, so that the next call to split() discovers it,
366  * and returns NULL.
367  */
368  if (*str) {
369  /*
370  * Skip trailing whitespace so that the caller
371  * can peek at the next argument.
372  */
373  while ((*str == ' ') ||
374  (*str == '|') ||
375  (*str == '\t')) {
376  *(str++) = '\0';
377  }
378  }
379 
380  *input = str;
381  *output = word;
382  return 1;
383 }
384 
385 static int split(char **input, char **output, bool syntax_string)
386 {
387  char quote;
388  char *str = *input;
389  char *word;
390 
391  /*
392  * String is empty, we're done.
393  */
394  if (!*str) return 0;
395 
396  /*
397  * Skip leading whitespace.
398  */
399  while ((*str == ' ') ||
400  (*str == '\t') ||
401  (*str == '\r') ||
402  (*str == '\n'))
403  *(str++) = '\0';
404 
405  /*
406  * String is empty, we're done.
407  */
408  if (!*str) return 0;
409 
410  /*
411  * String is only comments, we're done.
412  */
413  if (*str == '#') {
414  *str = '\0';
415  return 0;
416  }
417 
418  /*
419  * Remember the start of the word.
420  */
421  word = str;
422 
423  /*
424  * Quoted string? Skip to the trailing quote.
425  *
426  * But only if we're not parsing a syntax string.
427  */
428  if (!syntax_string && ((*str == '"') || (*str == '\''))) {
429  quote = *(str++);
430 
431  while (*str != quote) {
432  if (!*str) {
433  fr_strerror_const("String is not terminated with a quotation character.");
434  return -1;
435  }
436 
437  /*
438  * Skip backslashes and the following character
439  */
440  if (*str == '\\') {
441  str++;
442  if (!*str) {
443  fr_strerror_const("Invalid backslash at end of string.");
444  return -1;
445  }
446  str++;
447  continue;
448  }
449 
450  str++;
451  }
452 
453  /*
454  * Skip the final quotation mark.
455  */
456  str++;
457 
458  /*
459  * "foo"bar is invalid.
460  */
461  if ((*str != '\0') &&
462  (*str != ' ') &&
463  (*str != '#') &&
464  (*str != '\t') &&
465  (*str != '\r') &&
466  (*str != '\n')) {
467  fr_strerror_const("Invalid text after quoted string.");
468  return -1;
469  }
470 
471  } else if (syntax_string && ((*str == '[') || (*str == '('))) {
472  char end;
473  int count = 0;
474 
475  quote = *(str++);
476 
477  if (quote == '[') {
478  end = ']';
479  } else {
480  end = ')';
481  }
482 
483  /*
484  * Don't allow backslashes here. This piece is
485  * only for parsing syntax strings, which CANNOT
486  * have quotes in them.
487  */
488  while ((*str != end) || (count > 0)) {
489  if (!*str) {
490  fr_strerror_const("String ends before closing brace.");
491  return -1;
492  }
493 
494  if (*str == quote) count++;
495  if (*str == end) count--;
496 
497  str++;
498  }
499 
500  /*
501  * Skip the final "quotation" mark.
502  */
503  str++;
504 
505  /*
506  * [foo bar]baz is invalid.
507  */
508  if ((*str != '\0') &&
509  (*str != ' ') &&
510  (*str != '#') &&
511  (*str != '\t') &&
512  (*str != '\r') &&
513  (*str != '\n')) {
514  fr_strerror_const("Invalid text after quoted string.");
515  return -1;
516  }
517  } else {
518  /*
519  * Skip the next non-space characters.
520  */
521  while (*str &&
522  (*str != ' ') &&
523  (*str != '#') &&
524  (*str != '\t') &&
525  (*str != '\r') &&
526  (*str != '\n'))
527  str++;
528  }
529 
530  /*
531  * One of the above characters is after the word.
532  * Over-write it with NUL. If *str==0, then we leave it
533  * alone, so that the next call to split() discovers it,
534  * and returns NULL.
535  */
536  if (*str) {
537  /*
538  * Skip trailing whitespace so that the caller
539  * can peek at the next argument.
540  */
541  while ((*str == ' ') ||
542  (*str == '\t') ||
543  (*str == '\r') ||
544  (*str == '\n'))
545  *(str++) = '\0';
546  }
547 
548  *input = str;
549  *output = word;
550  return 1;
551 }
552 
553 static int fr_command_add_syntax(TALLOC_CTX *ctx, char *syntax, fr_cmd_argv_t **head, bool allow_varargs)
554 {
555  int i, ret;
556  char *name, *p;
557  fr_cmd_argv_t **last, *prev;
558 
559  p = syntax;
560  *head = NULL;
561  last = head;
562  prev = NULL;
563 
564  for (i = 0; i < CMD_MAX_ARGV; i++) {
565  fr_cmd_argv_t *argv;
566 
567  ret = split(&p, &name, true);
568  if (ret < 0) return ret;
569 
570  if (ret == 0) return i;
571 
572  /*
573  * Check for varargs. Which MUST NOT be
574  * the first argument, and MUST be the
575  * last argument, and MUST be preceded by
576  * a known data type.
577  */
578  if (strcmp(name, "...") == 0) {
579  if (!allow_varargs) {
580  fr_strerror_const("Varargs MUST NOT be in an [...] or (...) syntax.");
581  return -1;
582  }
583 
584  if (!prev || *p) {
585  fr_strerror_const("Varargs MUST be the last argument in the syntax list.");
586  return -1;
587  }
588 
589  /*
590  * The thing BEFORE the varags
591  * MUST be a known data type.
592  */
593  if (prev->type >= FR_TYPE_FIXED) {
594  fr_strerror_const("Varargs MUST be preceded by a data type.");
595  return -1;
596  }
597  argv = talloc_zero(ctx, fr_cmd_argv_t);
598  argv->name = name;
599  argv->type = FR_TYPE_VARARGS;
600  allow_varargs = false;
601 
602  } else if (name[0] == '[') {
603  /*
604  * Optional things. e.g. [foo bar]
605  */
606  char *option = talloc_strdup(ctx, name + 1);
607  char *q;
609 
610  q = option + strlen(option) - 1;
611  if (*q != ']') {
612  fr_strerror_const("Optional syntax is not properly terminated");
613  return -1;
614  }
615 
616  *q = '\0';
617  child = NULL;
618 
619  /*
620  * varargs can't be inside an optional block
621  */
622  ret = fr_command_add_syntax(option, option, &child, false);
623  if (ret < 0) return ret;
624 
625  argv = talloc_zero(ctx, fr_cmd_argv_t);
626  argv->name = name;
627  argv->type = FR_TYPE_OPTIONAL;
628  argv->child = child;
629 
630  } else if (name[0] == '(') {
631  /*
632  * Alternate things. e.g. [foo bar]
633  */
634  char *option = talloc_strdup(ctx, name + 1);
635  char *q, *word;
636  fr_cmd_argv_t *child, **last_child;
637 
638  q = option + strlen(option) - 1;
639  if (*q != ')') {
640  fr_strerror_const("Alternate syntax is not properly terminated");
641  return -1;
642  }
643 
644  *q = '\0';
645  child = NULL;
646  last_child = &child;
647 
648  /*
649  * Walk over the choices, creating
650  * intermediate nodes for each one. Then
651  * placing the actual choices into
652  * child->child.
653  */
654  q = option;
655  while (true) {
656  fr_cmd_argv_t *choice, *sub;
657 
658  ret = split_alternation(&q, &word);
659  if (ret < 0) return ret;
660  if (ret == 0) break;
661 
662  sub = NULL;
663 
664  /*
665  * varargs can't be inside an alternation block
666  */
667  ret = fr_command_add_syntax(option, word, &sub, false);
668  if (ret < 0) return ret;
669 
670  choice = talloc_zero(option, fr_cmd_argv_t);
671  choice->name = word;
672  choice->type = FR_TYPE_ALTERNATE_CHOICE;
673  choice->child = sub;
674 
675  *last_child = choice;
676  last_child = &(choice->next);
677  }
678 
679  argv = talloc_zero(ctx, fr_cmd_argv_t);
680  argv->name = name;
681  argv->type = FR_TYPE_ALTERNATE;
682  argv->child = child;
683 
684  } else {
685  argv = talloc_zero(ctx, fr_cmd_argv_t);
686  argv->name = name;
687 
688  /*
689  * Validates argv->name and sets argv->type
690  */
691  if (!fr_command_valid_syntax(argv)) {
692  talloc_free(argv);
693  return -1;
694  }
695  }
696 
697  *last = argv;
698  last = &(argv->next);
699  prev = argv;
700  }
701 
702  if (*p) {
703  fr_strerror_const("Too many arguments passed in syntax string");
704  return -1;
705  }
706 
707  return i;
708 }
709 
710 /** Add one command to the global command tree
711  *
712  * We do not do any sanity checks on "name". If it has spaces in it,
713  * or "special" characters, that's up to you. We assume that other
714  * things in the server will sanity check them.
715  *
716  * @param talloc_ctx the talloc context
717  * @param head pointer to the head of the command table.
718  * @param name of the command to allocate. Can be NULL for "top level" commands
719  * @param ctx for any callback function
720  * @param table of information about the current command
721  * @return
722  * - <0 on error
723  * - 0 on success
724  */
725 int fr_command_add(TALLOC_CTX *talloc_ctx, fr_cmd_t **head, char const *name, void *ctx, fr_cmd_table_t const *table)
726 {
727  fr_cmd_t *cmd, **start;
728  fr_cmd_t **insert;
729  int argc = 0, depth = 0;
731 
732  /*
733  * This is a place-holder for tab expansion.
734  */
735  if (!table->name) {
736  fr_strerror_const("A name MUST be specified.");
737  return -1;
738  }
739 
740  if (!name && table->add_name) {
741  fr_strerror_const("An additional name must be specified");
742  return -1;
743  }
744 
745  if (name && !fr_command_valid_name(name)) {
746  return -1;
747  }
748 
749  if (!fr_command_valid_name(table->name)) {
750  return -1;
751  }
752 
753  start = head;
754  syntax_argv = NULL;
755 
756  /*
757  * If there are parent commands, ensure that entries for
758  * them exist in the tree. This check allows a table for
759  * "foo" to add "show module foo", even if "show module"
760  * does not yet exist.
761  */
762  if (table->parent) {
763  int i, ret;
764  char *p;
765  char *parents[CMD_MAX_ARGV];
766 
767  p = talloc_strdup(talloc_ctx, table->parent);
768 
769  for (i = 0; i < CMD_MAX_ARGV; i++) {
770  ret = split(&p, &parents[i], true);
771  if (ret < 0) return -1;
772  if (ret == 0) break;
773 
774  if (!fr_command_valid_name(parents[i])) {
775  fr_strerror_printf("Invalid command name '%s'", parents[i]);
776  return -1;
777  }
778 
779  /*
780  * Find the head command. If found,
781  * go downwards into the child command.
782  */
783  cmd = fr_command_find(start, parents[i], &insert);
784  if (!cmd) {
785  cmd = fr_command_alloc(talloc_ctx, insert, parents[i]);
786  cmd->live = true;
787  }
788 
789  if (!cmd->intermediate) {
790  fr_strerror_const("Cannot add a subcommand to a pre-existing command.");
791  return -1;
792  }
793 
794  fr_assert(cmd->func == NULL);
795  start = &(cmd->child);
796  }
797 
798  if (i == CMD_MAX_ARGV) {
799  fr_strerror_printf("Commands are too deep (max is %d)", CMD_MAX_ARGV);
800  return -1;
801  }
802 
803  depth = i;
804  }
805 
806  /*
807  * Add an intermediate name, e.g. "network X"
808  */
809  if (table->add_name) {
810  fr_cmd_t **added_insert;
811 
812  /*
813  * See if we need to create the automatic
814  * place-holder command for help text.
815  */
816  cmd = fr_command_find(start, "STRING", &added_insert);
817  if (!cmd) {
818  cmd = fr_command_alloc(talloc_ctx, added_insert, "STRING");
819  }
820 
821  /*
822  * In the place-holders children, see if we need
823  * to add this subcommand.
824  */
825  cmd = fr_command_find(&(cmd->child), table->name, &added_insert);
826  if (!cmd) {
827  cmd = fr_command_alloc(talloc_ctx, added_insert, table->name);
828 
829  if (table->syntax) cmd->syntax = talloc_strdup(cmd, table->syntax);
830  if (table->help) cmd->help = talloc_strdup(cmd, table->help);
831  }
832 
833  /*
834  * Now insert or add the extended name to the command hierarchy.
835  */
836  cmd = fr_command_find(start, name, &insert);
837  if (!cmd) {
838  cmd = fr_command_alloc(talloc_ctx, insert, name);
839  cmd->added_name = true;
840  cmd->live = true;
841  }
842 
843  start = &(cmd->child);
844  depth++;
845  }
846 
847  /*
848  * @todo - check syntax, too!
849  *
850  * i.e. we have a command "foo" which accepts syntax "bar
851  * baz" we later try to add a command "foo bar" with
852  * syntax "bad". We don't find "bar" in the command
853  * list, because it's buried inside of the syntax for
854  * command "foo". So we can have duplicate / conflicting
855  * commands.
856  *
857  * The simple answer, of course, is "don't do that". The
858  * harder solution is to check for it and error out. But
859  * we're lazy, so too bad.
860  *
861  * The simple solution is to create a command line from
862  * the parents + name + syntax, and then look it up. If
863  * it's found, that's an error.
864  */
865 
866  /*
867  * Sanity check the syntax.
868  */
869  if (table->syntax) {
870  char *syntax = talloc_strdup(talloc_ctx, table->syntax);
871 
873  if (argc < 0) return -1;
874 
875  /*
876  * Empty syntax should have table.syntax == NULL
877  */
878  if (argc == 0) {
880  fr_strerror_const("Invalid empty string was supplied for syntax");
881  return -1;
882  }
883 
884  if ((depth + argc) >= CMD_MAX_ARGV) {
886  fr_strerror_const("Too many arguments were supplied to the command.");
887  return -1;
888  }
889  }
890 
891  /*
892  * "head" is now pointing to the list where we insert
893  * this new command. We now see if the "name" currently
894  * exists.
895  */
896  cmd = fr_command_find(start, table->name, &insert);
897 
898  /*
899  * The command exists already. We can't have TWO
900  * commands of the same name, so it's likely an error.
901  */
902  if (cmd) {
903  /*
904  * Not a callback, but an intermediary node. We
905  * can probably allow it.
906  */
907  if (!table->func) {
908  fr_assert(table->help != NULL);
909 
910  /*
911  * Suppress duplicates.
912  */
913  if (cmd->help == table->help) return 0;
914 
915  if (cmd->help != NULL) {
916  fr_strerror_printf("Cannot change help for command %s",
917  cmd->name);
918  return -1;
919  }
920  fr_assert(cmd->intermediate);
921  cmd->help = table->help;
922  cmd->read_only = table->read_only;
923  return 0;
924  }
925 
926  /*
927  * Can't add new sub-commands to a
928  * command which already has a
929  * pre-defined syntax.
930  */
931  if (!cmd->intermediate) {
932  fr_strerror_printf("Cannot modify a pre-existing command '%s'", cmd->name);
933  return -1;
934  }
935  } else {
936  /*
937  * Allocate cmd and insert it into the current point.
938  */
939  fr_assert(insert != NULL);
940  cmd = fr_command_alloc(talloc_ctx, insert, table->name);
941  }
942 
943  /*
944  * Assume that the commands are loaded from static
945  * structures.
946  *
947  * @todo - add "delete command" for unloading modules?
948  * otherwise after a module is removed, the command
949  * remains, and points to nothing.
950  */
951  cmd->ctx = ctx;
952  cmd->help = table->help;
953  cmd->func = table->func;
954 
955  cmd->intermediate = (cmd->func == NULL);
956 
957  cmd->tab_expand = table->tab_expand;
958  cmd->read_only = table->read_only;
959 
960  if (syntax_argv) {
961  cmd->syntax = table->syntax;
962  cmd->syntax_argv = talloc_steal(cmd, syntax_argv);
963  }
964 
965  cmd->live = true;
966 
967  return 0;
968 }
969 
970 
971 /** Add multiple commands to the global command tree
972  *
973  * e.g. for module "foo", add "show module foo", "set module foo",
974  * etc.
975  *
976  * @param talloc_ctx the talloc context
977  * @param head pointer to the head of the command table.
978  * @param name of the command to allocate
979  * @param ctx for any callback function
980  * @param table array of tables, terminated by "help == NULL"
981  * @return
982  * - <0 on error
983  * - 0 on success
984  */
985 int fr_command_add_multi(TALLOC_CTX *talloc_ctx, fr_cmd_t **head, char const *name, void *ctx, fr_cmd_table_t const *table)
986 {
987  int i;
988 
989  for (i = 0; table[i].help != NULL; i++) {
990  if (fr_command_add(talloc_ctx, head, name, ctx, &table[i]) < 0) return -1;
991  }
992 
993  return 0;
994 }
995 
996 /** A stack for walking commands.
997  *
998  */
999 typedef struct {
1000  int depth;
1001  char const **parents;
1003 } fr_cmd_stack_t;
1004 
1005 
1006 /** Walk over a command hierarchy
1007  *
1008  * @param head the head of the hierarchy. Call it with NULL to clean up `walk_ctx`
1009  * @param[in,out] walk_ctx to track across multiple function calls. MUST point to a `void*` when starting
1010  * @param ctx for the callback
1011  * @param callback to call with fr_walk_info_t about each command
1012  * @return
1013  * - <0 on error
1014  * - 0 for nothing more to do.
1015  * - 1 for "please call me again to get the next command".
1016  * and walk_ctx now points to data allocated by, and managed by this function.
1017  * It MUST be cleaned up via another call to this function.
1018  */
1019 int fr_command_walk(fr_cmd_t *head, void **walk_ctx, void *ctx, fr_cmd_walk_t callback)
1020 {
1021  int ret;
1023  fr_cmd_t *cmd = NULL;
1024  fr_cmd_walk_info_t info;
1025 
1026  if (!walk_ctx || !callback) {
1027  fr_strerror_const("No walk_ctx or callback specified");
1028  return -1;
1029  }
1030 
1031  /*
1032  * Caller can tell us to stop walking by passing a NULL
1033  * "head" pointer after the first call.
1034  */
1035  if (!head) {
1036  if (*walk_ctx) {
1037  stack = *walk_ctx;
1038  done:
1039  talloc_free(stack);
1040  *walk_ctx = NULL;
1041  }
1042 
1043  /*
1044  * If there's no "head", we just go "yeah, it's
1045  * fine..."
1046  */
1047  return 0;
1048  }
1049 
1050  /*
1051  * Allocate a stack the first time we're called. And
1052  * tell the caller to remember it so that we can keep
1053  * walking down the stack.
1054  */
1055  if (!*walk_ctx) {
1056  stack = talloc_zero(NULL, fr_cmd_stack_t);
1057  stack->entry[0] = head;
1058  stack->depth = 0;
1059  *walk_ctx = stack;
1060 
1061  stack->parents = info.parents = talloc_zero_array(stack, char const *, CMD_MAX_ARGV);
1062  } else {
1063  stack = *walk_ctx;
1064  info.parents = stack->parents;
1065  }
1066 
1067  /*
1068  * Grab this entry, which MUST exist.
1069  */
1070  cmd = stack->entry[stack->depth];
1071 
1072  /*
1073  * Fill in the structure.
1074  */
1075  info.num_parents = stack->depth;
1076  info.name = cmd->name;
1077  info.syntax = cmd->syntax;
1078  info.help = cmd->help;
1079 
1080  /*
1081  * Run the callback, but only for user-defined commands.
1082  */
1083  ret = callback(ctx, &info);
1084  if (ret <= 0) {
1085  talloc_free(stack);
1086  *walk_ctx = NULL;
1087  return ret;
1088  }
1089 
1090  /*
1091  * This command has children. Go do those before running
1092  * the next command at the current level.
1093  */
1094  if (cmd->child) {
1095  fr_assert(stack->depth < CMD_MAX_ARGV);
1096  info.parents[stack->depth] = cmd->name;
1097  stack->depth++;
1098  stack->entry[stack->depth] = cmd->child;
1099  return 1;
1100  }
1101 
1102 check_next:
1103  /*
1104  * Go to the next user-defined command at this level,
1105  * skipping any auto-allocated ones.
1106  */
1107  cmd = cmd->next;
1108  if (cmd) {
1109  stack->entry[stack->depth] = cmd;
1110  return 1;
1111  }
1112 
1113  /*
1114  * At the top of the stack, see if we're done.
1115  */
1116  if (stack->depth == 0) {
1117  if (!cmd) goto done;
1118 
1119  fr_assert(0 == 1);
1120  }
1121 
1122  /*
1123  * Done all of the commands at this depth, so we go up a
1124  * level and try to grab another command.
1125  */
1126  stack->depth--;
1127  cmd = stack->entry[stack->depth];
1128  goto check_next;
1129 }
1130 
1131 
1132 /*
1133  * This MAY be a partial match. In which case walk down
1134  * the current list, looking for commands which MAY
1135  * match.
1136  */
1137 static int fr_command_tab_expand_partial(fr_cmd_t *head, char const *partial, int max_expansions, char const **expansions)
1138 {
1139  int i;
1140  size_t len;
1141  fr_cmd_t *cmd;
1142 
1143  len = strlen(partial);
1144 
1145  /*
1146  * We loop over 'cmd', but only increment 'i' if we found a matching command.
1147  */
1148  for (i = 0, cmd = head; (i < max_expansions) && cmd != NULL; cmd = cmd->next) {
1149  if (strncmp(partial, cmd->name, len) != 0) continue;
1150 
1151  expansions[i++] = cmd->name;
1152  }
1153 
1154  return i;
1155 }
1156 
1157 
1158 static int fr_command_tab_expand_argv(TALLOC_CTX *ctx, fr_cmd_t *cmd, fr_cmd_info_t *info, char const *name, fr_cmd_argv_t *argv,
1159  int max_expansions, char const **expansions)
1160 {
1161  char const *p, *q;
1162 
1163  /*
1164  * If it's a real data type, run the defined callback to
1165  * expand it.
1166  */
1167  if (argv->type < FR_TYPE_FIXED) {
1168  if (!cmd->tab_expand) {
1169  expansions[0] = argv->name;
1170  return 1;
1171  }
1172 
1173  return cmd->tab_expand(ctx, cmd->ctx, info, max_expansions, expansions);
1174  }
1175 
1176  /*
1177  * Don't expand "[foo]", instead see if we can expand the
1178  * "foo".
1179  */
1180  if (argv->type == FR_TYPE_OPTIONAL) {
1181  return fr_command_tab_expand_argv(ctx, cmd, info, name, argv->child, max_expansions, expansions);
1182  }
1183 
1184  /*
1185  * Don't expand (foo|bar), instead see if we can expand
1186  * "foo" and "bar".
1187  */
1188  if (argv->type == FR_TYPE_ALTERNATE) {
1189  int count, ret;
1190  fr_cmd_argv_t *child;
1191 
1192  count = 0;
1193  for (child = argv->child; child != NULL; child = child->next) {
1194  if (count >= max_expansions) return count;
1195 
1196  ret = fr_command_tab_expand_argv(ctx, cmd, info, name, child, max_expansions - count, &expansions[count]);
1197  if (!ret) continue;
1198 
1199  count++;
1200  }
1201 
1202  return count;
1203  }
1204 
1205  fr_assert(argv->type == FR_TYPE_FIXED);
1206 
1207  /*
1208  * Not a full match, but we're at the last
1209  * keyword in the list. Maybe it's a partial
1210  * match?
1211  */
1212  for (p = name, q = argv->name;
1213  (*p != '\0') && (*q != '\0');
1214  p++, q++) {
1215  /*
1216  * Mismatch, can't expand.
1217  */
1218  if (*p != *q) return 0;
1219 
1220  /*
1221  * Input is longer than string we're
1222  * trying to match. We can't expand
1223  * that.
1224  */
1225  if (p[1] && !q[1]) return 0;
1226 
1227  /*
1228  * Input is shorter than the string we're
1229  * trying to match. Return the syntax
1230  * string as a suggested expansion.
1231  *
1232  * @todo - return a string which is ALL
1233  * of the fixed strings.
1234  *
1235  * e.g. "foo bar IPADDR". If they enter
1236  * "f<tab>", we should likely return "foo
1237  * bar", instead of just "foo".
1238  */
1239  if (!p[1] && q[1]) {
1240  expansions[0] = argv->name;
1241  return 1;
1242  }
1243  }
1244 
1245  return 0;
1246 }
1247 
1248 /*
1249  * We're at a leaf command, which has a syntax. Walk down the
1250  * syntax argv checking if it matches. If we get a matching
1251  * command, add that to the expansions array and return. If we
1252  * get a data type instead, do the callback to ask the caller to
1253  * expand it.
1254  */
1255 /*
1256  * We're at a leaf command, which has a syntax. Walk down the
1257  * syntax argv checking if it matches. If we get a matching
1258  * command, add that to the expansions array and return. If we
1259  * get a data type instead, do the callback to ask the caller to
1260  * expand it.
1261  */
1262 static int fr_command_tab_expand_syntax(TALLOC_CTX *ctx, fr_cmd_t *cmd, int syntax_offset, fr_cmd_info_t *info,
1263  int max_expansions, char const **expansions)
1264 {
1265  int ret;
1266  fr_cmd_argv_t *argv = cmd->syntax_argv;
1267 
1268  ret = fr_command_verify_argv(info, syntax_offset, info->argc - 1, info->argc - 1, &argv, false);
1269  if (ret < 0) return -1;
1270 
1271  /*
1272  * We've found the last argv. See if we need to expand it.
1273  */
1274  return fr_command_tab_expand_argv(ctx, cmd, info, info->argv[syntax_offset + ret], argv, max_expansions, expansions);
1275 }
1276 
1277 
1278 /** Get the commands && help at a particular level
1279  *
1280  * @param ctx talloc context for dynamically allocated expansions. The caller should free it to free all expansions it created.
1281  * Expansions added by this function are "const char *", and are managed by the command hierarchy.
1282  * @param head the head of the hierarchy.
1283  * @param info the structure describing the command to expand
1284  * @param max_expansions the maximum number of entries in the expansions array
1285  * @param expansions where the expansions will be stored.
1286  * @return
1287  * - <0 on error
1288  * - number of entries in the expansions array
1289  */
1290 int fr_command_tab_expand(TALLOC_CTX *ctx, fr_cmd_t *head, fr_cmd_info_t *info, int max_expansions, char const **expansions)
1291 {
1292  int i;
1293  fr_cmd_t *cmd, *start;
1294 
1295  if (!head) return 0;
1296 
1297  start = head;
1298 
1299  /*
1300  * Walk down the children until we find the correct
1301  * location.
1302  */
1303  for (i = 0; i < info->argc; i++) {
1304  cmd = fr_command_find(&start, info->argv[i], NULL);
1305 
1306  /*
1307  * The command wasn't found in the list. Walk
1308  * over the list AGAIN, doing tab expansions of
1309  * any partial matches.
1310  */
1311  if (!cmd) {
1312  return fr_command_tab_expand_partial(start, info->argv[i], max_expansions, expansions);
1313  }
1314 
1315  if (cmd->intermediate) {
1316  fr_assert(cmd->child != NULL);
1317  start = cmd->child;
1318  continue;
1319  }
1320 
1321  if (!cmd->syntax_argv) {
1322  if ((i + 1) == info->argc) return 0;
1323 
1324  return -1;
1325  }
1326 
1327  if (!cmd->live) return 0;
1328 
1329  /*
1330  * If there is a syntax, the command MUST be a
1331  * leaf node.
1332  *
1333  * Skip the name
1334  */
1335  fr_assert(cmd->func != NULL);
1336  return fr_command_tab_expand_syntax(ctx, cmd, i + 1, info, max_expansions, expansions);
1337  }
1338 
1339  cmd = start;
1340 
1341  /*
1342  * We've looked for "foo bar" and found it. There should
1343  * be child commands under that hierarchy. In which
1344  * case, show them as expansions.
1345  */
1346  fr_assert(i == info->argc);
1347  fr_assert(cmd->child != NULL);
1348 
1349  for (i = 0, cmd = cmd->child; (i < max_expansions) && (cmd != NULL); i++, cmd = cmd->next) {
1350  expansions[i] = cmd->name;
1351  }
1352 
1353  return i;
1354 }
1355 
1356 
1357 /*
1358  * Magic parsing macros
1359  */
1360 #define SKIP_NAME(name) do { p = word; q = name; while (*p && *q && (*p == *q)) { \
1361  p++; \
1362  q++; \
1363  } } while (0)
1364 #define MATCHED_NAME ((!*p || isspace((uint8_t) *p)) && !*q)
1365 #define TOO_FAR (*p && (*q > *p))
1366 #define MATCHED_START ((text + start) >= word) && ((text + start) <= p)
1367 
1368 static int fr_command_run_partial(FILE *fp, FILE *fp_err, fr_cmd_info_t *info, bool read_only, int offset, fr_cmd_t *head)
1369 {
1370  int i, ret;
1371  fr_cmd_t *start, *cmd = NULL;
1372  fr_cmd_info_t my_info;
1373 
1374  fr_assert(head->intermediate);
1375  fr_assert(head->child != NULL);
1376 
1377  start = head->child;
1378 
1379  /*
1380  * Wildcard '*' is at 'offset + 1'. Then the command to run is at 'offset + 2'.
1381  */
1382  fr_assert(info->argc >= (offset + 2));
1383 
1384  /*
1385  * Loop from "start", trying to find a matching command.
1386  */
1387  for (i = offset + 1; i < info->argc; i++) {
1388  char const *p, *q, *word;
1389 
1390  /*
1391  * Re-parse the input because "*" only picked up
1392  * the first command, not the rest of them.
1393  */
1394  for (cmd = start; cmd != NULL; cmd = cmd->next) {
1395  if (!cmd->live) continue;
1396 
1397  word = info->argv[i];
1398  SKIP_NAME(cmd->name);
1399 
1400  if (!MATCHED_NAME) continue;
1401 
1402  if (cmd->intermediate) {
1403  info->cmd[i] = cmd;
1404  start = cmd->child;
1405  break;
1406  }
1407 
1408  /*
1409  * Not an intermediate command, we've got
1410  * to run it.
1411  */
1412  break;
1413  }
1414 
1415  /*
1416  * Not found, die.
1417  */
1418  if (!cmd) return 0;
1419 
1420  /*
1421  * Ignore read-only on intermediate commands.
1422  * Some may have been automatically allocated
1423  */
1424  if (cmd->intermediate) continue;
1425  break;
1426  }
1427 
1428  if (!cmd) return 0;
1429 
1430  if (!cmd->live) return 0;
1431 
1432  if (!cmd->read_only && read_only) {
1433  fprintf(fp_err, "No permissions to run command '%s'\n", cmd->name);
1434  return -1;
1435  }
1436 
1437  /*
1438  * Leaf nodes must have a callback.
1439  */
1440  fr_assert(cmd->func != NULL);
1441 
1442  // @todo - add cmd->min_argc && cmd->max_argc, to track optional things, varargs, etc.
1443 
1444  /*
1445  * The arguments have already been verified by
1446  * fr_command_str_to_argv().
1447  */
1448  my_info.argc = info->argc - i - 1;
1449  my_info.max_argc = info->max_argc - info->argc;
1450  my_info.runnable = true;
1451  my_info.argv = &info->argv[i + 1];
1452  my_info.box = &info->box[i + 1];
1453  ret = cmd->func(fp, fp_err, cmd->ctx, &my_info);
1454 
1455  return ret;
1456 }
1457 
1458 
1459 /** Run a particular command
1460  *
1461  * info->argc is left alone, as are all other fields.
1462  * If you want to run multiple commands, call fr_command_clear(0, info)
1463  * to zero out the relevant information.
1464  *
1465  * @param fp where the output is sent
1466  * @param fp_err where the error output is sent
1467  * @param info the structure describing the command to expand
1468  * @param read_only whether or not this command should be run in read-only mode.
1469  * @return
1470  * - <0 on error
1471  * - 0 the command was run successfully
1472  */
1473 int fr_command_run(FILE *fp, FILE *fp_err, fr_cmd_info_t *info, bool read_only)
1474 {
1475  int i, ret;
1476  fr_cmd_t *cmd;
1477  fr_cmd_info_t my_info;
1478 
1479  cmd = NULL;
1480 
1481  /*
1482  * Asked to do nothing, do nothing.
1483  */
1484  if (info->argc == 0) return 0;
1485 
1486  for (i = 0; i < info->argc; i++) {
1487  cmd = info->cmd[i];
1488  fr_assert(cmd != NULL);
1489 
1490  if (cmd->added_name && (info->argv[i][0] == '*')) {
1491  fr_assert(i > 0);
1492 
1493  for (; cmd != NULL; cmd = cmd->next) {
1494  if (!cmd->live) continue;
1495 
1496  fprintf(fp, "%s %s\n", info->argv[i - 1], cmd->name);
1497  info->argv[i] = cmd->name;
1498  ret = fr_command_run_partial(fp, fp_err, info, read_only, i, cmd);
1499  if (ret < 0) return ret;
1500  }
1501 
1502  return 0;
1503  }
1504 
1505  /*
1506  * Ignore read-only on intermediate commands.
1507  * Some may have been automatically allocated
1508  */
1509  if (cmd->intermediate) continue;
1510  break;
1511  }
1512 
1513  if (!cmd) return 0;
1514 
1515  if (!cmd->live) return 0;
1516 
1517  if (!cmd->read_only && read_only) {
1518  fprintf(fp_err, "No permissions to run command '%s' help %s\n", cmd->name, cmd->help);
1519  return -1;
1520  }
1521 
1522  /*
1523  * Leaf nodes must have a callback.
1524  */
1525  fr_assert(cmd->func != NULL);
1526 
1527  // @todo - add cmd->min_argc && cmd->max_argc, to track optional things, varargs, etc.
1528 
1529  /*
1530  * The arguments have already been verified by
1531  * fr_command_str_to_argv().
1532  */
1533  my_info.argc = info->argc - i - 1;
1534  my_info.max_argc = info->max_argc - info->argc;
1535  my_info.runnable = true;
1536  my_info.argv = &info->argv[i + 1];
1537  my_info.box = &info->box[i + 1];
1538  ret = cmd->func(fp, fp_err, cmd->ctx, &my_info);
1539 
1540  return ret;
1541 }
1542 
1543 
1544 /** Get help text for a particular command.
1545  *
1546  * @param head the head of the hierarchy.
1547  * @param argc the number of arguments in argv
1548  * @param argv the arguments
1549  * @return
1550  * - NULL on "no help text"
1551  * - !NULL is the help text. Do not free or access it.
1552  */
1553 char const *fr_command_help(fr_cmd_t *head, int argc, char *argv[])
1554 {
1555  int i;
1556  fr_cmd_t *cmd, *start;
1557 
1558  start = head;
1559 
1560  for (i = 0; i < argc; i++) {
1561  cmd = fr_command_find(&start, argv[i], NULL);
1562  if (!cmd) return NULL;
1563 
1564  if (cmd->intermediate) {
1565  fr_assert(cmd->child != NULL);
1566  start = cmd->child;
1567  continue;
1568  }
1569 
1570  return cmd->help;
1571  }
1572 
1573  /*
1574  * Return intermediate node help, if that help exists.
1575  */
1576  if (start) return start->help;
1577 
1578  return NULL;
1579 }
1580 
1581 static const char *tabs = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
1582 
1583 static void fr_command_debug_node(FILE *fp, fr_cmd_t *cmd, int depth)
1584 {
1585  fprintf(fp, "%.*s%s\n", depth, tabs, cmd->name);
1586  if (cmd->syntax) fprintf(fp, "%.*s -> %s\n", depth, tabs, cmd->syntax);
1587  if (cmd->help) fprintf(fp, "%.*s ? %s\n", depth, tabs, cmd->help);
1588 }
1589 
1590 static void fr_command_debug_internal(FILE *fp, fr_cmd_t *head, int depth)
1591 {
1592  fr_cmd_t *cmd;
1593 
1594  for (cmd = head; cmd != NULL; cmd = cmd->next) {
1595  fr_command_debug_node(fp, cmd, depth);
1596  if (cmd->child) {
1597  fr_command_debug_internal(fp, cmd->child, depth + 1);
1598  }
1599  }
1600 }
1601 
1603 {
1605 }
1606 
1607 
1608 static void fr_command_list_node(FILE *fp, fr_cmd_t *cmd, int depth, char const **argv, int options)
1609 {
1610  int i;
1611 
1612  for (i = 0; i < depth; i++) {
1613  fprintf(fp, "%s ", argv[i]);
1614  }
1615 
1616  if ((options & FR_COMMAND_OPTION_NAME) != 0) {
1617  fprintf(fp, ":");
1618  }
1619 
1620  if (!cmd->syntax) {
1621  fprintf(fp, "%s\n", cmd->name);
1622  } else {
1623  fprintf(fp, "%s %s\n", cmd->name, cmd->syntax);
1624  }
1625 
1626  if (cmd->help && ((options & FR_COMMAND_OPTION_HELP) != 0)) {
1627  fprintf(fp, "\t%s\n", cmd->help);
1628  }
1629 }
1630 
1631 static void fr_command_list_internal(FILE *fp, fr_cmd_t *head, int depth, int max_depth, char const **argv, int options)
1632 {
1633  fr_cmd_t *cmd;
1634 
1635  for (cmd = head; cmd != NULL; cmd = cmd->next) {
1636  if (cmd->added_name) continue;
1637 
1638  // We DO print out commands are !cmd->live
1639 
1640  if (cmd->child && ((depth + 1) < max_depth)) {
1641  argv[depth] = cmd->name;
1642  fr_command_list_internal(fp, cmd->child, depth + 1, max_depth, argv, options);
1643  } else {
1644  fr_command_list_node(fp, cmd, depth, argv, options);
1645  }
1646  }
1647 }
1648 
1649 void fr_command_list(FILE *fp, int max_depth, fr_cmd_t *head, int options)
1650 {
1651  char const *argv[CMD_MAX_ARGV];
1652 
1653  if ((max_depth <= 0) || !head) return;
1654  if (max_depth > CMD_MAX_ARGV) max_depth = CMD_MAX_ARGV;
1655 
1656  argv[0] = NULL; /* not sure what argv is doing here... */
1657 
1658  if ((options & FR_COMMAND_OPTION_LIST_CHILD) != 0) {
1659  if (!head->child) {
1660  fr_assert(head->func != NULL);
1661  // @todo - skip syntax_argv as necessary
1662  fr_command_list_node(fp, head, 0, argv, options);
1663  return;
1664  }
1665  head = head->child;
1666  }
1667 
1668  fr_command_list_internal(fp, head, 0, max_depth, argv, options);
1669 }
1670 
1671 
1672 static int fr_command_verify_argv(fr_cmd_info_t *info, int start, int verify, int argc, fr_cmd_argv_t **argv_p, bool optional)
1673 {
1674  char quote;
1675  int used = 0, ret;
1676  fr_type_t type;
1677  fr_value_box_t *box, my_box;
1678  char const *name;
1679  fr_cmd_argv_t *argv = *argv_p;
1680  fr_cmd_argv_t *child;
1681  TALLOC_CTX *ctx = NULL;
1682 
1683 redo:
1685 
1686  /*
1687  * Don't eat too many arguments.
1688  */
1689  if ((start + used) >= argc) {
1690  fr_assert(argv != NULL);
1691 
1692  /*
1693  * Skip trailing optional pieces.
1694  */
1695  while (argv && (argv->type == FR_TYPE_OPTIONAL)) {
1696  argv = argv->next;
1697  }
1698 
1699  *argv_p = argv;
1700  return used;
1701  }
1702 
1703  /*
1704  * May be written to for things like
1705  * "combo_ipaddr".
1706  */
1707  type = argv->type;
1708  name = info->argv[start + used];
1709 
1710  /*
1711  * Fixed strings.
1712  *
1713  * Note that for optional parameters, we assume that they
1714  * always begin with fixed strings.
1715  */
1716  if (type == FR_TYPE_FIXED) {
1717  if (strcmp(argv->name, info->argv[start + used]) != 0) {
1718 
1719  /*
1720  * This one didn't match, so we return
1721  * "no match", even if we consumed many
1722  * inputs.
1723  */
1724  if (optional) return 0;
1725 
1726  return -1;
1727  }
1728 
1729  used++;
1730  goto next;
1731  }
1732 
1733  /*
1734  * Optional. It's OK if there's no match.
1735  */
1736  if (type == FR_TYPE_OPTIONAL) {
1737  child = argv->child;
1738 
1739  ret = fr_command_verify_argv(info, start + used, verify, argc, &child, true);
1740  if (ret < 0) return ret;
1741 
1742  /*
1743  * No match, that's OK. Skip it.
1744  */
1745  if (ret == 0) {
1746  goto next;
1747  }
1748 
1749  /*
1750  * We've used SOME of the input.
1751  */
1752  used += ret;
1753 
1754  /*
1755  * But perhaps not all of it. If so, remember
1756  * how much we've used, and return that.
1757  */
1758  if (child) {
1759  *argv_p = argv;
1760  return used;
1761  }
1762 
1763  /*
1764  * If we have used all of the optional thing, keep going.
1765  */
1766  goto next;
1767  }
1768 
1769  /*
1770  * Try the alternates until we find a match.
1771  */
1772  if (type == FR_TYPE_ALTERNATE) {
1773  child = NULL;
1774 
1775  for (child = argv->child; child != NULL; child = child->next) {
1776  fr_cmd_argv_t *sub;
1777 
1779  fr_assert(child->child != NULL);
1780  sub = child->child;
1781 
1782  ret = fr_command_verify_argv(info, start + used, verify, argc, &sub, true);
1783  if (ret <= 0) continue;
1784 
1785  /*
1786  * Only a partial match. Return that.
1787  */
1788  if (sub) {
1789  *argv_p = argv;
1790  return used + ret;
1791  }
1792 
1793  used += ret;
1794  goto next;
1795  }
1796 
1797  /*
1798  * We've gone through all of the alternates
1799  * without a match, that's an error.
1800  */
1801  goto no_match;
1802  }
1803 
1805 
1806  /*
1807  * Don't re-verify things we've already verified.
1808  */
1809  if ((start + used) < verify) {
1810  used++;
1811  goto next;
1812  }
1813 
1814  quote = '\0';
1815  if (type == FR_TYPE_STRING) {
1816  if ((name[0] == '"') ||
1817  (name[0] == '\'')) {
1818  quote = name[0];
1819  }
1820  }
1821 
1822  /*
1823  * Set up and/or cache value boxes
1824  */
1825  if (info->box) {
1826  ctx = info->box;
1827  if (!info->box[start + used]) {
1828  info->box[start + used] = talloc_zero(ctx, fr_value_box_t);
1829  }
1830 
1831  box = info->box[start + used];
1832  } else {
1833  box = &my_box;
1834  }
1835 
1836  /*
1837  * Parse the data to be sure it's well formed.
1838  */
1839  if (fr_value_box_from_str(ctx, box, type,
1840  NULL,
1841  name, strlen(name),
1842  fr_value_unescape_by_char[(uint8_t)quote], true) < 0) {
1843  fr_strerror_printf_push("Failed parsing argument '%s'", name);
1844  return -1;
1845  }
1846 
1847  if (box == &my_box) fr_value_box_clear(box);
1848  used++;
1849 
1850 next:
1851  /*
1852  * Go to the next one, but only if we don't have varargs.
1853  */
1854  if (!argv->next || (argv->next->type != FR_TYPE_VARARGS)) {
1855  argv = argv->next;
1856  }
1857 
1858  if (argv) {
1859  goto redo;
1860  }
1861 
1862  if ((start + used) < argc) {
1863 no_match:
1864  fr_strerror_printf("No match for command %s", info->argv[start + used]);
1865  return -1;
1866  }
1867 
1868  *argv_p = NULL;
1869  return used;
1870 }
1871 
1872 static char const *skip_word(char const *text)
1873 {
1874  char quote;
1875  char const *word = text;
1876 
1877  if ((*word != '"') && (*word != '\'')) {
1878  fr_skip_not_whitespace(word);
1879  return word;
1880  }
1881 
1882  quote = *word;
1883  word++;
1884  while (*word && (*word != quote)) {
1885  if (*word != '\\') {
1886  word++;
1887  continue;
1888  }
1889 
1890  word++;
1891  if (!*word) return NULL;
1892  word++;
1893  }
1894 
1895  return word;
1896 }
1897 
1898 
1899 /** Check the syntax of a command, starting at `*text`
1900  *
1901  * Note that we don't keep a stack of where we are for partial
1902  * commands. So we MUST re-parse the ENTIRE input every time.
1903  */
1904 static int syntax_str_to_argv(int start_argc, fr_cmd_argv_t *start, fr_cmd_info_t *info,
1905  char const **text, bool *runnable)
1906 {
1907  int argc = start_argc;
1908  int ret;
1909  bool child_done;
1910  char const *word, *my_word, *p, *q;
1911  fr_cmd_argv_t *argv = start;
1912  fr_cmd_argv_t *child;
1913 
1914  word = *text;
1915  *runnable = false;
1916 
1917  while (argv) {
1918  fr_skip_whitespace(word);
1919 
1920  if (!*word) goto done;
1921 
1922  /*
1923  * Parse / check data types.
1924  */
1925  if (argv->type < FR_TYPE_FIXED) {
1926  size_t len, offset;
1927  char quote, *str;
1928  fr_type_t type;
1929 
1930  p = skip_word(word);
1931  if (!p) {
1932  fr_strerror_const("Invalid string");
1933  return -1;
1934  }
1935 
1936  /*
1937  * An already-parsed data type. Skip it.
1938  */
1939  if (argc < info->argc) {
1940  fr_assert(info->box[argc] != NULL);
1941  word = p;
1942  argc++;
1943  goto next;
1944  }
1945 
1946  /*
1947  * Non-strings MUST not be quoted.
1948  */
1949  if ((argv->type != FR_TYPE_STRING) &&
1950  ((*word == '"') || (*word == '\''))) {
1951  fr_strerror_printf("Invalid quoted string at %s", word);
1952  return -1;
1953  }
1954 
1955  len = p - word;
1956  if ((*word == '"') || (*word == '\'')) {
1957  quote = *word;
1958  offset = 1;
1959  } else {
1960  quote = 0;
1961  offset = 0;
1962  }
1963 
1964  type = argv->type;
1965  if (!info->box) {
1966  fr_strerror_const("No array defined for values");
1967  return -1;
1968  }
1969 
1970  if (!info->box[argc]) {
1971  info->box[argc] = talloc_zero(info->box, fr_value_box_t);
1972  }
1973 
1974  ret = fr_value_box_from_str(info->box[argc], info->box[argc],
1975  type, NULL,
1976  word + offset, len - (offset << 1),
1977  fr_value_unescape_by_char[(uint8_t)quote], false);
1978  if (ret < 0) return -1;
1979 
1980  /*
1981  * Note that argv[i] is the *input* string.
1982  *
1983  * The called function MUST check box[i]
1984  * for the actual value.
1985  */
1986  info->argv[argc] = str = talloc_memdup(info->argv, word + offset, len + 1);
1987  str[len] = '\0';
1988 
1989  word = p;
1990  argc++;
1991  goto next;
1992  }
1993 
1994  /*
1995  * Fixed strings. We re-validate these for the
1996  * heck of it.
1997  */
1998  if (argv->type == FR_TYPE_FIXED) {
1999  SKIP_NAME(argv->name);
2000 
2001  /*
2002  * End of input text before we matched
2003  * the whole command.
2004  */
2005  if (!*p && *q) {
2006  fr_strerror_printf("Input is too short for command: %s", argv->name);
2007  return -1;
2008  }
2009 
2010  /*
2011  * The only matching exit condition is *p is a
2012  * space, and *q is the NUL character.
2013  */
2014  if (!MATCHED_NAME) {
2015  fr_strerror_printf("Unknown command at: %s", p);
2016  return -1;
2017  }
2018 
2019  /*
2020  * Otherwise keep looking for the next option.
2021  */
2022  info->argv[argc] = argv->name;
2023  info->cmd[argc] = NULL;
2024  // assume that the value box has already been cleared
2025 
2026  word = p;
2027  argc++;
2028  goto next;
2029  }
2030 
2031  /*
2032  * Evaluate alternates in sequence until one
2033  * matches. If none match, that's an error.
2034  */
2035  if (argv->type == FR_TYPE_ALTERNATE) {
2036  my_word = word;
2037 
2038  for (child = argv->child; child != NULL; child = child->next) {
2039  fr_cmd_argv_t *sub;
2040 
2042  fr_assert(child->child != NULL);
2043  sub = child->child;
2044 
2045  /*
2046  * This can fail on things like
2047  * "(INTEGER|IPADDR)" where
2048  * "192.168.0.1" is not a valid
2049  * INTEGER, but it is a valid IPADDR.
2050  */
2051  ret = syntax_str_to_argv(argc, sub, info, &my_word, &child_done);
2052  if (ret <= 0) continue;
2053 
2054  goto skip_child;
2055  }
2056 
2057  /*
2058  * We've gone through all of the alternates
2059  * without a match, that's an error.
2060  */
2061  fr_strerror_printf("No matching command for input string %s", word);
2062  return -1;
2063  }
2064 
2065  /*
2066  * Evaluate an optional argument. If nothing
2067  * matches, that's OK.
2068  */
2069  if (argv->type == FR_TYPE_OPTIONAL) {
2070  child = argv->child;
2071  my_word = word;
2072 
2073  ret = syntax_str_to_argv(argc, child, info, &my_word, &child_done);
2074  if (ret < 0) return ret;
2075 
2076  /*
2077  * Didn't match anything, skip it.
2078  */
2079  if (ret == 0) goto next;
2080 
2081  skip_child:
2082  /*
2083  * We've eaten more input, remember that,
2084  */
2085  argc += ret;
2086  word = my_word;
2087 
2088  /*
2089  * We used only *part* of it. We're done here.
2090  */
2091  if (!child_done) {
2092  word = my_word;
2093  goto done;
2094  }
2095 
2096  goto next;
2097  }
2098 
2099  /*
2100  * Not done yet!
2101  */
2102  fr_strerror_printf("%s: Internal sanity check failed", __FUNCTION__);
2103  return -1;
2104 
2105  next:
2106  /*
2107  * Go to the next one, but only if we don't have varargs.
2108  */
2109  if (!argv->next || (argv->next->type != FR_TYPE_VARARGS)) {
2110  argv = argv->next;
2111  }
2112  }
2113 
2114 done:
2115  /*
2116  * End of input. Skip any trailing optional pieces.
2117  */
2118  if (!*word) {
2119  while (argv && (argv->type == FR_TYPE_OPTIONAL)) argv = argv->next;
2120  }
2121 
2122  if (!argv) *runnable = true;
2123  *text = word;
2124  return (argc - start_argc);
2125 }
2126 
2127 /** Split a string in-place, updating argv[]
2128  *
2129  * This function also respects the various data types (mostly).
2130  * Strings can have quotes. Nothing else can have quotes.
2131  * Non-string data types are skipped and only parsed to data types by
2132  * fr_command_run().
2133  *
2134  * @param head the head of the hierarchy.
2135  * @param info the structure describing the command to expand
2136  * @param text the string to split
2137  * @return
2138  * - <0 on error.
2139  * - total number of arguments in the argv[] array. Always >= argc.
2140  */
2141 int fr_command_str_to_argv(fr_cmd_t *head, fr_cmd_info_t *info, char const *text)
2142 {
2143  int argc, ret;
2144  char const *word, *p, *q;
2145  fr_cmd_t *cmd;
2146 
2147  if ((info->argc < 0) || (info->max_argc <= 0)) {
2148  fr_strerror_const("argc / max_argc must be greater than zero");
2149  return -1;
2150  }
2151 
2152  if (!text) {
2153  fr_strerror_const("No string to split.");
2154  return -1;
2155  }
2156 
2157  /*
2158  * Must have something to check.
2159  */
2160  if (!head) {
2161  fr_strerror_const("No commands to parse.");
2162  return -1;
2163  }
2164 
2165  info->runnable = false;
2166  cmd = head;
2167  word = text;
2168 
2169  /*
2170  * Double-check the commands we may have already parsed.
2171  */
2172  for (argc = 0; argc < info->argc; argc++) {
2173  cmd = info->cmd[argc];
2174  fr_assert(cmd != NULL);
2175 
2176  fr_skip_whitespace(word);
2177 
2178  if ((word[0] == '*') && isspace(word[1]) && cmd->added_name) {
2179  p = word + 1;
2180  goto skip_matched;
2181  }
2182 
2183  SKIP_NAME(cmd->name);
2184 
2185  /*
2186  * The only matching exit condition is *p is a
2187  * space, and *q is the NUL character.
2188  */
2189  if (!MATCHED_NAME) {
2190  goto invalid;
2191  }
2192 
2193 skip_matched:
2194  word = p;
2195 
2196  if (!cmd->intermediate) {
2197  argc++;
2198  goto check_syntax;
2199  }
2200  }
2201 
2202  /*
2203  * If we've found a cached command, go parse it's
2204  * children.
2205  */
2206  if ((argc > 0) && cmd->intermediate) {
2207  cmd = cmd->child;
2208  }
2209 
2210  /*
2211  * Search the remaining text for matching commands.
2212  */
2213  while (cmd) {
2214  fr_skip_whitespace(word);
2215 
2216  /*
2217  * Skip commands which we shouldn't know about...
2218  */
2219  if (!cmd->live) {
2220  cmd = cmd->next;
2221  continue;
2222  }
2223 
2224  /*
2225  * End of the input. Tab expand everything here.
2226  */
2227  if (!*word) {
2228  info->argc = argc;
2229  return argc;
2230  }
2231 
2232  /*
2233  * Double-check using the cached cmd.
2234  */
2235  if (argc < info->argc) {
2236  cmd = info->cmd[argc];
2237  if (!cmd) {
2238  fr_strerror_printf("No cmd at offset %d", argc);
2239  goto invalid;
2240  }
2241  }
2242 
2243  /*
2244  * Allow wildcards as a primitive "for" loop in
2245  * some special circumstances.
2246  */
2247  if ((word[0] == '*') && isspace(word[1]) && cmd->added_name) {
2248  fr_assert(cmd->intermediate);
2249  fr_assert(cmd->child != NULL);
2250 
2251  info->argv[argc] = "*";
2252  info->cmd[argc] = cmd;
2253  word++;
2254  cmd = cmd->child;
2255  argc++;
2256  continue;
2257  }
2258 
2259  SKIP_NAME(cmd->name);
2260 
2261  /*
2262  * The only matching exit condition is *p is a
2263  * space, and *q is the NUL character.
2264  */
2265  if (!MATCHED_NAME) {
2266  if (argc < info->argc) {
2267  invalid:
2268  fr_strerror_const("Invalid internal state");
2269  return -1;
2270  }
2271 
2272  /*
2273  * We're looking for "abc" and we found
2274  * "def". We know that "abc" can't occur
2275  * any more, so stop.
2276  */
2277  if (TOO_FAR) {
2278  cmd = NULL;
2279  break;
2280  }
2281 
2282  /*
2283  * Otherwise keep searching for it.
2284  */
2285  cmd = cmd->next;
2286  continue;
2287  }
2288 
2289  if (cmd->intermediate) {
2290  fr_assert(cmd->child != NULL);
2291  info->argv[argc] = cmd->name;
2292  info->cmd[argc] = cmd;
2293  word = p;
2294  cmd = cmd->child;
2295  argc++;
2296  continue;
2297  }
2298 
2299  /*
2300  * Skip the command name we matched.
2301  */
2302  word = p;
2303  info->argv[argc] = cmd->name;
2304  info->cmd[argc] = cmd;
2305  argc++;
2306  break;
2307  }
2308 
2309  if (argc == info->max_argc) {
2310  too_many:
2311  fr_strerror_const("Too many arguments for command.");
2312  return -1;
2313  }
2314 
2315  /*
2316  * We've walked off of the end of the list without
2317  * finding anything.
2318  */
2319  if (!cmd) {
2320  fr_strerror_printf("No such command: %s", word);
2321  return -1;
2322  }
2323 
2324  fr_assert(cmd->func != NULL);
2325  fr_assert(cmd->child == NULL);
2326 
2327 check_syntax:
2328  /*
2329  * The command doesn't take any arguments. Error out if
2330  * there are any. Otherwise, return that the command is
2331  * runnable.
2332  */
2333  if (!cmd->syntax_argv) {
2334  fr_skip_whitespace(word);
2335 
2336  if (*word > 0) goto too_many;
2337 
2338  info->runnable = true;
2339  info->argc = argc;
2340  return argc;
2341  }
2342 
2343  /*
2344  * Do recursive checks on the input string.
2345  */
2346  ret = syntax_str_to_argv(argc, cmd->syntax_argv, info, &word, &info->runnable);
2347  if (ret < 0) return ret;
2348 
2349  argc += ret;
2350 
2351  /*
2352  * Run out of options to parse, but there's still more
2353  * input.
2354  */
2355  if (!info->runnable && *word) {
2356  fr_skip_whitespace(word);
2357  if (*word) goto too_many;
2358  }
2359 
2360  info->argc = argc;
2361  return argc;
2362 }
2363 
2364 /** Clear out any value boxes etc.
2365  *
2366  * @param new_argc the argc to set inside of info
2367  * @param info the information with the current argc
2368  */
2369 int fr_command_clear(int new_argc, fr_cmd_info_t *info)
2370 {
2371  int i;
2372 
2373  if ((new_argc < 0) || (new_argc >= CMD_MAX_ARGV) ||
2374  (new_argc > info->argc)) {
2375  fr_strerror_const("Invalid argument");
2376  return -1;
2377  }
2378 
2379  if (new_argc == info->argc) return 0;
2380 
2381  for (i = new_argc; i < info->argc; i++) {
2382  if (info->box && info->box[i]) {
2383  fr_value_box_clear(info->box[i]);
2384  talloc_const_free(info->argv[i]);
2385  }
2386  if (info->cmd && info->cmd[i]) info->cmd[i] = NULL;
2387  info->argv[i] = NULL;
2388  }
2389 
2390  info->argc = new_argc;
2391  return 0;
2392 }
2393 
2394 /** Initialize an fr_cmd_info_t structure.
2395  *
2396  */
2397 void fr_command_info_init(TALLOC_CTX *ctx, fr_cmd_info_t *info)
2398 {
2399  memset(info, 0, sizeof(*info));
2400 
2401  info->argc = 0;
2402  info->max_argc = CMD_MAX_ARGV;
2403  MEM(info->argv = talloc_zero_array(ctx, char const *, CMD_MAX_ARGV));
2404  MEM(info->box = talloc_zero_array(ctx, fr_value_box_t *, CMD_MAX_ARGV));
2405  MEM(info->cmd = talloc_zero_array(ctx, fr_cmd_t *, CMD_MAX_ARGV));
2406 }
2407 
2408 
2409 static int expand_all(fr_cmd_t *cmd, fr_cmd_info_t *info, fr_cmd_argv_t *argv, int count, int max_expansions, char const **expansions)
2410 {
2411  fr_cmd_argv_t *child;
2412 
2413  if (count >= max_expansions) return count;
2414 
2415  if (argv->type == FR_TYPE_ALTERNATE) {
2416  child = NULL;
2417 
2418  for (child = argv->child; child != NULL; child = child->next) {
2419  fr_cmd_argv_t *sub;
2420 
2422  fr_assert(child->child != NULL);
2423  sub = child->child;
2424 
2425  count = expand_all(cmd, info, sub, count, max_expansions, expansions);
2426  }
2427 
2428  return count;
2429  }
2430 
2431  if (argv->type == FR_TYPE_ALTERNATE) {
2432  for (child = argv->child; child != NULL; child = child->next) {
2433  fr_cmd_argv_t *sub;
2434 
2436  fr_assert(child->child != NULL);
2437  sub = child->child;
2438 
2439  count = expand_all(cmd, info, sub, count, max_expansions, expansions);
2440  }
2441 
2442  return count;
2443  }
2444 
2445  /*
2446  * @todo - might want to do something smarter here?
2447  */
2448  if (argv->type == FR_TYPE_OPTIONAL) {
2449  return expand_all(cmd, info, argv->child, count, max_expansions, expansions);
2450  }
2451 
2452  if ((argv->type < FR_TYPE_FIXED) && cmd->tab_expand) {
2453  int ret;
2454 
2455  info->argv[info->argc] = "";
2456  info->box[info->argc] = NULL;
2457  info->argc++;
2458 
2459  fr_assert(count == 0);
2460  ret = cmd->tab_expand(NULL, cmd->ctx, info, max_expansions - count, expansions + count);
2461  if (ret < 0) return ret;
2462 
2463  return count + ret;
2464  }
2465 
2466  expansions[count] = strdup(argv->name);
2467  return count + 1;
2468 }
2469 
2470 static int expand_syntax(fr_cmd_t *cmd, fr_cmd_info_t *info, fr_cmd_argv_t *argv, char const *text, int start,
2471  char const **word_p, int count, int max_expansions, char const **expansions)
2472 {
2473  char const *p, *q;
2474  char const *word = *word_p;
2475 
2476  /*
2477  * Loop over syntax_argv, looking for matches.
2478  */
2479  for (/* nothing */ ; argv != NULL; argv = argv->next) {
2480  fr_skip_whitespace(word);
2481 
2482  if (!*word) {
2483  return expand_all(cmd, info, argv, count, max_expansions, expansions);
2484  }
2485 
2486  if (argv->type == FR_TYPE_VARARGS) return count;
2487 
2488  if (count >= max_expansions) return count;
2489 
2490  /*
2491  * Optional gets expanded, too.
2492  */
2493  if (argv->type == FR_TYPE_OPTIONAL) {
2494  char const *my_word;
2495 
2496  my_word = word;
2497 
2498  count = expand_syntax(cmd, info, argv->child, text, start, &my_word, count, max_expansions, expansions);
2499 
2500  if (word != my_word) *word_p = word;
2501  continue;
2502  }
2503 
2504  if (argv->type == FR_TYPE_ALTERNATE) {
2505  fr_cmd_argv_t *child;
2506 
2507  for (child = argv->child; child != NULL; child = child->next) {
2508  fr_cmd_argv_t *sub;
2509  char const *my_word = word;
2510 
2512  fr_assert(child->child != NULL);
2513  sub = child->child;
2514 
2515  /*
2516  * See if the child eats any of
2517  * the input. If so, use it.
2518  */
2519  count = expand_syntax(cmd, info, sub, text, start, &my_word, count, max_expansions, expansions);
2520  if (my_word != word) {
2521  *word_p = word;
2522  break;
2523  }
2524  }
2525 
2526  continue;
2527  }
2528 
2529  /*
2530  * Check data types.
2531  */
2532  if (argv->type < FR_TYPE_FIXED) {
2533  int ret;
2534  size_t len, offset;
2535  char quote, *my_word;
2536  fr_type_t type = argv->type;
2537 
2538  p = skip_word(word);
2539 
2540  if (!p) return count;
2541 
2542  if (MATCHED_START) {
2543  if (!cmd->tab_expand) {
2544  /*
2545  * Partial word on input.
2546  * Tell the caller the
2547  * full name.
2548  */
2549  if (!*p || (isspace((uint8_t) *p))) {
2550  expand_name:
2551  expansions[count] = strdup(argv->name);
2552  count++;
2553  }
2554 
2555  return count;
2556  }
2557 
2558  /*
2559  * Give the function the partial
2560  * text which should be expanded.
2561  */
2562  info->argv[info->argc] = word;
2563  info->box[info->argc] = NULL;
2564  info->argc++;
2565 
2566  /*
2567  * Expand this thing.
2568  */
2569  fr_assert(count == 0);
2570  ret = cmd->tab_expand(NULL, cmd->ctx, info, max_expansions - count, expansions + count);
2571  if (ret < 0) return ret;
2572  return count + ret;
2573  }
2574 
2575  len = p - word;
2576 
2577  info->argv[info->argc] = my_word = talloc_zero_array(info->argv, char, len + 1);
2578  memcpy(my_word, word, len);
2579  my_word[len] = '\0';
2580 
2581  if (!info->box[info->argc]) {
2582  info->box[info->argc] = talloc_zero(info->box, fr_value_box_t);
2583  }
2584 
2585  if ((*word == '"') || (*word == '\'')) {
2586  quote = *word;
2587  offset = 1;
2588  } else {
2589  quote = 0;
2590  offset = 0;
2591  }
2592 
2593  ret = fr_value_box_from_str(info->box[info->argc], info->box[info->argc],
2594  type, NULL,
2595  word + offset, len - (offset << 1),
2596  fr_value_unescape_by_char[(uint8_t)quote], false);
2597  if (ret < 0) return -1;
2598  info->argc++;
2599  *word_p = word = p;
2600  continue;
2601  }
2602 
2603  /*
2604  * This should be the only remaining data type.
2605  */
2606  fr_assert(argv->type == FR_TYPE_FIXED);
2607 
2608  SKIP_NAME(argv->name);
2609 
2610  /*
2611  * The only matching exit condition is *p is a
2612  * space, and *q is the NUL character.
2613  */
2614  if (MATCHED_NAME) {
2615  *word_p = word = p;
2616  info->argv[info->argc] = word;
2617  info->box[info->argc] = NULL;
2618  info->argc++;
2619  continue;
2620  }
2621 
2622  /*
2623  * Ran off of the end of the input before
2624  * matching all of the name. The input is a
2625  * PARTIAL match. Go fill it in.
2626  */
2627  if (!*p || isspace((uint8_t) *p)) {
2628  goto expand_name;
2629  }
2630 
2631  /*
2632  * No match, stop here.
2633  */
2634  break;
2635  }
2636 
2637  /*
2638  * Ran out of words to match.
2639  */
2640  *word_p = word;
2641  return count;
2642 }
2643 
2644 
2645 /** Do readline-style command completions
2646  *
2647  * Most useful as part of readline tab expansions. The expansions
2648  * are strdup() strings, and MUST be free'd by the caller.
2649  *
2650  * @param head of the command tree
2651  * @param text the text to check
2652  * @param start offset in the text where the completions should start
2653  * @param max_expansions how many entries in the "expansions" array.
2654  * @param[in,out] expansions where the expansions are stored.
2655  * @return
2656  * - <0 on error
2657  * - >= 0 number of expansions in the array
2658  */
2659 int fr_command_complete(fr_cmd_t *head, char const *text, int start,
2660  int max_expansions, char const **expansions)
2661 {
2662  char const *word, *p, *q;
2663  fr_cmd_t *cmd;
2664  int count;
2665  fr_cmd_info_t *info;
2666 
2667  cmd = head;
2668  word = text;
2669  count = 0;
2670 
2671  info = talloc_zero(head, fr_cmd_info_t);
2672  fr_command_info_init(head, info);
2673 
2674  /*
2675  * Try to do this without mangling "text".
2676  */
2677  while (cmd) {
2678  fr_skip_whitespace(word);
2679 
2680  /*
2681  * Skip commands which we shouldn't know about...
2682  */
2683  if (!cmd->live) {
2684  cmd = cmd->next;
2685  continue;
2686  }
2687 
2688  /*
2689  * End of the input. Tab expand everything here.
2690  */
2691  if (!*word) {
2692  expand:
2693  while (cmd && (count < max_expansions)) {
2694  if (!cmd->live) goto next;
2695 
2696  SKIP_NAME(cmd->name);
2697 
2698  /*
2699  * Matched all of the input to
2700  * part of cmd->name.
2701  */
2702  if (!*p || isspace((uint8_t) *p)) {
2703  expansions[count] = strdup(cmd->name);
2704  count++;
2705  }
2706 
2707  next:
2708  cmd = cmd->next;
2709  }
2710 
2711  talloc_free(info);
2712  return count;
2713  }
2714 
2715  SKIP_NAME(cmd->name);
2716 
2717  /*
2718  * We're supposed to expand the text at this
2719  * location, go do so. Even if it doesn't match.
2720  */
2721  if (MATCHED_START) {
2722  goto expand;
2723  }
2724 
2725  /*
2726  * We've run off of the end of the input, and
2727  * found a partially matching command. Return
2728  * all of the commands which match this
2729  * expansion.
2730  */
2731  if (!*p && *q) {
2732  goto expand;
2733  }
2734 
2735  /*
2736  * The only matching exit condition is *p is a
2737  * space, and *q is the NUL character.
2738  */
2739  if (!MATCHED_NAME) {
2740  if (TOO_FAR) return count;
2741 
2742  cmd = cmd->next;
2743  continue;
2744  }
2745 
2746  if (cmd->intermediate) {
2747  fr_assert(cmd->child != NULL);
2748  word = p;
2749  cmd = cmd->child;
2750 
2751  info->argv[info->argc] = cmd->name;
2752  info->argc++;
2753  continue;
2754  }
2755 
2756  /*
2757  * Skip the command name we matched.
2758  */
2759  word = p;
2760  break;
2761  }
2762 
2763  /*
2764  * No match, can't do anything.
2765  */
2766  if (!cmd) {
2767  talloc_free(info);
2768  return count;
2769  }
2770 
2771  /*
2772  * No syntax, can't do anything.
2773  */
2774  if (!cmd->syntax_argv) {
2775  talloc_free(info);
2776  return count;
2777  }
2778 
2779  count = expand_syntax(cmd, info, cmd->syntax_argv, text, start, &word, count, max_expansions, expansions);
2780  fr_command_clear(0, info);
2781  talloc_free(info);
2782  return count;
2783 }
2784 
2785 static void print_help(FILE *fp, fr_cmd_t *cmd)
2786 {
2787  if (!cmd->help) {
2788  fprintf(fp, "%s\n", cmd->name);
2789  } else {
2790  fprintf(fp, "%-30s%s\n", cmd->name, cmd->help);
2791  }
2792 }
2793 
2794 /** Do readline-style help completions
2795  *
2796  * Most useful as part of readline.
2797  *
2798  * @param fp where the help is printed
2799  * @param head of the command tree
2800  * @param text the text to check
2801  */
2802 int fr_command_print_help(FILE *fp, fr_cmd_t *head, char const *text)
2803 {
2804  char const *word, *p, *q;
2805  fr_cmd_t *cmd;
2806 
2807  cmd = head;
2808  word = text;
2809 
2810  /*
2811  * Try to do this without mangling "text".
2812  */
2813  while (cmd) {
2814  fr_skip_whitespace(word);
2815 
2816  /*
2817  * End of the input. Tab expand everything here.
2818  */
2819  if (!*word) {
2820  while (cmd) {
2821  print_help(fp, cmd);
2822  cmd = cmd->next;
2823  }
2824  return 0;
2825  }
2826 
2827  /*
2828  * Try to find a matching cmd->name
2829  */
2830  SKIP_NAME(cmd->name);
2831 
2832  /*
2833  * Matched part of the name. Print out help for this one.
2834  */
2835  if (!*p && *q) {
2836  print_help(fp, cmd);
2837  }
2838 
2839  /*
2840  * The only matching exit condition is *p is a
2841  * space, and *q is the NUL character.
2842  */
2843  if (!MATCHED_NAME) {
2844  if (TOO_FAR) return 0;
2845 
2846  cmd = cmd->next;
2847  continue;
2848  }
2849 
2850  /*
2851  * Done the input, but not the commands.
2852  */
2853  if (!*p) {
2854  /*
2855  * If we've ALSO matched this complete
2856  * command, AND it has children, then
2857  * print help about the children.
2858  */
2859  if (!*q && cmd->intermediate) goto intermediate;
2860  break;
2861  }
2862 
2863  if (cmd->intermediate) {
2864  intermediate:
2865  fr_assert(cmd->child != NULL);
2866  word = p;
2867  cmd = cmd->child;
2868  continue;
2869  }
2870 
2871  /*
2872  * Skip the command name we matched.
2873  */
2874  break;
2875  }
2876 
2877  /*
2878  * No match, can't do anything.
2879  */
2880  if (!cmd) {
2881  return 0;
2882  }
2883 
2884  /*
2885  * For one command, try to print out the syntax, as it's
2886  * generally more useful than the help.
2887  */
2888  if (!cmd->syntax) {
2889  print_help(fp, cmd);
2890  } else {
2891  fprintf(fp, "%-30s%s\n", cmd->name, cmd->syntax);
2892  }
2893 
2894  return 0;
2895 }
2896 
2897 /* See if partial string matches a full string.
2898  *
2899  * @param word the partial word to match
2900  * @param name the name which "word" might match
2901  * @return
2902  * - false if they do not match
2903  * - true if "word" is a prefix of "name"
2904  *
2905  */
2906 bool fr_command_strncmp(const char *word, const char *name)
2907 {
2908  char const *p, *q;
2909 
2910  if (!*word) return true;
2911 
2912  SKIP_NAME(name);
2913 
2914  /*
2915  * If we're done P (partial or full), that's a match.
2916  */
2917  return (*p == '\0');
2918 }
#define CMD_MAX_ARGV
Definition: radmin.c:150
#define RCSID(id)
Definition: build.h:481
#define UNUSED
Definition: build.h:313
static int split_alternation(char **input, char **output)
Definition: command.c:268
bool read_only
Definition: command.c:67
#define MATCHED_NAME
Definition: command.c:1364
int fr_command_clear(int new_argc, fr_cmd_info_t *info)
Clear out any value boxes etc.
Definition: command.c:2369
static int expand_all(fr_cmd_t *cmd, fr_cmd_info_t *info, fr_cmd_argv_t *argv, int count, int max_expansions, char const **expansions)
Definition: command.c:2409
void fr_command_list(FILE *fp, int max_depth, fr_cmd_t *head, int options)
Definition: command.c:1649
void * ctx
Definition: command.c:63
int fr_command_walk(fr_cmd_t *head, void **walk_ctx, void *ctx, fr_cmd_walk_t callback)
Walk over a command hierarchy.
Definition: command.c:1019
char const * name
Definition: command.c:46
bool added_name
was this name added?
Definition: command.c:70
int fr_command_str_to_argv(fr_cmd_t *head, fr_cmd_info_t *info, char const *text)
Split a string in-place, updating argv[].
Definition: command.c:2141
int fr_command_run(FILE *fp, FILE *fp_err, fr_cmd_info_t *info, bool read_only)
Run a particular command.
Definition: command.c:1473
static int syntax_str_to_argv(int start_argc, fr_cmd_argv_t *start, fr_cmd_info_t *info, char const **text, bool *runnable)
Check the syntax of a command, starting at *text
Definition: command.c:1904
static int fr_command_add_syntax(TALLOC_CTX *ctx, char *syntax, fr_cmd_argv_t **head, bool allow_varargs)
Definition: command.c:553
static void fr_command_list_node(FILE *fp, fr_cmd_t *cmd, int depth, char const **argv, int options)
Definition: command.c:1608
struct fr_cmd_s * child
if there are subcommands
Definition: command.c:56
void fr_command_info_init(TALLOC_CTX *ctx, fr_cmd_info_t *info)
Initialize an fr_cmd_info_t structure.
Definition: command.c:2397
static fr_cmd_t * fr_command_find(fr_cmd_t **head, char const *name, fr_cmd_t ***insert)
Find a command.
Definition: command.c:100
fr_cmd_func_t func
Definition: command.c:64
fr_cmd_argv_t * syntax_argv
arguments and types
Definition: command.c:61
static void fr_command_debug_node(FILE *fp, fr_cmd_t *cmd, int depth)
Definition: command.c:1583
int fr_command_print_help(FILE *fp, fr_cmd_t *head, char const *text)
Do readline-style help completions.
Definition: command.c:2802
fr_command_register_hook_t fr_command_register_hook
Definition: command.c:42
void fr_command_debug(FILE *fp, fr_cmd_t *head)
Definition: command.c:1602
char const ** parents
Definition: command.c:1001
static void fr_command_list_internal(FILE *fp, fr_cmd_t *head, int depth, int max_depth, char const **argv, int options)
Definition: command.c:1631
static char const * skip_word(char const *text)
Definition: command.c:1872
#define FR_TYPE_OPTIONAL
Definition: command.c:87
int fr_command_complete(fr_cmd_t *head, char const *text, int start, int max_expansions, char const **expansions)
Do readline-style command completions.
Definition: command.c:2659
static void fr_command_debug_internal(FILE *fp, fr_cmd_t *head, int depth)
Definition: command.c:1590
static int fr_command_register(UNUSED TALLOC_CTX *talloc_ctx, UNUSED char const *name, UNUSED void *ctx, UNUSED fr_cmd_table_t *table)
Definition: command.c:37
static int fr_command_tab_expand_partial(fr_cmd_t *head, char const *partial, int max_expansions, char const **expansions)
Definition: command.c:1137
struct fr_cmd_s * next
Definition: command.c:55
char const * name
Definition: command.c:53
static int fr_command_verify_argv(fr_cmd_info_t *info, int start, int verify, int argc, fr_cmd_argv_t **argv_p, bool optional)
Definition: command.c:1672
static int fr_command_run_partial(FILE *fp, FILE *fp_err, fr_cmd_info_t *info, bool read_only, int offset, fr_cmd_t *head)
Definition: command.c:1368
bool fr_command_strncmp(const char *word, const char *name)
Definition: command.c:2906
#define FR_TYPE_FIXED
Definition: command.c:84
#define FR_TYPE_ALTERNATE
Definition: command.c:88
int fr_command_add(TALLOC_CTX *talloc_ctx, fr_cmd_t **head, char const *name, void *ctx, fr_cmd_table_t const *table)
Add one command to the global command tree.
Definition: command.c:725
int fr_command_add_multi(TALLOC_CTX *talloc_ctx, fr_cmd_t **head, char const *name, void *ctx, fr_cmd_table_t const *table)
Add multiple commands to the global command tree.
Definition: command.c:985
static const char * tabs
Definition: command.c:1581
char const * fr_command_help(fr_cmd_t *head, int argc, char *argv[])
Get help text for a particular command.
Definition: command.c:1553
#define TOO_FAR
Definition: command.c:1365
bool intermediate
intermediate commands can't have callbacks
Definition: command.c:68
#define MATCHED_START
Definition: command.c:1366
#define SKIP_NAME(name)
Definition: command.c:1360
#define FR_TYPE_ALTERNATE_CHOICE
Definition: command.c:89
static bool fr_command_valid_syntax(fr_cmd_argv_t *argv)
Definition: command.c:204
fr_type_t type
Definition: command.c:47
static int expand_syntax(fr_cmd_t *cmd, fr_cmd_info_t *info, fr_cmd_argv_t *argv, char const *text, int start, char const **word_p, int count, int max_expansions, char const **expansions)
Definition: command.c:2470
char const * syntax
only for terminal nodes
Definition: command.c:58
bool live
is this entry live?
Definition: command.c:69
static int split(char **input, char **output, bool syntax_string)
Definition: command.c:385
#define FR_TYPE_VARARGS
Definition: command.c:86
char const * help
Definition: command.c:59
int fr_command_tab_expand(TALLOC_CTX *ctx, fr_cmd_t *head, fr_cmd_info_t *info, int max_expansions, char const **expansions)
Get the commands && help at a particular level.
Definition: command.c:1290
fr_cmd_tab_t tab_expand
Definition: command.c:65
static bool fr_command_valid_name(char const *name)
Definition: command.c:174
static fr_cmd_t * fr_command_alloc(TALLOC_CTX *ctx, fr_cmd_t **head, char const *name)
Allocate an fr_cmd_t structure.
Definition: command.c:150
fr_cmd_argv_t * next
Definition: command.c:48
static int fr_command_tab_expand_syntax(TALLOC_CTX *ctx, fr_cmd_t *cmd, int syntax_offset, fr_cmd_info_t *info, int max_expansions, char const **expansions)
Definition: command.c:1262
static void print_help(FILE *fp, fr_cmd_t *cmd)
Definition: command.c:2785
fr_cmd_argv_t * child
Definition: command.c:49
static int fr_command_tab_expand_argv(TALLOC_CTX *ctx, fr_cmd_t *cmd, fr_cmd_info_t *info, char const *name, fr_cmd_argv_t *argv, int max_expansions, char const **expansions)
Definition: command.c:1158
A stack for walking commands.
Definition: command.c:999
int(* fr_cmd_walk_t)(void *ctx, fr_cmd_walk_info_t *)
Definition: command.h:72
char const ** parents
Definition: command.h:66
bool add_name
do we add a name here?
Definition: command.h:59
char const * help
help text
Definition: command.h:55
int argc
current argument count
Definition: command.h:39
int(* fr_cmd_func_t)(FILE *fp, FILE *fp_err, void *ctx, fr_cmd_info_t const *info)
Definition: command.h:47
fr_cmd_func_t func
function to process this command
Definition: command.h:56
char const * syntax
Definition: command.h:68
char const * syntax
e.g. "STRING"
Definition: command.h:54
fr_value_box_t ** box
value_box version of commands.
Definition: command.h:43
bool read_only
Definition: command.h:58
char const * parent
e.g. "show module"
Definition: command.h:52
#define FR_COMMAND_OPTION_NAME
Definition: command.h:89
#define FR_COMMAND_OPTION_LIST_CHILD
Definition: command.h:88
fr_cmd_tab_t tab_expand
tab expand things in the syntax string
Definition: command.h:57
bool runnable
is the command runnable?
Definition: command.h:41
int(* fr_command_register_hook_t)(TALLOC_CTX *talloc_ctx, char const *name, void *ctx, fr_cmd_table_t *table)
Definition: command.h:73
#define FR_COMMAND_OPTION_HELP
Definition: command.h:90
int max_argc
maximum number of arguments
Definition: command.h:40
char const * name
e.g. "stats"
Definition: command.h:53
char const * help
Definition: command.h:69
char const ** argv
text version of commands
Definition: command.h:42
int(* fr_cmd_tab_t)(TALLOC_CTX *talloc_ctx, void *ctx, fr_cmd_info_t *info, int max_expansions, char const **expansions)
Definition: command.h:49
char const * name
Definition: command.h:67
fr_cmd_t ** cmd
cached commands at each offset
Definition: command.h:44
next
Definition: dcursor.h:178
talloc_free(reap)
static char * stack[MAX_STACK]
Definition: radmin.c:158
fr_type_t
Definition: merged_model.c:80
@ FR_TYPE_STRING
String of printable characters.
Definition: merged_model.c:83
@ FR_TYPE_MAX
Number of defined data types.
Definition: merged_model.c:130
@ FR_TYPE_NULL
Invalid (uninitialised) attribute type.
Definition: merged_model.c:81
@ FR_TYPE_VALUE_BOX
A boxed value.
Definition: merged_model.c:125
@ FR_TYPE_VOID
User data.
Definition: merged_model.c:127
unsigned char uint8_t
Definition: merged_model.c:30
static size_t used
static uint8_t depth(fr_minmax_heap_index_t i)
Definition: minmax_heap.c:83
#define fr_skip_not_whitespace(_p)
Skip everything that's not whitespace ('\t', '\n', '\v', '\f', '\r', ' ')
Definition: misc.h:72
#define fr_skip_whitespace(_p)
Skip whitespace ('\t', '\n', '\v', '\f', '\r', ' ')
Definition: misc.h:59
size_t fr_utf8_char(uint8_t const *str, ssize_t inlen)
Checks for utf-8, taken from http://www.w3.org/International/questions/qa-forms-utf-8.
Definition: print.c:39
static bool done
Definition: radclient.c:80
static char const * name
return count
Definition: module.c:163
fr_assert(0)
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
fr_aka_sim_id_type_t type
#define fr_table_value_by_str(_table, _name, _def)
Convert a string to a value using a sorted or ordered table.
Definition: table.h:653
static int talloc_const_free(void const *ptr)
Free const'd memory.
Definition: talloc.h:224
static fr_slen_t head
Definition: xlat.h:406
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition: strerror.h:64
#define fr_strerror_printf_push(_fmt,...)
Add a message to an existing stack of messages at the tail.
Definition: strerror.h:84
#define fr_strerror_const(_msg)
Definition: strerror.h:223
fr_table_num_ordered_t const fr_type_table[]
Map data types to names representing those types.
Definition: types.c:31
#define FR_TYPE_STRUCTURAL
Definition: types.h:296
ssize_t fr_value_box_from_str(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, char const *in, size_t inlen, fr_sbuff_unescape_rules_t const *erules, bool tainted)
Definition: value.c:5315
fr_sbuff_unescape_rules_t * fr_value_unescape_by_char[UINT8_MAX+1]
Definition: value.c:343
void fr_value_box_clear(fr_value_box_t *data)
Clear/free any existing value and metadata.
Definition: value.c:3723
int nonnull(2, 5))