]> git.ipfire.org Git - thirdparty/bird.git/blame - nest/cli.c
Make ACCEPT/REJECT actually return the result...
[thirdparty/bird.git] / nest / cli.c
CommitLineData
7d3aab1c
MM
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
1d2664a4
MM
9#include <string.h>
10
7d3aab1c 11#include "nest/bird.h"
7d3aab1c 12#include "nest/cli.h"
bc2fb680
MM
13#include "conf/conf.h"
14#include "lib/string.h"
7d3aab1c
MM
15
16pool *cli_pool;
17
18void
19cli_printf(cli *c, int code, char *msg, ...)
20{
21 va_list args;
22 byte buf[1024];
b9672a84
MM
23 int cd = code;
24 int size, cnt;
7d3aab1c
MM
25 struct cli_out *o;
26
27 va_start(args, msg);
b9672a84
MM
28 if (cd < 0)
29 {
30 cd = -cd;
10b5baae 31#if 0 /* FIXME: Enable */
b9672a84
MM
32 if (cd == c->last_reply)
33 size = bsprintf(buf, " ");
34 else
10b5baae 35#endif
b9672a84
MM
36 size = bsprintf(buf, "%04d-", cd);
37 }
7d3aab1c 38 else
b9672a84
MM
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;
7d3aab1c
MM
48 buf[size++] = '\n';
49 if (!(o = c->tx_write) || o->wpos + size > o->end)
50 {
b9672a84
MM
51 if (!o && c->tx_buf)
52 o = c->tx_buf;
7d3aab1c 53 else
b9672a84
MM
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 }
7d3aab1c 64 c->tx_write = o;
b9672a84
MM
65 if (!c->tx_pos)
66 c->tx_pos = o;
7d3aab1c
MM
67 }
68 memcpy(o->wpos, buf, size);
69 o->wpos += size;
70}
71
b9672a84
MM
72static void
73cli_hello(cli *c)
74{
75 cli_printf(c, 1, "BIRD " BIRD_VERSION " ready.");
76 c->cont = NULL;
77}
78
7d3aab1c
MM
79static void
80cli_free_out(cli *c)
81{
82 struct cli_out *o, *p;
83
84 if (o = c->tx_buf)
85 {
b9672a84 86 c->tx_write = NULL;
7d3aab1c
MM
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
bc2fb680
MM
96static byte *cli_rh_pos;
97static unsigned int cli_rh_len;
98static int cli_rh_trick_flag;
99struct cli *this_cli;
100
101static int
102cli_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
118static void
119cli_command(struct cli *c)
120{
121 struct config f;
122 int res;
123
1d2664a4 124 bzero(&f, sizeof(f));
bc2fb680
MM
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
7d3aab1c
MM
137static int
138cli_event(void *data)
139{
140 cli *c = data;
141 int err;
142
b9672a84
MM
143 if (c->tx_pos)
144 ;
145 else if (c->cont)
146 c->cont(c);
147 else
7d3aab1c 148 {
b9672a84
MM
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
bc2fb680 155 cli_command(c);
7d3aab1c 156 }
b9672a84
MM
157 if (cli_write(c))
158 {
159 cli_free_out(c);
160 return 1;
161 }
162 return 0;
7d3aab1c
MM
163}
164
165cli *
166cli_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;
b9672a84 177 c->cont = cli_hello;
ffb59d24 178 c->cleanup = NULL;
b9672a84 179 c->last_reply = 0;
bc2fb680 180 c->parser_pool = lp_new(c->pool, 4096);
b9672a84 181 ev_schedule(c->event);
7d3aab1c
MM
182 return c;
183}
184
185void
186cli_kick(cli *c)
187{
b9672a84
MM
188 if (!c->cont && !c->tx_pos)
189 ev_schedule(c->event);
7d3aab1c
MM
190}
191
192void
193cli_written(cli *c)
194{
7d3aab1c 195 cli_free_out(c);
b9672a84 196 ev_schedule(c->event);
7d3aab1c
MM
197}
198
199void
200cli_free(cli *c)
201{
ffb59d24
MM
202 if (c->cleanup)
203 c->cleanup(c);
7d3aab1c
MM
204 rfree(c->pool);
205}
206
207void
208cli_init(void)
209{
210 cli_pool = rp_new(&root_pool, "CLI");
211}