Client considered finished (modulo bugs).
Core
~~~~
-- IPv6: router advertisements
-- IPv6: test it!
- IPv6: hashing functions etc.
- krt-iface: check whether the interface alias hack works
~~~~~~~~
- 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
~~~~~~~~~~~~~
- write doctool
Various ideas
~~~~~~~~~~~~~
+- client: access control
+- IPv6 router advertisements
- real multipath (doesn't seem to be simple at all :()
- fake multipath (even less simple)
- route recalculation timing and flap dampening [see RFC2439 for algorithms]
static void
got_line(char *cmd_buffer)
{
+ char *cmd;
+
if (!cmd_buffer)
{
cleanup();
}
if (cmd_buffer[0])
{
- add_history(cmd_buffer);
- /* FIXME: Builtin commands: exit, ... */
- server_send(cmd_buffer);
- input_hidden = -1;
- io_loop(0);
- input_hidden = 0;
+ cmd = cmd_expand(cmd_buffer);
+ if (cmd)
+ {
+ add_history(cmd);
+ puts(cmd);
+ 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);
}
void cmd_build_tree(void);
void cmd_help(char *cmd, int len);
int cmd_complete(char *cmd, int len, char *buf, int again);
+char *cmd_expand(char *cmd);
#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 *sibling, *son, **plastson;
struct cmd_info *cmd, *help;
while (*c)
{
char *d = c;
- while (*c && *c != ' ')
+ while (*c && !isspace(*c))
c++;
for(new=old->son; new; new=new->sibling)
if (new->len == c-d && !memcmp(new->token, d, c-d))
memcpy(new->token, d, c-d);
}
old = new;
- while (*c == ' ')
+ while (isspace(*c))
c++;
}
if (cmd->is_real_cmd)
n = &cmd_root;
while (cmd < end)
{
- if (*cmd == ' ' || *cmd == '\t')
+ if (isspace(*cmd))
{
cmd++;
continue;
}
z = cmd;
- while (cmd < end && *cmd != ' ' && *cmd != '\t')
+ while (cmd < end && !isspace(*cmd))
cmd++;
m = cmd_find_abbrev(n, z, cmd-z, &ambig);
if (ambig)
n = &cmd_root;
while (cmd < fin && n->son)
{
- if (*cmd == ' ' || *cmd == '\t')
+ if (isspace(*cmd))
{
cmd++;
continue;
input_stop_list();
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;
+}
#include <stdarg.h>
#include "nest/bird.h"
+#include "lib/string.h"
#include "client/client.h"
/* 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
bug(char *msg, ...)
va_start(args, msg);
cleanup();
fputs("Internal error: ", stderr);
+ vlog(msg, args);
vfprintf(stderr, msg, args);
- fputc('\n', stderr);
exit(1);
}
va_start(args, msg);
cleanup();
- vfprintf(stderr, msg, args);
- fputc('\n', stderr);
+ vlog(msg, args);
exit(1);
}