Statistics
| Branch: | Revision:

iof-bird-daemon / nest / cli.c @ bc2fb680

History | View | Annotate | Download (3.39 KB)

1
/*
2
 *        BIRD Internet Routing Daemon -- Command-Line Interface
3
 *
4
 *        (c) 1999 Martin Mares <mj@ucw.cz>
5
 *
6
 *        Can be freely distributed and used under the terms of the GNU GPL.
7
 */
8

    
9
#include "nest/bird.h"
10
#include "nest/cli.h"
11
#include "conf/conf.h"
12
#include "lib/string.h"
13

    
14
pool *cli_pool;
15

    
16
void
17
cli_printf(cli *c, int code, char *msg, ...)
18
{
19
  va_list args;
20
  byte buf[1024];
21
  int cd = code;
22
  int size, cnt;
23
  struct cli_out *o;
24

    
25
  va_start(args, msg);
26
  if (cd < 0)
27
    {
28
      cd = -cd;
29
      if (cd == c->last_reply)
30
        size = bsprintf(buf, " ");
31
      else
32
        size = bsprintf(buf, "%04d-", cd);
33
    }
34
  else
35
    size = bsprintf(buf, "%04d ", cd);
36
  c->last_reply = cd;
37
  cnt = bvsnprintf(buf+size, sizeof(buf)-size-1, msg, args);
38
  if (cnt < 0)
39
    {
40
      cli_printf(c, code < 0 ? -8000 : 8000, "<line overflow>");
41
      return;
42
    }
43
  size += cnt;
44
  buf[size++] = '\n';
45
  if (!(o = c->tx_write) || o->wpos + size > o->end)
46
    {
47
      if (!o && c->tx_buf)
48
        o = c->tx_buf;
49
      else
50
        {
51
          o = mb_alloc(c->pool, sizeof(struct cli_out) + CLI_TX_BUF_SIZE);
52
          if (c->tx_write)
53
            c->tx_write->next = o;
54
          else
55
            c->tx_buf = o;
56
          o->next = NULL;
57
          o->wpos = o->outpos = o->buf;
58
          o->end = o->buf + CLI_TX_BUF_SIZE;
59
        }
60
      c->tx_write = o;
61
      if (!c->tx_pos)
62
        c->tx_pos = o;
63
    }
64
  memcpy(o->wpos, buf, size);
65
  o->wpos += size;
66
}
67

    
68
static void
69
cli_hello(cli *c)
70
{
71
  cli_printf(c, 1, "BIRD " BIRD_VERSION " ready.");
72
  c->cont = NULL;
73
}
74

    
75
static void
76
cli_free_out(cli *c)
77
{
78
  struct cli_out *o, *p;
79

    
80
  if (o = c->tx_buf)
81
    {
82
      c->tx_write = NULL;
83
      o->wpos = o->outpos = o->buf;
84
      while (p = o->next)
85
        {
86
          o->next = p->next;
87
          mb_free(p);
88
        }
89
    }
90
}
91

    
92
static byte *cli_rh_pos;
93
static unsigned int cli_rh_len;
94
static int cli_rh_trick_flag;
95
struct cli *this_cli;
96

    
97
static int
98
cli_cmd_read_hook(byte *buf, unsigned int max)
99
{
100
  if (!cli_rh_trick_flag)
101
    {
102
      cli_rh_trick_flag = 1;
103
      buf[0] = '!';
104
      return 1;
105
    }
106
  if (max > cli_rh_len)
107
    max = cli_rh_len;
108
  memcpy(buf, cli_rh_pos, max);
109
  cli_rh_pos += max;
110
  cli_rh_len -= max;
111
  return max;
112
}
113

    
114
static void
115
cli_command(struct cli *c)
116
{
117
  struct config f;
118
  int res;
119

    
120
  f.pool = NULL;
121
  f.mem = c->parser_pool;
122
  cf_read_hook = cli_cmd_read_hook;
123
  cli_rh_pos = c->rx_buf;
124
  cli_rh_len = strlen(c->rx_buf);
125
  cli_rh_trick_flag = 0;
126
  this_cli = c;
127
  res = cli_parse(&f);
128
  lp_flush(c->parser_pool);
129
  if (!res)
130
    cli_printf(c, 9001, f.err_msg);
131
}
132

    
133
static int
134
cli_event(void *data)
135
{
136
  cli *c = data;
137
  int err;
138

    
139
  if (c->tx_pos)
140
    ;
141
  else if (c->cont)
142
    c->cont(c);
143
  else
144
    {
145
      err = cli_get_command(c);
146
      if (!err)
147
        return 0;
148
      if (err < 0)
149
        cli_printf(c, 9000, "Command too long");
150
      else
151
        cli_command(c);
152
    }
153
  if (cli_write(c))
154
    {
155
      cli_free_out(c);
156
      return 1;
157
    }
158
  return 0;
159
}
160

    
161
cli *
162
cli_new(void *priv)
163
{
164
  pool *p = rp_new(cli_pool, "CLI");
165
  cli *c = mb_alloc(p, sizeof(cli));
166

    
167
  c->pool = p;
168
  c->priv = priv;
169
  c->event = ev_new(p);
170
  c->event->hook = cli_event;
171
  c->event->data = c;
172
  c->tx_buf = c->tx_pos = c->tx_write = NULL;
173
  c->cont = cli_hello;
174
  c->last_reply = 0;
175
  c->parser_pool = lp_new(c->pool, 4096);
176
  ev_schedule(c->event);
177
  return c;
178
}
179

    
180
void
181
cli_kick(cli *c)
182
{
183
  if (!c->cont && !c->tx_pos)
184
    ev_schedule(c->event);
185
}
186

    
187
void
188
cli_written(cli *c)
189
{
190
  cli_free_out(c);
191
  ev_schedule(c->event);
192
}
193

    
194
void
195
cli_free(cli *c)
196
{
197
  rfree(c->pool);
198
}
199

    
200
void
201
cli_init(void)
202
{
203
  cli_pool = rp_new(&root_pool, "CLI");
204
}