]> git.ipfire.org Git - thirdparty/bird.git/blob - client/commands.c
Client: Online help works (Cisco style: just press `?' at the end of a line).
[thirdparty/bird.git] / client / commands.c
1 /*
2 * BIRD Client -- Command Handling
3 *
4 * (c) 1999--2000 Martin Mares <mj@ucw.cz>
5 *
6 * Can be freely distributed and used under the terms of the GNU GPL.
7 */
8
9 #include <stdio.h>
10
11 #include "nest/bird.h"
12 #include "lib/resource.h"
13 #include "client/client.h"
14
15 struct cmd_info {
16 char *command;
17 char *args;
18 char *help;
19 int is_real_cmd;
20 };
21
22 static struct cmd_info command_table[] = {
23 #include "conf/commands.h"
24 };
25
26 /* FIXME: There should exist some system of aliases, so that `show' can be abbreviated as `s' etc. */
27
28 struct cmd_node {
29 struct cmd_node *sibling, *son, **plastson;
30 struct cmd_info *cmd;
31 int len;
32 char token[1];
33 };
34
35 static struct cmd_node cmd_root;
36
37 void
38 cmd_build_tree(void)
39 {
40 unsigned int i;
41
42 cmd_root.plastson = &cmd_root.son;
43
44 for(i=0; i<sizeof(command_table) / sizeof(struct cmd_info); i++)
45 {
46 struct cmd_info *cmd = &command_table[i];
47 struct cmd_node *old, *new;
48 char *c = cmd->command;
49
50 old = &cmd_root;
51 while (*c)
52 {
53 char *d = c;
54 while (*c && *c != ' ')
55 c++;
56 for(new=old->son; new; new=new->sibling)
57 if (new->len == c-d && !memcmp(new->token, d, c-d))
58 break;
59 if (!new)
60 {
61 new = xmalloc(sizeof(struct cmd_node) + c-d);
62 *old->plastson = new;
63 old->plastson = &new->sibling;
64 new->sibling = new->son = NULL;
65 new->plastson = &new->son;
66 new->cmd = NULL;
67 new->len = c-d;
68 memcpy(new->token, d, c-d);
69 new->token[c-d] = 0;
70 }
71 old = new;
72 while (*c == ' ')
73 c++;
74 }
75 old->cmd = cmd;
76 }
77 }
78
79 static void
80 cmd_display_help(struct cmd_info *c)
81 {
82 char buf[strlen(c->command) + strlen(c->args) + 4];
83
84 sprintf(buf, "%s %s", c->command, c->args);
85 printf("%-45s %s\n", buf, c->help);
86 }
87
88 static struct cmd_node *
89 cmd_find_abbrev(struct cmd_node *root, char *cmd, int len)
90 {
91 struct cmd_node *m, *best = NULL, *best2 = NULL;
92
93 for(m=root->son; m; m=m->sibling)
94 {
95 if (m->len == len && !memcmp(m->token, cmd, len))
96 return m;
97 if (m->len > len && !memcmp(m->token, cmd, len))
98 {
99 best2 = best;
100 best = m;
101 }
102 }
103 return best2 ? NULL : best;
104 }
105
106 void
107 cmd_help(char *cmd, int len)
108 {
109 char *end = cmd + len;
110 struct cmd_node *n, *m;
111 char *z;
112
113 n = &cmd_root;
114 while (cmd < end)
115 {
116 if (*cmd == ' ' || *cmd == '\t')
117 {
118 cmd++;
119 continue;
120 }
121 z = cmd;
122 while (cmd < end && *cmd != ' ' && *cmd != '\t')
123 cmd++;
124 m = cmd_find_abbrev(n, z, cmd-z);
125 if (!m)
126 break;
127 n = m;
128 }
129 if (n->cmd && n->cmd->is_real_cmd)
130 cmd_display_help(n->cmd);
131 for (m=n->son; m; m=m->sibling)
132 cmd_display_help(m->cmd);
133 }