Support expansion of command abbreviations.

Client considered finished (modulo bugs).
This commit is contained in:
Martin Mares 2000-02-27 22:00:19 +00:00
parent de30342f97
commit e69e4ed934
5 changed files with 80 additions and 34 deletions

19
TODO
View file

@ -1,7 +1,5 @@
Core Core
~~~~ ~~~~
- IPv6: router advertisements
- IPv6: test it!
- IPv6: hashing functions etc. - IPv6: hashing functions etc.
- krt-iface: check whether the interface alias hack works - krt-iface: check whether the interface alias hack works
@ -36,21 +34,6 @@ Commands
~~~~~~~~ ~~~~~~~~
- showing of routing table as seen by given protocol - showing of routing table as seen by given protocol
Roadmap
~~~~~~~
- Allocators and data structures
- Client
- Remaining bits of IPv6 support (radvd)
- RIPv6
- BGP?
Client
~~~~~~
- command completion
- online help
- builtin command and aliases
- access control
Documentation Documentation
~~~~~~~~~~~~~ ~~~~~~~~~~~~~
- write doctool - write doctool
@ -74,6 +57,8 @@ Globals
Various ideas Various ideas
~~~~~~~~~~~~~ ~~~~~~~~~~~~~
- client: access control
- IPv6 router advertisements
- real multipath (doesn't seem to be simple at all :() - real multipath (doesn't seem to be simple at all :()
- fake multipath (even less simple) - fake multipath (even less simple)
- route recalculation timing and flap dampening [see RFC2439 for algorithms] - route recalculation timing and flap dampening [see RFC2439 for algorithms]

View file

@ -79,6 +79,8 @@ extern Function *rl_last_func;
static void static void
got_line(char *cmd_buffer) got_line(char *cmd_buffer)
{ {
char *cmd;
if (!cmd_buffer) if (!cmd_buffer)
{ {
cleanup(); cleanup();
@ -86,12 +88,22 @@ got_line(char *cmd_buffer)
} }
if (cmd_buffer[0]) if (cmd_buffer[0])
{ {
add_history(cmd_buffer); cmd = cmd_expand(cmd_buffer);
/* FIXME: Builtin commands: exit, ... */ if (cmd)
server_send(cmd_buffer); {
input_hidden = -1; add_history(cmd);
io_loop(0); puts(cmd);
input_hidden = 0; if (!strcmp(cmd, "exit") || !strcmp(cmd, "quit"))
{
cleanup();
exit(0);
}
server_send(cmd);
input_hidden = -1;
io_loop(0);
input_hidden = 0;
free(cmd);
}
} }
free(cmd_buffer); free(cmd_buffer);
} }

View file

@ -17,3 +17,4 @@ void input_stop_list(void);
void cmd_build_tree(void); void cmd_build_tree(void);
void cmd_help(char *cmd, int len); void cmd_help(char *cmd, int len);
int cmd_complete(char *cmd, int len, char *buf, int again); int cmd_complete(char *cmd, int len, char *buf, int again);
char *cmd_expand(char *cmd);

View file

@ -25,8 +25,6 @@ static struct cmd_info command_table[] = {
#include "conf/commands.h" #include "conf/commands.h"
}; };
/* FIXME: There should exist some system of aliases, so that `show' can be abbreviated as `s' etc. */
struct cmd_node { struct cmd_node {
struct cmd_node *sibling, *son, **plastson; struct cmd_node *sibling, *son, **plastson;
struct cmd_info *cmd, *help; struct cmd_info *cmd, *help;
@ -53,7 +51,7 @@ cmd_build_tree(void)
while (*c) while (*c)
{ {
char *d = c; char *d = c;
while (*c && *c != ' ') while (*c && !isspace(*c))
c++; c++;
for(new=old->son; new; new=new->sibling) for(new=old->son; new; new=new->sibling)
if (new->len == c-d && !memcmp(new->token, d, c-d)) if (new->len == c-d && !memcmp(new->token, d, c-d))
@ -70,7 +68,7 @@ cmd_build_tree(void)
memcpy(new->token, d, c-d); memcpy(new->token, d, c-d);
} }
old = new; old = new;
while (*c == ' ') while (isspace(*c))
c++; c++;
} }
if (cmd->is_real_cmd) if (cmd->is_real_cmd)
@ -143,13 +141,13 @@ cmd_help(char *cmd, int len)
n = &cmd_root; n = &cmd_root;
while (cmd < end) while (cmd < end)
{ {
if (*cmd == ' ' || *cmd == '\t') if (isspace(*cmd))
{ {
cmd++; cmd++;
continue; continue;
} }
z = cmd; z = cmd;
while (cmd < end && *cmd != ' ' && *cmd != '\t') while (cmd < end && !isspace(*cmd))
cmd++; cmd++;
m = cmd_find_abbrev(n, z, cmd-z, &ambig); m = cmd_find_abbrev(n, z, cmd-z, &ambig);
if (ambig) if (ambig)
@ -213,7 +211,7 @@ cmd_complete(char *cmd, int len, char *buf, int again)
n = &cmd_root; n = &cmd_root;
while (cmd < fin && n->son) while (cmd < fin && n->son)
{ {
if (*cmd == ' ' || *cmd == '\t') if (isspace(*cmd))
{ {
cmd++; cmd++;
continue; continue;
@ -262,3 +260,44 @@ cmd_complete(char *cmd, int len, char *buf, int again)
input_stop_list(); input_stop_list();
return 0; return 0;
} }
char *
cmd_expand(char *cmd)
{
struct cmd_node *n, *m;
char *c, *b, *args;
int ambig;
args = c = cmd;
n = &cmd_root;
while (*c)
{
if (isspace(*c))
{
c++;
continue;
}
b = c;
while (*c && !isspace(*c))
c++;
m = cmd_find_abbrev(n, b, c-b, &ambig);
if (!m)
{
if (!ambig)
break;
puts("Ambiguous command, possible expansions are:");
cmd_list_ambiguous(n, b, c-b);
return NULL;
}
args = c;
n = m;
}
if (!n->cmd)
{
puts("No such command.");
return NULL;
}
b = malloc(strlen(n->cmd->command) + strlen(args) + 1);
sprintf(b, "%s%s", n->cmd->command, args);
return b;
}

View file

@ -12,11 +12,21 @@
#include <stdarg.h> #include <stdarg.h>
#include "nest/bird.h" #include "nest/bird.h"
#include "lib/string.h"
#include "client/client.h" #include "client/client.h"
/* Client versions of logging functions */ /* Client versions of logging functions */
/* FIXME: Use bsprintf, so that %m works */ static void
vlog(char *msg, va_list args)
{
char buf[1024];
if (bvsnprintf(buf, sizeof(buf)-1, msg, args) < 0)
bsprintf(buf + sizeof(buf) - 100, " ... <too long>");
fputs(buf, stderr);
fputc('\n', stderr);
}
void void
bug(char *msg, ...) bug(char *msg, ...)
@ -26,8 +36,8 @@ bug(char *msg, ...)
va_start(args, msg); va_start(args, msg);
cleanup(); cleanup();
fputs("Internal error: ", stderr); fputs("Internal error: ", stderr);
vlog(msg, args);
vfprintf(stderr, msg, args); vfprintf(stderr, msg, args);
fputc('\n', stderr);
exit(1); exit(1);
} }
@ -38,7 +48,6 @@ die(char *msg, ...)
va_start(args, msg); va_start(args, msg);
cleanup(); cleanup();
vfprintf(stderr, msg, args); vlog(msg, args);
fputc('\n', stderr);
exit(1); exit(1);
} }