First steps of the Command Line Interface: I/O routines.
This commit is contained in:
parent
b93abffae4
commit
7d3aab1c16
5 changed files with 313 additions and 2 deletions
|
@ -1,4 +1,4 @@
|
||||||
source=rt-table.c rt-fib.c rt-attr.c proto.c iface.c rt-dev.c password.c
|
source=rt-table.c rt-fib.c rt-attr.c proto.c iface.c rt-dev.c password.c cli.c
|
||||||
root-rel=../
|
root-rel=../
|
||||||
dir-name=nest
|
dir-name=nest
|
||||||
|
|
||||||
|
|
144
nest/cli.c
Normal file
144
nest/cli.c
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
/*
|
||||||
|
* BIRD Internet Routing Daemon -- Command-Line Interface
|
||||||
|
*
|
||||||
|
* (c) 1999 Martin Mares <mj@ucw.cz>
|
||||||
|
*
|
||||||
|
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "nest/bird.h"
|
||||||
|
#include "lib/string.h"
|
||||||
|
#include "nest/cli.h"
|
||||||
|
|
||||||
|
pool *cli_pool;
|
||||||
|
|
||||||
|
void
|
||||||
|
cli_printf(cli *c, int code, char *msg, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
byte buf[1024];
|
||||||
|
int flag = (code < 0) ? '-' : ' ';
|
||||||
|
int size;
|
||||||
|
struct cli_out *o;
|
||||||
|
|
||||||
|
va_start(args, msg);
|
||||||
|
if (code < 0)
|
||||||
|
code = -code;
|
||||||
|
bsprintf(buf, "%04d%c", code, flag);
|
||||||
|
size = bvsnprintf(buf+5, sizeof(buf)-6, msg, args);
|
||||||
|
if (size < 0)
|
||||||
|
size = bsprintf(buf, "9999%c<line overflow>", flag);
|
||||||
|
else
|
||||||
|
size += 5;
|
||||||
|
buf[size++] = '\n';
|
||||||
|
if (!(o = c->tx_write) || o->wpos + size > o->end)
|
||||||
|
{
|
||||||
|
o = mb_alloc(c->pool, sizeof(struct cli_out) + CLI_TX_BUF_SIZE);
|
||||||
|
if (c->tx_write)
|
||||||
|
c->tx_write->next = o;
|
||||||
|
else
|
||||||
|
c->tx_buf = o;
|
||||||
|
o->next = NULL;
|
||||||
|
o->wpos = o->outpos = o->buf;
|
||||||
|
o->end = o->buf + CLI_TX_BUF_SIZE;
|
||||||
|
c->tx_write = o;
|
||||||
|
}
|
||||||
|
memcpy(o->wpos, buf, size);
|
||||||
|
o->wpos += size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cli_free_out(cli *c)
|
||||||
|
{
|
||||||
|
struct cli_out *o, *p;
|
||||||
|
|
||||||
|
if (o = c->tx_buf)
|
||||||
|
{
|
||||||
|
c->tx_write = o;
|
||||||
|
o->wpos = o->outpos = o->buf;
|
||||||
|
while (p = o->next)
|
||||||
|
{
|
||||||
|
o->next = p->next;
|
||||||
|
mb_free(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
cli_flush(cli *c)
|
||||||
|
{
|
||||||
|
if (cli_write(c))
|
||||||
|
{
|
||||||
|
cli_free_out(c);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
cli_event(void *data)
|
||||||
|
{
|
||||||
|
cli *c = data;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
debug("CLI EVENT\n");
|
||||||
|
if (!c->inited)
|
||||||
|
{
|
||||||
|
c->inited = 1;
|
||||||
|
cli_printf(c, 0, "Welcome!");
|
||||||
|
cli_printf(c, 0, "Here");
|
||||||
|
return cli_flush(c);
|
||||||
|
}
|
||||||
|
err = cli_get_command(c);
|
||||||
|
if (!err)
|
||||||
|
return 0;
|
||||||
|
if (err < 0)
|
||||||
|
debug("CLI CMD ERR\n");
|
||||||
|
else
|
||||||
|
debug("CLI CMD %s\n", c->rx_buf);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cli *
|
||||||
|
cli_new(void *priv)
|
||||||
|
{
|
||||||
|
pool *p = rp_new(cli_pool, "CLI");
|
||||||
|
cli *c = mb_alloc(p, sizeof(cli));
|
||||||
|
|
||||||
|
c->pool = p;
|
||||||
|
c->priv = priv;
|
||||||
|
c->event = ev_new(p);
|
||||||
|
c->event->hook = cli_event;
|
||||||
|
c->event->data = c;
|
||||||
|
c->tx_buf = c->tx_pos = c->tx_write = NULL;
|
||||||
|
c->inited = 0;
|
||||||
|
cli_kick(c);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cli_kick(cli *c)
|
||||||
|
{
|
||||||
|
debug("CLI KICK\n");
|
||||||
|
ev_schedule(c->event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cli_written(cli *c)
|
||||||
|
{
|
||||||
|
debug("CLI WRITTEN\n");
|
||||||
|
cli_free_out(c);
|
||||||
|
cli_kick(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cli_free(cli *c)
|
||||||
|
{
|
||||||
|
rfree(c->pool);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cli_init(void)
|
||||||
|
{
|
||||||
|
cli_pool = rp_new(&root_pool, "CLI");
|
||||||
|
}
|
49
nest/cli.h
Normal file
49
nest/cli.h
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* BIRD Internet Routing Daemon -- Command-Line Interface
|
||||||
|
*
|
||||||
|
* (c) 1999 Martin Mares <mj@ucw.cz>
|
||||||
|
*
|
||||||
|
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _BIRD_CLI_H_
|
||||||
|
#define _BIRD_CLI_H_
|
||||||
|
|
||||||
|
#include "lib/resource.h"
|
||||||
|
#include "lib/event.h"
|
||||||
|
|
||||||
|
#define CLI_RX_BUF_SIZE 4096
|
||||||
|
#define CLI_TX_BUF_SIZE 4096
|
||||||
|
|
||||||
|
struct cli_out {
|
||||||
|
struct cli_out *next;
|
||||||
|
byte *wpos, *outpos, *end;
|
||||||
|
byte buf[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct cli {
|
||||||
|
pool *pool;
|
||||||
|
void *priv; /* Private to sysdep layer */
|
||||||
|
int inited;
|
||||||
|
byte rx_buf[CLI_RX_BUF_SIZE];
|
||||||
|
byte *rx_pos, *rx_aux; /* sysdep */
|
||||||
|
struct cli_out *tx_buf, *tx_pos, *tx_write;
|
||||||
|
event *event;
|
||||||
|
} cli;
|
||||||
|
|
||||||
|
extern pool *cli_pool;
|
||||||
|
|
||||||
|
cli *cli_new(void *);
|
||||||
|
void cli_init(void);
|
||||||
|
void cli_free(cli *);
|
||||||
|
void cli_kick(cli *);
|
||||||
|
void cli_written(cli *);
|
||||||
|
void cli_printf(cli *, int, char *, ...);
|
||||||
|
|
||||||
|
/* Function provided by sysdep layer */
|
||||||
|
|
||||||
|
int cli_write(cli *);
|
||||||
|
void cli_disconnect(cli *);
|
||||||
|
int cli_get_command(cli *);
|
||||||
|
|
||||||
|
#endif
|
|
@ -12,6 +12,7 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "nest/bird.h"
|
#include "nest/bird.h"
|
||||||
|
#include "lib/resource.h" /* For dmalloc */
|
||||||
#include "client/client.h"
|
#include "client/client.h"
|
||||||
|
|
||||||
#include "unix.h"
|
#include "unix.h"
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "nest/route.h"
|
#include "nest/route.h"
|
||||||
#include "nest/protocol.h"
|
#include "nest/protocol.h"
|
||||||
#include "nest/iface.h"
|
#include "nest/iface.h"
|
||||||
|
#include "nest/cli.h"
|
||||||
#include "conf/conf.h"
|
#include "conf/conf.h"
|
||||||
#include "filter/filter.h"
|
#include "filter/filter.h"
|
||||||
|
|
||||||
|
@ -86,6 +87,119 @@ async_config(void)
|
||||||
debug("Asynchronous reconfigurations are not supported in demo version\n");
|
debug("Asynchronous reconfigurations are not supported in demo version\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Command-Line Interface
|
||||||
|
*/
|
||||||
|
|
||||||
|
static sock *cli_sk;
|
||||||
|
|
||||||
|
void
|
||||||
|
cli_disconnect(cli *c)
|
||||||
|
{
|
||||||
|
bug("CLI DISCONNECT: Not implemented"); /* FIXME */
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
cli_write(cli *c)
|
||||||
|
{
|
||||||
|
sock *s = c->priv;
|
||||||
|
|
||||||
|
if (c->tx_pos)
|
||||||
|
{
|
||||||
|
struct cli_out *o = c->tx_pos;
|
||||||
|
c->tx_pos = o->next;
|
||||||
|
s->tbuf = o->outpos;
|
||||||
|
return sk_send(s, o->wpos - o->outpos);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
cli_get_command(cli *c)
|
||||||
|
{
|
||||||
|
sock *s = c->priv;
|
||||||
|
byte *t = c->rx_aux ? : s->rbuf;
|
||||||
|
byte *tend = s->rpos;
|
||||||
|
byte *d = c->rx_pos;
|
||||||
|
byte *dend = c->rx_buf + CLI_RX_BUF_SIZE - 2;
|
||||||
|
|
||||||
|
while (t < tend)
|
||||||
|
{
|
||||||
|
if (*t == '\r')
|
||||||
|
t++;
|
||||||
|
else if (*t == '\n')
|
||||||
|
{
|
||||||
|
t++;
|
||||||
|
c->rx_pos = c->rx_buf;
|
||||||
|
c->rx_aux = t;
|
||||||
|
*d = 0;
|
||||||
|
return (d < dend) ? 1 : -1;
|
||||||
|
}
|
||||||
|
else if (d < dend)
|
||||||
|
*d++ = *t++;
|
||||||
|
}
|
||||||
|
c->rx_aux = s->rpos = s->rbuf;
|
||||||
|
c->rx_pos = d;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
cli_rx(sock *s, int size)
|
||||||
|
{
|
||||||
|
debug("CLI RX\n");
|
||||||
|
cli_kick(s->data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cli_tx(sock *s)
|
||||||
|
{
|
||||||
|
cli *c = s->data;
|
||||||
|
|
||||||
|
debug("CLI TX\n");
|
||||||
|
if (cli_write(c))
|
||||||
|
cli_written(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cli_err(sock *s, int err)
|
||||||
|
{
|
||||||
|
if (err)
|
||||||
|
log(L_INFO "CLI connection dropped: %s", strerror(err));
|
||||||
|
else
|
||||||
|
log(L_INFO "CLI connection closed");
|
||||||
|
s->type = SK_DELETED;
|
||||||
|
cli_free(s->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
cli_connect(sock *s, int size)
|
||||||
|
{
|
||||||
|
cli *c;
|
||||||
|
|
||||||
|
log(L_INFO "CLI connect");
|
||||||
|
s->rx_hook = cli_rx;
|
||||||
|
s->tx_hook = cli_tx;
|
||||||
|
s->err_hook = cli_err;
|
||||||
|
s->rbsize = 1024;
|
||||||
|
s->data = c = cli_new(s);
|
||||||
|
c->rx_pos = c->rx_buf;
|
||||||
|
c->rx_aux = NULL;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cli_init_unix(void)
|
||||||
|
{
|
||||||
|
sock *s;
|
||||||
|
|
||||||
|
cli_init();
|
||||||
|
s = cli_sk = sk_new(cli_pool);
|
||||||
|
s->type = SK_UNIX_PASSIVE;
|
||||||
|
s->rx_hook = cli_connect;
|
||||||
|
sk_open_unix(s, PATH_CONTROL_SOCKET);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Shutdown
|
* Shutdown
|
||||||
*/
|
*/
|
||||||
|
@ -101,6 +215,7 @@ async_shutdown(void)
|
||||||
void
|
void
|
||||||
protos_shutdown_notify(void)
|
protos_shutdown_notify(void)
|
||||||
{
|
{
|
||||||
|
unlink(PATH_CONTROL_SOCKET);
|
||||||
die("System shutdown completed");
|
die("System shutdown completed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,7 +309,7 @@ main(int argc, char **argv)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
log_init_debug(NULL);
|
log_init_debug(NULL);
|
||||||
setvbuf(stdout, NULL, _IONBF, 0); /* And yes, this does make a difference */
|
setvbuf(stdout, NULL, _IONBF, 0); /* FIXME: Kill some day. */
|
||||||
setvbuf(stderr, NULL, _IONBF, 0);
|
setvbuf(stderr, NULL, _IONBF, 0);
|
||||||
parse_args(argc, argv);
|
parse_args(argc, argv);
|
||||||
|
|
||||||
|
@ -214,6 +329,8 @@ main(int argc, char **argv)
|
||||||
|
|
||||||
signal_init();
|
signal_init();
|
||||||
|
|
||||||
|
cli_init_unix();
|
||||||
|
|
||||||
protos_start();
|
protos_start();
|
||||||
|
|
||||||
ev_run_list(&global_event_list);
|
ev_run_list(&global_event_list);
|
||||||
|
|
Loading…
Reference in a new issue