Statistics
| Branch: | Revision:

iof-bird-daemon / nest / cli.c @ 1d2664a4

History | View | Annotate | Download (3.51 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 <string.h>
10

    
11
#include "nest/bird.h"
12
#include "nest/cli.h"
13
#include "conf/conf.h"
14
#include "lib/string.h"
15

    
16
pool *cli_pool;
17

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

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

    
72
static void
73
cli_hello(cli *c)
74
{
75
  cli_printf(c, 1, "BIRD " BIRD_VERSION " ready.");
76
  c->cont = NULL;
77
}
78

    
79
static void
80
cli_free_out(cli *c)
81
{
82
  struct cli_out *o, *p;
83

    
84
  if (o = c->tx_buf)
85
    {
86
      c->tx_write = NULL;
87
      o->wpos = o->outpos = o->buf;
88
      while (p = o->next)
89
        {
90
          o->next = p->next;
91
          mb_free(p);
92
        }
93
    }
94
}
95

    
96
static byte *cli_rh_pos;
97
static unsigned int cli_rh_len;
98
static int cli_rh_trick_flag;
99
struct cli *this_cli;
100

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

    
118
static void
119
cli_command(struct cli *c)
120
{
121
  struct config f;
122
  int res;
123

    
124
  bzero(&f, sizeof(f));
125
  f.mem = c->parser_pool;
126
  cf_read_hook = cli_cmd_read_hook;
127
  cli_rh_pos = c->rx_buf;
128
  cli_rh_len = strlen(c->rx_buf);
129
  cli_rh_trick_flag = 0;
130
  this_cli = c;
131
  res = cli_parse(&f);
132
  lp_flush(c->parser_pool);
133
  if (!res)
134
    cli_printf(c, 9001, f.err_msg);
135
}
136

    
137
static int
138
cli_event(void *data)
139
{
140
  cli *c = data;
141
  int err;
142

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

    
165
cli *
166
cli_new(void *priv)
167
{
168
  pool *p = rp_new(cli_pool, "CLI");
169
  cli *c = mb_alloc(p, sizeof(cli));
170

    
171
  c->pool = p;
172
  c->priv = priv;
173
  c->event = ev_new(p);
174
  c->event->hook = cli_event;
175
  c->event->data = c;
176
  c->tx_buf = c->tx_pos = c->tx_write = NULL;
177
  c->cont = cli_hello;
178
  c->cleanup = NULL;
179
  c->last_reply = 0;
180
  c->parser_pool = lp_new(c->pool, 4096);
181
  ev_schedule(c->event);
182
  return c;
183
}
184

    
185
void
186
cli_kick(cli *c)
187
{
188
  if (!c->cont && !c->tx_pos)
189
    ev_schedule(c->event);
190
}
191

    
192
void
193
cli_written(cli *c)
194
{
195
  cli_free_out(c);
196
  ev_schedule(c->event);
197
}
198

    
199
void
200
cli_free(cli *c)
201
{
202
  if (c->cleanup)
203
    c->cleanup(c);
204
  rfree(c->pool);
205
}
206

    
207
void
208
cli_init(void)
209
{
210
  cli_pool = rp_new(&root_pool, "CLI");
211
}