[build] legacy files update
[platform/upstream/multipath-tools.git] / multipathd / cli.c
1 /*
2  * Copyright (c) 2005 Christophe Varoqui
3  */
4 #include <memory.h>
5 #include <vector.h>
6 #include <util.h>
7
8 #include "cli.h"
9
10 static struct key *
11 alloc_key (void)
12 {
13         return (struct key *)MALLOC(sizeof(struct key));
14 }
15
16 static struct handler *
17 alloc_handler (void)
18 {
19         return (struct handler *)MALLOC(sizeof(struct handler));
20 }
21
22 static int
23 add_key (vector vec, char * str, int code, int has_param)
24 {
25         struct key * kw;
26
27         kw = alloc_key();
28
29         if (!kw)
30                 return 1;
31
32         kw->code = code;
33         kw->has_param = has_param;
34         kw->str = STRDUP(str);
35
36         if (!kw->str)
37                 goto out;
38
39         if (!vector_alloc_slot(vec))
40                 goto out1;
41
42         vector_set_slot(vec, kw);
43
44         return 0;
45
46 out1:
47         FREE(kw->str);
48 out:
49         FREE(kw);
50         return 1;
51 }
52
53 int
54 add_handler (int fp, int (*fn)(void *, char **, int *, void *))
55 {
56         struct handler * h;
57
58         h = alloc_handler();
59
60         if (!h)
61                 return 1;
62
63         if (!vector_alloc_slot(handlers)) {
64                 FREE(h);
65                 return 1;
66         }
67
68         vector_set_slot(handlers, h);
69         h->fingerprint = fp;
70         h->fn = fn;
71
72         return 0;
73 }
74
75 static void
76 free_key (struct key * kw)
77 {
78         if (kw->str)
79                 FREE(kw->str);
80
81         if (kw->param)
82                 FREE(kw->param);
83
84         FREE(kw);
85 }
86
87 void
88 free_keys (vector vec)
89 {
90         int i;
91         struct key * kw;
92
93         vector_foreach_slot (vec, kw, i)
94                 free_key(kw);
95
96         vector_free(vec);
97 }
98
99 void
100 free_handlers (vector vec)
101 {
102         int i;
103         struct handler * h;
104
105         vector_foreach_slot (vec, h, i)
106                 FREE(h);
107
108         vector_free(vec);
109 }
110
111 int
112 load_keys (void)
113 {
114         int r = 0;
115         keys = vector_alloc();
116
117         if (!keys)
118                 return 1;
119
120         r += add_key(keys, "list", LIST, 0);
121         r += add_key(keys, "show", LIST, 0);
122         r += add_key(keys, "add", ADD, 0);
123         r += add_key(keys, "remove", DEL, 0);
124         r += add_key(keys, "del", DEL, 0);
125         r += add_key(keys, "switch", SWITCH, 0);
126         r += add_key(keys, "switchgroup", SWITCH, 0);
127         r += add_key(keys, "suspend", SUSPEND, 0);
128         r += add_key(keys, "resume", RESUME, 0);
129         r += add_key(keys, "reinstate", REINSTATE, 0);
130         r += add_key(keys, "fail", FAIL, 0);
131         r += add_key(keys, "paths", PATHS, 0);
132         r += add_key(keys, "maps", MAPS, 0);
133         r += add_key(keys, "path", PATH, 1);
134         r += add_key(keys, "map", MAP, 1);
135         r += add_key(keys, "group", GROUP, 1);
136         r += add_key(keys, "dump", DUMP, 0);
137         r += add_key(keys, "pathvec", PATHVEC, 0);
138         r += add_key(keys, "reconfigure", RECONFIGURE, 0);
139
140         if (r) {
141                 free_keys(keys);
142                 keys = NULL;
143                 return 1;
144         }
145
146         return 0;
147 }
148
149 static struct key *
150 find_key (char * str)
151 {
152         int i;
153         struct key * kw = NULL;
154
155         vector_foreach_slot (keys, kw, i)
156                 if (strlen(str) == strlen(kw->str) &&
157                     !strcmp(kw->str, str))
158                                 return kw;
159
160         return NULL;
161 }
162                 
163 static struct handler *
164 find_handler (int fp)
165 {
166         int i;
167         struct handler *h;
168
169         vector_foreach_slot (handlers, h, i)
170                 if (h->fingerprint == fp)
171                         return h;
172
173         return NULL;
174 }
175
176 static vector
177 get_cmdvec (char * cmd)
178 {
179         int fwd = 1;
180         char * p = cmd;
181         char * buff;
182         struct key * kw = NULL;
183         struct key * cmdkw = NULL;
184         vector cmdvec;
185
186         cmdvec = vector_alloc();
187
188         if (!cmdvec)
189                 return NULL;
190
191         while (fwd) {
192                 fwd = get_word(p, &buff);
193
194                 if (!buff)
195                         break;
196
197                 p += fwd;
198                 kw = find_key(buff);
199                 FREE(buff);
200
201                 if (!kw)
202                         goto out; /* synthax error */
203
204                 cmdkw = alloc_key();
205
206                 if (!cmdkw)
207                         goto out;
208
209                 if (!vector_alloc_slot(cmdvec)) {
210                         FREE(cmdkw);
211                         goto out;
212                 }
213
214                 vector_set_slot(cmdvec, cmdkw);
215                 cmdkw->code = kw->code;
216                 cmdkw->has_param = kw->has_param;
217                 
218                 if (kw->has_param) {
219                         if (*p == '\0')
220                                 goto out;
221
222                         fwd = get_word(p, &buff);
223
224                         if (!buff)
225                                 goto out;
226
227                         p += fwd;
228                         cmdkw->param = buff;
229                 }
230         }
231
232         return cmdvec;
233
234 out:
235         free_keys(cmdvec);
236         return NULL;
237 }
238
239 static int 
240 fingerprint(vector vec)
241 {
242         int i;
243         int fp = 0;
244         struct key * kw;
245
246         vector_foreach_slot(vec, kw, i)
247                 fp += kw->code;
248
249         return fp;
250 }
251
252 int
253 alloc_handlers (void)
254 {
255         handlers = vector_alloc();
256
257         if (!handlers)
258                 return 1;
259
260         return 0;
261 }
262
263 static int
264 genhelp_sprint_aliases (char * reply, vector keys, struct key * refkw)
265 {
266         int i, fwd = 0;
267         struct key * kw;
268
269         vector_foreach_slot (keys, kw, i)
270                 if (kw->code == refkw->code && kw != refkw)
271                         fwd += sprintf(reply, "|%s", kw->str);
272
273         return fwd;
274 }
275
276 static char *
277 genhelp_handler (void)
278 {
279         int i, j;
280         int fp;
281         struct handler * h;
282         struct key * kw;
283         char * reply;
284         char * p;
285
286         reply = MALLOC(INITIAL_REPLY_LEN);
287
288         if (!reply)
289                 return NULL;
290
291         p = reply;
292
293         vector_foreach_slot (handlers, h, i) {
294                 fp = h->fingerprint;
295                 vector_foreach_slot (keys, kw, j) {
296                         if ((kw->code & fp)) {
297                                 fp -= kw->code;
298                                 p += sprintf(p, " %s", kw->str);
299                                 p += genhelp_sprint_aliases(p, keys, kw);
300
301                                 if (kw->has_param)
302                                         p += sprintf(p, " $%s", kw->str);
303                         }
304                 }
305                 p += sprintf(p, "\n");
306         }
307
308         return reply;
309 }
310
311 int
312 parse_cmd (char * cmd, char ** reply, int * len, void * data)
313 {
314         int r;
315         struct handler * h;
316         vector cmdvec = get_cmdvec(cmd);
317
318         if (!cmdvec) {
319                 *reply = genhelp_handler();
320                 *len = strlen(*reply) + 1;
321                 return 0;
322         }
323
324         h = find_handler(fingerprint(cmdvec));
325
326         if (!h) {
327                 *reply = genhelp_handler();
328                 *len = strlen(*reply) + 1;
329                 return 0;
330         }
331
332         /*
333          * execute handler
334          */
335         r = h->fn(cmdvec, reply, len, data);
336         free_keys(cmdvec);
337
338         return r;
339 }
340
341 char *
342 get_keyparam (vector v, int code)
343 {
344         struct key * kw;
345         int i;
346
347         vector_foreach_slot(v, kw, i)
348                 if (kw->code == code)
349                         return kw->param;
350
351         return NULL;
352 }