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=../
|
||||
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 "nest/bird.h"
|
||||
#include "lib/resource.h" /* For dmalloc */
|
||||
#include "client/client.h"
|
||||
|
||||
#include "unix.h"
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "nest/route.h"
|
||||
#include "nest/protocol.h"
|
||||
#include "nest/iface.h"
|
||||
#include "nest/cli.h"
|
||||
#include "conf/conf.h"
|
||||
#include "filter/filter.h"
|
||||
|
||||
|
@ -86,6 +87,119 @@ async_config(void)
|
|||
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
|
||||
*/
|
||||
|
@ -101,6 +215,7 @@ async_shutdown(void)
|
|||
void
|
||||
protos_shutdown_notify(void)
|
||||
{
|
||||
unlink(PATH_CONTROL_SOCKET);
|
||||
die("System shutdown completed");
|
||||
}
|
||||
|
||||
|
@ -194,7 +309,7 @@ main(int argc, char **argv)
|
|||
#endif
|
||||
|
||||
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);
|
||||
parse_args(argc, argv);
|
||||
|
||||
|
@ -214,6 +329,8 @@ main(int argc, char **argv)
|
|||
|
||||
signal_init();
|
||||
|
||||
cli_init_unix();
|
||||
|
||||
protos_start();
|
||||
|
||||
ev_run_list(&global_event_list);
|
||||
|
|
Loading…
Reference in a new issue