1 /*
2  * cmdlang.c
3  *
4  * A command interpreter for OpenIPMI
5  *
6  * Author: MontaVista Software, Inc.
7  *         Corey Minyard <minyard@mvista.com>
8  *         source@mvista.com
9  *
10  * Copyright 2004 MontaVista Software Inc.
11  *
12  *  This program is free software; you can redistribute it and/or
13  *  modify it under the terms of the GNU Lesser General Public License
14  *  as published by the Free Software Foundation; either version 2 of
15  *  the License, or (at your option) any later version.
16  *
17  *
18  *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
19  *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
24  *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25  *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
26  *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
27  *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  *
29  *  You should have received a copy of the GNU Lesser General Public
30  *  License along with this program; if not, write to the Free
31  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
32  */
33 
34 
35 #include <errno.h>
36 #include <string.h>
37 #include <ctype.h>
38 #include <stdlib.h>
39 #include <stdio.h>
40 #include <stdint.h>
41 #include <sys/types.h>
42 #include <sys/socket.h>
43 #include <netdb.h>
44 #include <OpenIPMI/ipmiif.h>
45 #include <OpenIPMI/ipmi_cmdlang.h>
46 #include <OpenIPMI/ipmi_pet.h>
47 #include <OpenIPMI/ipmi_lanparm.h>
48 #include <OpenIPMI/ipmi_solparm.h>
49 #include <OpenIPMI/ipmi_fru.h>
50 #include <OpenIPMI/ipmi_pef.h>
51 #include <OpenIPMI/ipmi_auth.h>
52 #include <OpenIPMI/ipmi_debug.h>
53 #include <OpenIPMI/ipmi_mc.h>
54 
55 /* Internal includes, do not use in your programs */
56 #include <OpenIPMI/internal/ipmi_locks.h>
57 #include <OpenIPMI/internal/ipmi_malloc.h>
58 
59 /*
60  * This is the value passed to a command handler.
61  */
62 struct ipmi_cmd_info_s
63 {
64     void               *handler_data; /* From cb_data in the cmd reg */
65     int                curr_arg;      /* Argument you should start at */
66     int                argc;          /* Total number of arguments */
67     char               **argv;        /* The arguments */
68 
69     /* Only allow one writer at a time */
70     ipmi_lock_t        *lock;
71 
72     /* The cmdlang structure the user passed in.  Use this for output
73        and error reporting. */
74     ipmi_cmdlang_t     *cmdlang;
75 
76     /* The matching cmd structure for the command being executed.  May
77        be NULL if no command is being processed. */
78     ipmi_cmdlang_cmd_t *cmd;
79 
80     /* Refcount for the structure. */
81     unsigned int       usecount;
82 
83     /* For use by the user commands */
84     void *data;
85 
86     /* Used to know if the command generated output. */
87     int did_output;
88 };
89 
90 
91 struct ipmi_cmdlang_cmd_s
92 {
93     char                  *name;
94     char                  *help;
95     ipmi_help_finisher_cb help_finish;
96 
97     /* Only one of handler or subcmds may be non-NULL. */
98     ipmi_cmdlang_handler_cb handler;
99     ipmi_cmdlang_cmd_t      *subcmds;
100 
101     void                    *handler_data;
102 
103     /* Used for a linked list. */
104     ipmi_cmdlang_cmd_t *next;
105 };
106 
107 static os_handler_t *cmdlang_os_hnd;
108 
109 /* Parse a string of the form [domain][(class)][.obj] and return each
110    of the strings in the given string pointers. */
111 static int
parse_ipmi_objstr(char * str,char ** domain,char ** class,char ** obj)112 parse_ipmi_objstr(char *str,
113 		  char **domain,
114 		  char **class,
115 		  char **obj)
116 {
117     int  i;
118     char *class_start = NULL, *class_end = NULL;
119 
120     for (i=0; str[i]; i++) {
121 	if (str[i] == '(') {
122 	    if (class_start)
123 		/* Only one '(' allowed. */
124 		return EINVAL;
125 	    class_start = str + i;
126 	} else if (str[i] == ')') {
127 	    if (class_start) {
128 		/* a ')' only means something after a '('. */
129 		class_end = str + i;
130 		i++;
131 		break;
132 	    }
133 	}
134     }
135 
136     if (str[i]) {
137 	if (str[i] != '.')
138 	    return EINVAL;
139     }
140 
141     if (class_start) {
142 	if (!class_end)
143 	    /* If class starts, must see the end paren. */
144 	    return EINVAL;
145 	*class_start = '\0';
146 	*class_end = '\0';
147 	*class = class_start + 1;
148     } else {
149 	*class = NULL;
150     }
151 
152     if (strlen(str) == 0)
153 	*domain = NULL;
154     else
155 	*domain = str;
156 
157     if (str[i])
158 	*obj = str + i + 1;
159     else
160 	*obj = NULL;
161 
162     return 0;
163 }
164 
165 
166 /*
167  * Handling for iterating domains.
168  */
169 
170 typedef struct domain_iter_info_s
171 {
172     char               *cmpstr;
173     ipmi_domain_ptr_cb handler;
174     void               *cb_data;
175     ipmi_cmd_info_t    *cmd_info;
176 } domain_iter_info_t;
177 
178 static void
for_each_domain_handler(ipmi_domain_t * domain,void * cb_data)179 for_each_domain_handler(ipmi_domain_t *domain, void *cb_data)
180 {
181     domain_iter_info_t *info = cb_data;
182     ipmi_cmd_info_t    *cmd_info = info->cmd_info;
183     char               domain_name[IPMI_DOMAIN_NAME_LEN];
184 
185     if (cmd_info->cmdlang->err)
186 	return;
187 
188     ipmi_domain_get_name(domain, domain_name, sizeof(domain_name));
189     if ((!info->cmpstr) || (strcmp(info->cmpstr, domain_name) == 0))
190 	info->handler(domain, info->cb_data);
191 }
192 
193 static void
for_each_domain(ipmi_cmd_info_t * cmd_info,char * domain,char * class,char * obj,ipmi_domain_ptr_cb handler,void * cb_data)194 for_each_domain(ipmi_cmd_info_t    *cmd_info,
195 		char               *domain,
196 		char               *class,
197 		char               *obj,
198 		ipmi_domain_ptr_cb handler,
199 		void               *cb_data)
200 {
201     domain_iter_info_t info;
202 
203     if (class || obj) {
204 	cmd_info->cmdlang->errstr = "Invalid domain";
205 	cmd_info->cmdlang->err = EINVAL;
206 	cmd_info->cmdlang->location = "cmdlang.c(for_each_domain)";
207 	return;
208     }
209 
210     info.cmpstr = domain;
211     info.handler = handler;
212     info.cb_data = cb_data;
213     info.cmd_info = cmd_info;
214     ipmi_domain_iterate_domains(for_each_domain_handler, &info);
215 }
216 
217 void
ipmi_cmdlang_domain_handler(ipmi_cmd_info_t * cmd_info)218 ipmi_cmdlang_domain_handler(ipmi_cmd_info_t *cmd_info)
219 {
220     char *domain, *class, *obj;
221     int  rv;
222 
223     if (cmd_info->curr_arg >= cmd_info->argc) {
224 	domain = class = obj = NULL;
225     } else {
226 	rv = parse_ipmi_objstr(cmd_info->argv[cmd_info->curr_arg],
227 			       &domain, &class, &obj);
228 	if (rv) {
229 	    cmd_info->cmdlang->errstr = "Invalid domain";
230 	    cmd_info->cmdlang->err = rv;
231 	    cmd_info->cmdlang->location
232 		= "cmdlang.c(ipmi_cmdlang_domain_handler)";
233 	    return;
234 	}
235 	cmd_info->curr_arg++;
236     }
237 
238     for_each_domain(cmd_info, domain, class, obj,
239 		    cmd_info->handler_data, cmd_info);
240 }
241 
242 
243 /*
244  * Handling for iterating PETs.
245  */
246 typedef struct pet_iter_info_s
247 {
248     char            *cmdstr;
249     ipmi_pet_ptr_cb handler;
250     void            *cb_data;
251     ipmi_cmd_info_t *cmd_info;
252 } pet_iter_info_t;
253 
254 static void
for_each_pet_handler(ipmi_pet_t * pet,void * cb_data)255 for_each_pet_handler(ipmi_pet_t *pet, void *cb_data)
256 {
257     pet_iter_info_t *info = cb_data;
258     ipmi_cmd_info_t *cmd_info = info->cmd_info;
259     ipmi_cmdlang_t  *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
260     char            name[IPMI_PET_NAME_LEN];
261     char            *c;
262 
263     if (cmdlang->err)
264 	return;
265 
266     ipmi_pet_get_name(pet, name, sizeof(name));
267 
268     c = strrchr(name, '.');
269     if (!c)
270 	goto out_err;
271     c++;
272     if ((! info->cmdstr) || (strcmp(info->cmdstr, c) == 0))
273 	info->handler(pet, info->cb_data);
274     return;
275 
276  out_err:
277     ipmi_cmdlang_global_err(name,
278 			    "cmdlang.c(for_each_pet_handler)",
279 			    "Bad PET name", EINVAL);
280 }
281 
282 static void
for_each_pet_domain_handler(ipmi_domain_t * domain,void * cb_data)283 for_each_pet_domain_handler(ipmi_domain_t *domain, void *cb_data)
284 {
285     ipmi_pet_iterate_pets(domain, for_each_pet_handler, cb_data);
286 }
287 
288 static void
for_each_pet(ipmi_cmd_info_t * cmd_info,char * domain,char * class,char * obj,ipmi_pet_ptr_cb handler,void * cb_data)289 for_each_pet(ipmi_cmd_info_t *cmd_info,
290 	     char            *domain,
291 	     char            *class,
292 	     char            *obj,
293 	     ipmi_pet_ptr_cb handler,
294 	     void            *cb_data)
295 {
296     pet_iter_info_t info;
297 
298     if (class) {
299 	cmd_info->cmdlang->errstr = "Invalid PET";
300 	cmd_info->cmdlang->err = EINVAL;
301 	cmd_info->cmdlang->location = "cmdlang.c(for_each_pet)";
302 	return;
303     }
304 
305     info.handler = handler;
306     info.cb_data = cb_data;
307     info.cmd_info = cmd_info;
308     info.cmdstr = obj;
309     for_each_domain(cmd_info, domain, NULL, NULL,
310 		    for_each_pet_domain_handler, &info);
311 }
312 
313 void
ipmi_cmdlang_pet_handler(ipmi_cmd_info_t * cmd_info)314 ipmi_cmdlang_pet_handler(ipmi_cmd_info_t *cmd_info)
315 {
316     char *domain, *class, *obj;
317 
318     if (cmd_info->curr_arg >= cmd_info->argc) {
319 	domain = class = obj = NULL;
320     } else {
321 	domain = cmd_info->argv[cmd_info->curr_arg];
322 	class = NULL;
323 	obj = strrchr(domain, '.');
324 	if (!obj) {
325 	    cmd_info->cmdlang->errstr = "Invalid PET";
326 	    cmd_info->cmdlang->err = EINVAL;
327 	    cmd_info->cmdlang->location
328 		= "cmdlang.c(ipmi_cmdlang_pet_handler)";
329 	    return;
330 	}
331 	*obj = '\0';
332 	obj++;
333 	cmd_info->curr_arg++;
334     }
335 
336     for_each_pet(cmd_info, domain, class, obj, cmd_info->handler_data,
337 		 cmd_info);
338 }
339 
340 /*
341  * Handling for iterating LANPARMs.
342  */
343 typedef struct lanparm_iter_info_s
344 {
345     char                *cmdstr;
346     ipmi_lanparm_ptr_cb handler;
347     void                *cb_data;
348     ipmi_cmd_info_t     *cmd_info;
349 } lanparm_iter_info_t;
350 
351 static void
for_each_lanparm_handler(ipmi_lanparm_t * lanparm,void * cb_data)352 for_each_lanparm_handler(ipmi_lanparm_t *lanparm, void *cb_data)
353 {
354     lanparm_iter_info_t *info = cb_data;
355     ipmi_cmd_info_t *cmd_info = info->cmd_info;
356     ipmi_cmdlang_t  *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
357     char            name[IPMI_LANPARM_NAME_LEN];
358     char            *c;
359 
360     if (cmdlang->err)
361 	return;
362 
363     ipmi_lanparm_get_name(lanparm, name, sizeof(name));
364 
365     c = strrchr(name, '.');
366     if (!c)
367 	goto out_err;
368     c++;
369     if ((! info->cmdstr) || (strcmp(info->cmdstr, c) == 0))
370 	info->handler(lanparm, info->cb_data);
371     return;
372 
373  out_err:
374     ipmi_cmdlang_global_err(name,
375 			    "cmdlang.c(for_each_lanparm_handler)",
376 			    "Bad LANPARM name", EINVAL);
377 }
378 
379 static void
for_each_lanparm_domain_handler(ipmi_domain_t * domain,void * cb_data)380 for_each_lanparm_domain_handler(ipmi_domain_t *domain, void *cb_data)
381 {
382     ipmi_lanparm_iterate_lanparms(domain, for_each_lanparm_handler, cb_data);
383 }
384 
385 static void
for_each_lanparm(ipmi_cmd_info_t * cmd_info,char * domain,char * class,char * obj,ipmi_lanparm_ptr_cb handler,void * cb_data)386 for_each_lanparm(ipmi_cmd_info_t *cmd_info,
387 	     char            *domain,
388 	     char            *class,
389 	     char            *obj,
390 	     ipmi_lanparm_ptr_cb handler,
391 	     void            *cb_data)
392 {
393     lanparm_iter_info_t info;
394 
395     if (class) {
396 	cmd_info->cmdlang->errstr = "Invalid LANPARM";
397 	cmd_info->cmdlang->err = EINVAL;
398 	cmd_info->cmdlang->location = "cmdlang.c(for_each_lanparm)";
399 	return;
400     }
401 
402     info.handler = handler;
403     info.cb_data = cb_data;
404     info.cmd_info = cmd_info;
405     info.cmdstr = obj;
406     for_each_domain(cmd_info, domain, NULL, NULL,
407 		    for_each_lanparm_domain_handler, &info);
408 }
409 
410 void
ipmi_cmdlang_lanparm_handler(ipmi_cmd_info_t * cmd_info)411 ipmi_cmdlang_lanparm_handler(ipmi_cmd_info_t *cmd_info)
412 {
413     char *domain, *class, *obj;
414 
415     if (cmd_info->curr_arg >= cmd_info->argc) {
416 	domain = class = obj = NULL;
417     } else {
418 	domain = cmd_info->argv[cmd_info->curr_arg];
419 	class = NULL;
420 	obj = strrchr(domain, '.');
421 	if (!obj) {
422 	    cmd_info->cmdlang->errstr = "Invalid LANPARM";
423 	    cmd_info->cmdlang->err = EINVAL;
424 	    cmd_info->cmdlang->location
425 		= "cmdlang.c(ipmi_cmdlang_lanparm_handler)";
426 	    return;
427 	}
428 	*obj = '\0';
429 	obj++;
430 	cmd_info->curr_arg++;
431     }
432 
433     for_each_lanparm(cmd_info, domain, class, obj, cmd_info->handler_data,
434 		 cmd_info);
435 }
436 
437 /*
438  * Handling for iterating SOLPARMs.
439  */
440 typedef struct solparm_iter_info_s
441 {
442     char                *cmdstr;
443     ipmi_solparm_ptr_cb handler;
444     void                *cb_data;
445     ipmi_cmd_info_t     *cmd_info;
446 } solparm_iter_info_t;
447 
448 static void
for_each_solparm_handler(ipmi_solparm_t * solparm,void * cb_data)449 for_each_solparm_handler(ipmi_solparm_t *solparm, void *cb_data)
450 {
451     solparm_iter_info_t *info = cb_data;
452     ipmi_cmd_info_t *cmd_info = info->cmd_info;
453     ipmi_cmdlang_t  *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
454     char            name[IPMI_SOLPARM_NAME_LEN];
455     char            *c;
456 
457     if (cmdlang->err)
458 	return;
459 
460     ipmi_solparm_get_name(solparm, name, sizeof(name));
461 
462     c = strrchr(name, '.');
463     if (!c)
464 	goto out_err;
465     c++;
466     if ((! info->cmdstr) || (strcmp(info->cmdstr, c) == 0))
467 	info->handler(solparm, info->cb_data);
468     return;
469 
470  out_err:
471     ipmi_cmdlang_global_err(name,
472 			    "cmdlang.c(for_each_solparm_handler)",
473 			    "Bad SOLPARM name", EINVAL);
474 }
475 
476 static void
for_each_solparm_domain_handler(ipmi_domain_t * domain,void * cb_data)477 for_each_solparm_domain_handler(ipmi_domain_t *domain, void *cb_data)
478 {
479     ipmi_solparm_iterate_solparms(domain, for_each_solparm_handler, cb_data);
480 }
481 
482 static void
for_each_solparm(ipmi_cmd_info_t * cmd_info,char * domain,char * class,char * obj,ipmi_solparm_ptr_cb handler,void * cb_data)483 for_each_solparm(ipmi_cmd_info_t *cmd_info,
484 	     char            *domain,
485 	     char            *class,
486 	     char            *obj,
487 	     ipmi_solparm_ptr_cb handler,
488 	     void            *cb_data)
489 {
490     solparm_iter_info_t info;
491 
492     if (class) {
493 	cmd_info->cmdlang->errstr = "Invalid SOLPARM";
494 	cmd_info->cmdlang->err = EINVAL;
495 	cmd_info->cmdlang->location = "cmdlang.c(for_each_solparm)";
496 	return;
497     }
498 
499     info.handler = handler;
500     info.cb_data = cb_data;
501     info.cmd_info = cmd_info;
502     info.cmdstr = obj;
503     for_each_domain(cmd_info, domain, NULL, NULL,
504 		    for_each_solparm_domain_handler, &info);
505 }
506 
507 void
ipmi_cmdlang_solparm_handler(ipmi_cmd_info_t * cmd_info)508 ipmi_cmdlang_solparm_handler(ipmi_cmd_info_t *cmd_info)
509 {
510     char *domain, *class, *obj;
511 
512     if (cmd_info->curr_arg >= cmd_info->argc) {
513 	domain = class = obj = NULL;
514     } else {
515 	domain = cmd_info->argv[cmd_info->curr_arg];
516 	class = NULL;
517 	obj = strrchr(domain, '.');
518 	if (!obj) {
519 	    cmd_info->cmdlang->errstr = "Invalid SOLPARM";
520 	    cmd_info->cmdlang->err = EINVAL;
521 	    cmd_info->cmdlang->location
522 		= "cmdlang.c(ipmi_cmdlang_solparm_handler)";
523 	    return;
524 	}
525 	*obj = '\0';
526 	obj++;
527 	cmd_info->curr_arg++;
528     }
529 
530     for_each_solparm(cmd_info, domain, class, obj, cmd_info->handler_data,
531 		 cmd_info);
532 }
533 
534 /*
535  * Handling for iterating PEFs.
536  */
537 typedef struct pef_iter_info_s
538 {
539     char            *cmdstr;
540     ipmi_pef_ptr_cb handler;
541     void            *cb_data;
542     ipmi_cmd_info_t *cmd_info;
543 } pef_iter_info_t;
544 
545 static void
for_each_pef_handler(ipmi_pef_t * pef,void * cb_data)546 for_each_pef_handler(ipmi_pef_t *pef, void *cb_data)
547 {
548     pef_iter_info_t *info = cb_data;
549     ipmi_cmd_info_t *cmd_info = info->cmd_info;
550     ipmi_cmdlang_t  *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
551     char            name[IPMI_PEF_NAME_LEN];
552     char            *c;
553 
554     if (cmdlang->err)
555 	return;
556 
557     ipmi_pef_get_name(pef, name, sizeof(name));
558 
559     c = strrchr(name, '.');
560     if (!c)
561 	goto out_err;
562     c++;
563     if ((! info->cmdstr) || (strcmp(info->cmdstr, c) == 0))
564 	info->handler(pef, info->cb_data);
565     return;
566 
567  out_err:
568     ipmi_cmdlang_global_err(name,
569 			    "cmdlang.c(for_each_pef_handler)",
570 			    "Bad PEF name", EINVAL);
571 }
572 
573 static void
for_each_pef_domain_handler(ipmi_domain_t * domain,void * cb_data)574 for_each_pef_domain_handler(ipmi_domain_t *domain, void *cb_data)
575 {
576     ipmi_pef_iterate_pefs(domain, for_each_pef_handler, cb_data);
577 }
578 
579 static void
for_each_pef(ipmi_cmd_info_t * cmd_info,char * domain,char * class,char * obj,ipmi_pef_ptr_cb handler,void * cb_data)580 for_each_pef(ipmi_cmd_info_t *cmd_info,
581 	     char            *domain,
582 	     char            *class,
583 	     char            *obj,
584 	     ipmi_pef_ptr_cb handler,
585 	     void            *cb_data)
586 {
587     pef_iter_info_t info;
588 
589     if (class) {
590 	cmd_info->cmdlang->errstr = "Invalid PEF";
591 	cmd_info->cmdlang->err = EINVAL;
592 	cmd_info->cmdlang->location = "cmdlang.c(for_each_pef)";
593 	return;
594     }
595 
596     info.handler = handler;
597     info.cb_data = cb_data;
598     info.cmd_info = cmd_info;
599     info.cmdstr = obj;
600     for_each_domain(cmd_info, domain, NULL, NULL,
601 		    for_each_pef_domain_handler, &info);
602 }
603 
604 void
ipmi_cmdlang_pef_handler(ipmi_cmd_info_t * cmd_info)605 ipmi_cmdlang_pef_handler(ipmi_cmd_info_t *cmd_info)
606 {
607     char *domain, *class, *obj;
608 
609     if (cmd_info->curr_arg >= cmd_info->argc) {
610 	domain = class = obj = NULL;
611     } else {
612 	domain = cmd_info->argv[cmd_info->curr_arg];
613 	class = NULL;
614 	obj = strrchr(domain, '.');
615 	if (!obj) {
616 	    cmd_info->cmdlang->errstr = "Invalid PEF";
617 	    cmd_info->cmdlang->err = EINVAL;
618 	    cmd_info->cmdlang->location
619 		= "cmdlang.c(ipmi_cmdlang_pef_handler)";
620 	    return;
621 	}
622 	*obj = '\0';
623 	obj++;
624 	cmd_info->curr_arg++;
625     }
626 
627     for_each_pef(cmd_info, domain, class, obj, cmd_info->handler_data,
628 		 cmd_info);
629 }
630 
631 
632 /*
633  * Handling for iterating FRUs.
634  */
635 typedef struct fru_iter_info_s
636 {
637     char            *cmdstr;
638     ipmi_fru_ptr_cb handler;
639     void            *cb_data;
640     ipmi_cmd_info_t *cmd_info;
641 } fru_iter_info_t;
642 
643 static void
for_each_fru_handler(ipmi_fru_t * fru,void * cb_data)644 for_each_fru_handler(ipmi_fru_t *fru, void *cb_data)
645 {
646     fru_iter_info_t *info = cb_data;
647     ipmi_cmd_info_t *cmd_info = info->cmd_info;
648     ipmi_cmdlang_t  *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
649     char            name[IPMI_FRU_NAME_LEN];
650     char            *c;
651 
652     if (cmdlang->err)
653 	return;
654 
655     ipmi_fru_get_name(fru, name, sizeof(name));
656 
657     c = strrchr(name, '.');
658     if (!c)
659 	goto out_err;
660     c++;
661     if ((! info->cmdstr) || (strcmp(info->cmdstr, c) == 0))
662 	info->handler(fru, info->cb_data);
663     return;
664 
665  out_err:
666     ipmi_cmdlang_global_err(name,
667 			    "cmdlang.c(for_each_fru_handler)",
668 			    "Bad FRU name", EINVAL);
669 }
670 
671 static void
for_each_fru_domain_handler(ipmi_domain_t * domain,void * cb_data)672 for_each_fru_domain_handler(ipmi_domain_t *domain, void *cb_data)
673 {
674     ipmi_fru_iterate_frus(domain, for_each_fru_handler, cb_data);
675 }
676 
677 static void
for_each_fru(ipmi_cmd_info_t * cmd_info,char * domain,char * class,char * obj,ipmi_fru_ptr_cb handler,void * cb_data)678 for_each_fru(ipmi_cmd_info_t *cmd_info,
679 	     char            *domain,
680 	     char            *class,
681 	     char            *obj,
682 	     ipmi_fru_ptr_cb handler,
683 	     void            *cb_data)
684 {
685     fru_iter_info_t info;
686 
687     if (class) {
688 	cmd_info->cmdlang->errstr = "Invalid FRU";
689 	cmd_info->cmdlang->err = EINVAL;
690 	cmd_info->cmdlang->location = "cmdlang.c(for_each_fru)";
691 	return;
692     }
693 
694     info.handler = handler;
695     info.cb_data = cb_data;
696     info.cmd_info = cmd_info;
697     info.cmdstr = obj;
698     for_each_domain(cmd_info, domain, NULL, NULL,
699 		    for_each_fru_domain_handler, &info);
700 }
701 
702 void
ipmi_cmdlang_fru_handler(ipmi_cmd_info_t * cmd_info)703 ipmi_cmdlang_fru_handler(ipmi_cmd_info_t *cmd_info)
704 {
705     char *domain, *class, *obj;
706 
707     if (cmd_info->curr_arg >= cmd_info->argc) {
708 	domain = class = obj = NULL;
709     } else {
710 	domain = cmd_info->argv[cmd_info->curr_arg];
711 	class = NULL;
712 	obj = strrchr(domain, '.');
713 	if (!obj) {
714 	    cmd_info->cmdlang->errstr = "Invalid FRU";
715 	    cmd_info->cmdlang->err = EINVAL;
716 	    cmd_info->cmdlang->location
717 		= "cmdlang.c(ipmi_cmdlang_fru_handler)";
718 	    return;
719 	}
720 	*obj = '\0';
721 	obj++;
722 	cmd_info->curr_arg++;
723     }
724 
725     for_each_fru(cmd_info, domain, class, obj, cmd_info->handler_data,
726 		 cmd_info);
727 }
728 
729 
730 /*
731  * Handling for iterating entities.
732  */
733 typedef struct entity_iter_info_s
734 {
735     char               *cmpstr;
736     ipmi_entity_ptr_cb handler;
737     void               *cb_data;
738     ipmi_cmd_info_t    *cmd_info;
739 } entity_iter_info_t;
740 
741 static void
for_each_entity_handler(ipmi_entity_t * entity,void * cb_data)742 for_each_entity_handler(ipmi_entity_t *entity, void *cb_data)
743 {
744     entity_iter_info_t *info = cb_data;
745     ipmi_cmd_info_t    *cmd_info = info->cmd_info;
746     char               entity_name[IPMI_ENTITY_NAME_LEN];
747     char               *c, *c2;
748 
749     if (cmd_info->cmdlang->err)
750 	return;
751 
752     ipmi_entity_get_name(entity, entity_name, sizeof(entity_name));
753     c = strchr(entity_name, '(');
754     if (!c)
755 	goto out_err;
756     c++;
757     c2 = strchr(c, ')');
758     if (!c2)
759 	goto out_err;
760     *c2 = '\0';
761     if ((!info->cmpstr) || (strcmp(info->cmpstr, c) == 0)) {
762 	*c2 = ')';
763 	info->handler(entity, info->cb_data);
764     } else
765 	*c2 = ')';
766     return;
767 
768  out_err:
769     ipmi_cmdlang_global_err(entity_name,
770 			    "cmdlang.c(for_each_entity_handler)",
771 			    "Bad entity name", EINVAL);
772 }
773 
774 static void
for_each_entity_domain_handler(ipmi_domain_t * domain,void * cb_data)775 for_each_entity_domain_handler(ipmi_domain_t *domain, void *cb_data)
776 {
777     ipmi_domain_iterate_entities(domain, for_each_entity_handler, cb_data);
778 }
779 
780 static void
for_each_entity(ipmi_cmd_info_t * cmd_info,char * domain,char * class,char * obj,ipmi_entity_ptr_cb handler,void * cb_data)781 for_each_entity(ipmi_cmd_info_t    *cmd_info,
782 		char               *domain,
783 		char               *class,
784 		char               *obj,
785 		ipmi_entity_ptr_cb handler,
786 		void               *cb_data)
787 {
788     entity_iter_info_t info;
789 
790     if (obj) {
791 	cmd_info->cmdlang->errstr = "Invalid entity";
792 	cmd_info->cmdlang->err = EINVAL;
793 	cmd_info->cmdlang->location = "cmdlang.c(for_each_entity)";
794 	return;
795     }
796 
797     info.cmpstr = class;
798     info.handler = handler;
799     info.cb_data = cb_data;
800     info.cmd_info = cmd_info;
801     for_each_domain(cmd_info, domain, NULL, NULL,
802 		    for_each_entity_domain_handler, &info);
803 }
804 
805 void
ipmi_cmdlang_entity_handler(ipmi_cmd_info_t * cmd_info)806 ipmi_cmdlang_entity_handler(ipmi_cmd_info_t *cmd_info)
807 {
808     char *domain, *class, *obj;
809     int  rv;
810 
811     if (cmd_info->curr_arg >= cmd_info->argc) {
812 	domain = class = obj = NULL;
813     } else {
814 	rv = parse_ipmi_objstr(cmd_info->argv[cmd_info->curr_arg],
815 			       &domain, &class, &obj);
816 	if (rv) {
817 	    cmd_info->cmdlang->errstr = "Invalid entity";
818 	    cmd_info->cmdlang->err = rv;
819 	    cmd_info->cmdlang->location
820 		= "cmdlang.c(ipmi_cmdlang_entity_handler)";
821 	    return;
822 	}
823 	cmd_info->curr_arg++;
824     }
825 
826     for_each_entity(cmd_info, domain, class, obj,
827 		    cmd_info->handler_data, cmd_info);
828 }
829 
830 
831 /*
832  * Handling for iterating sensors.
833  */
834 typedef struct sensor_iter_info_s
835 {
836     char               *cmpstr;
837     ipmi_sensor_ptr_cb handler;
838     void               *cb_data;
839     ipmi_cmd_info_t    *cmd_info;
840 } sensor_iter_info_t;
841 
842 static void
for_each_sensor_handler(ipmi_entity_t * entity,ipmi_sensor_t * sensor,void * cb_data)843 for_each_sensor_handler(ipmi_entity_t *entity,
844 			ipmi_sensor_t *sensor,
845 			void          *cb_data)
846 {
847     sensor_iter_info_t *info = cb_data;
848     char               sensor_name[IPMI_SENSOR_NAME_LEN];
849     char               *c;
850 
851     ipmi_sensor_get_name(sensor, sensor_name, sizeof(sensor_name));
852     c = strchr(sensor_name, '(');
853     if (!c)
854 	goto out_err;
855     c = strchr(c, ')');
856     if (!c)
857 	goto out_err;
858     c = strchr(c, '.');
859     if (!c)
860 	goto out_err;
861     c++;
862     if ((!info->cmpstr) || (strcmp(info->cmpstr, c) == 0))
863 	info->handler(sensor, info->cb_data);
864     return;
865 
866  out_err:
867     ipmi_cmdlang_global_err(sensor_name,
868 			    "cmdlang.c(for_each_sensor_handler)",
869 			    "Bad sensor name", EINVAL);
870 }
871 
872 static void
for_each_sensor_entity_handler(ipmi_entity_t * entity,void * cb_data)873 for_each_sensor_entity_handler(ipmi_entity_t *entity, void *cb_data)
874 {
875     ipmi_entity_iterate_sensors(entity, for_each_sensor_handler, cb_data);
876 }
877 
878 static void
for_each_sensor(ipmi_cmd_info_t * cmd_info,char * domain,char * class,char * obj,ipmi_sensor_ptr_cb handler,void * cb_data)879 for_each_sensor(ipmi_cmd_info_t    *cmd_info,
880 		char               *domain,
881 		char               *class,
882 		char               *obj,
883 		ipmi_sensor_ptr_cb handler,
884 		void               *cb_data)
885 {
886     sensor_iter_info_t info;
887 
888     info.cmpstr = obj;
889     info.handler = handler;
890     info.cb_data = cb_data;
891     info.cmd_info = cmd_info;
892     for_each_entity(cmd_info, domain, class, NULL,
893 		    for_each_sensor_entity_handler, &info);
894 }
895 
896 void
ipmi_cmdlang_sensor_handler(ipmi_cmd_info_t * cmd_info)897 ipmi_cmdlang_sensor_handler(ipmi_cmd_info_t *cmd_info)
898 {
899     char *domain, *class, *obj;
900     int  rv;
901 
902     if (cmd_info->curr_arg >= cmd_info->argc) {
903 	domain = class = obj = NULL;
904     } else {
905 	rv = parse_ipmi_objstr(cmd_info->argv[cmd_info->curr_arg],
906 			       &domain, &class, &obj);
907 	if (rv) {
908 	    cmd_info->cmdlang->errstr = "Invalid sensor";
909 	    cmd_info->cmdlang->err = rv;
910 	    cmd_info->cmdlang->location
911 		= "cmdlang.c(ipmi_cmdlang_sensor_handler)";
912 	    return;
913 	}
914 	cmd_info->curr_arg++;
915     }
916 
917     for_each_sensor(cmd_info, domain, class, obj,
918 		    cmd_info->handler_data, cmd_info);
919 }
920 
921 
922 /*
923  * Handling for iterating controls.
924  */
925 typedef struct control_iter_info_s
926 {
927     char                *cmpstr;
928     ipmi_control_ptr_cb handler;
929     void                *cb_data;
930     ipmi_cmd_info_t     *cmd_info;
931 } control_iter_info_t;
932 
933 static void
for_each_control_handler(ipmi_entity_t * entity,ipmi_control_t * control,void * cb_data)934 for_each_control_handler(ipmi_entity_t  *entity,
935 			 ipmi_control_t *control,
936 			 void           *cb_data)
937 {
938     control_iter_info_t *info = cb_data;
939     char                control_name[IPMI_CONTROL_NAME_LEN];
940     char               *c;
941 
942     ipmi_control_get_name(control, control_name, sizeof(control_name));
943     c = strchr(control_name, '(');
944     if (!c)
945 	goto out_err;
946     c = strchr(c, ')');
947     if (!c)
948 	goto out_err;
949     c = strchr(c, '.');
950     if (!c)
951 	goto out_err;
952     c++;
953     if ((!info->cmpstr) || (strcmp(info->cmpstr, c) == 0))
954 	info->handler(control, info->cb_data);
955     return;
956 
957  out_err:
958     ipmi_cmdlang_global_err(control_name,
959 			    "cmdlang.c(for_each_control_handler)",
960 			    "Bad control name", EINVAL);
961 }
962 
963 static void
for_each_control_entity_handler(ipmi_entity_t * entity,void * cb_data)964 for_each_control_entity_handler(ipmi_entity_t *entity, void *cb_data)
965 {
966     ipmi_entity_iterate_controls(entity, for_each_control_handler, cb_data);
967 }
968 
969 static void
for_each_control(ipmi_cmd_info_t * cmd_info,char * domain,char * class,char * obj,ipmi_control_ptr_cb handler,void * cb_data)970 for_each_control(ipmi_cmd_info_t     *cmd_info,
971 		 char                *domain,
972 		 char                *class,
973 		 char                *obj,
974 		 ipmi_control_ptr_cb handler,
975 		 void                *cb_data)
976 {
977     control_iter_info_t info;
978 
979     info.cmpstr = obj;
980     info.handler = handler;
981     info.cb_data = cb_data;
982     info.cmd_info = cmd_info;
983     for_each_entity(cmd_info, domain, class, NULL,
984 		    for_each_control_entity_handler, &info);
985 }
986 
987 void
ipmi_cmdlang_control_handler(ipmi_cmd_info_t * cmd_info)988 ipmi_cmdlang_control_handler(ipmi_cmd_info_t *cmd_info)
989 {
990     char *domain, *class, *obj;
991     int  rv;
992 
993     if (cmd_info->curr_arg >= cmd_info->argc) {
994 	domain = class = obj = NULL;
995     } else {
996 	rv = parse_ipmi_objstr(cmd_info->argv[cmd_info->curr_arg],
997 			       &domain, &class, &obj);
998 	if (rv) {
999 	    cmd_info->cmdlang->errstr = "Invalid control";
1000 	    cmd_info->cmdlang->err = rv;
1001 	    cmd_info->cmdlang->location
1002 		= "cmdlang.c(ipmi_cmdlang_control_handler)";
1003 	    return;
1004 	}
1005 	cmd_info->curr_arg++;
1006     }
1007 
1008     for_each_control(cmd_info, domain, class, obj,
1009 		     cmd_info->handler_data, cmd_info);
1010 }
1011 
1012 
1013 /*
1014  * Handling for iterating mcs.
1015  */
1016 typedef struct mc_iter_info_s
1017 {
1018     char            *cmpstr;
1019     ipmi_mc_ptr_cb  handler;
1020     void            *cb_data;
1021     ipmi_cmd_info_t *cmd_info;
1022 } mc_iter_info_t;
1023 
1024 static void
for_each_mc_handler(ipmi_domain_t * domain,ipmi_mc_t * mc,void * cb_data)1025 for_each_mc_handler(ipmi_domain_t *domain, ipmi_mc_t *mc, void *cb_data)
1026 {
1027     mc_iter_info_t  *info = cb_data;
1028     char            mc_name[IPMI_MC_NAME_LEN];
1029     char            *c, *c2;
1030 
1031     ipmi_mc_get_name(mc, mc_name, sizeof(mc_name));
1032     c = strchr(mc_name, '(');
1033     if (!c)
1034 	goto out_err;
1035     c++;
1036     c2 = strchr(c, ')');
1037     if (!c2)
1038 	goto out_err;
1039     *c2 = '\0';
1040     if ((!info->cmpstr) || (strcmp(info->cmpstr, c) == 0)) {
1041 	*c2 = ')';
1042 	info->handler(mc, info->cb_data);
1043     } else
1044 	*c2 = ')';
1045     return;
1046 
1047  out_err:
1048     ipmi_cmdlang_global_err(mc_name,
1049 			    "cmdlang.c(for_each_entity_handler)",
1050 			    "Bad mc name", EINVAL);
1051 }
1052 
1053 static void
for_each_mc_domain_handler(ipmi_domain_t * domain,void * cb_data)1054 for_each_mc_domain_handler(ipmi_domain_t *domain, void *cb_data)
1055 {
1056     ipmi_domain_iterate_mcs(domain, for_each_mc_handler, cb_data);
1057 }
1058 
1059 static void
for_each_mc(ipmi_cmd_info_t * cmd_info,char * domain,char * class,char * obj,ipmi_mc_ptr_cb handler,void * cb_data)1060 for_each_mc(ipmi_cmd_info_t *cmd_info,
1061 	    char            *domain,
1062 	    char            *class,
1063 	    char            *obj,
1064 	    ipmi_mc_ptr_cb  handler,
1065 	    void            *cb_data)
1066 {
1067     mc_iter_info_t info;
1068 
1069     if (obj) {
1070 	cmd_info->cmdlang->errstr = "Invalid MC";
1071 	cmd_info->cmdlang->err = EINVAL;
1072 	cmd_info->cmdlang->location = "cmdlang.c(for_each_mc)";
1073 	return;
1074     }
1075 
1076     info.cmpstr = class;
1077     info.handler = handler;
1078     info.cb_data = cb_data;
1079     info.cmd_info = cmd_info;
1080     for_each_domain(cmd_info, domain, NULL, NULL,
1081 		    for_each_mc_domain_handler, &info);
1082 }
1083 
1084 void
ipmi_cmdlang_mc_handler(ipmi_cmd_info_t * cmd_info)1085 ipmi_cmdlang_mc_handler(ipmi_cmd_info_t *cmd_info)
1086 {
1087     char *domain, *class, *obj;
1088     int  rv;
1089 
1090     if (cmd_info->curr_arg >= cmd_info->argc) {
1091 	domain = class = obj = NULL;
1092     } else {
1093 	rv = parse_ipmi_objstr(cmd_info->argv[cmd_info->curr_arg],
1094 			       &domain, &class, &obj);
1095 	if (rv) {
1096 	    cmd_info->cmdlang->errstr = "Invalid MC";
1097 	    cmd_info->cmdlang->err = rv;
1098 	    cmd_info->cmdlang->location
1099 		= "cmdlang.c(ipmi_cmdlang_mc_handler)";
1100 	    return;
1101 	}
1102 	cmd_info->curr_arg++;
1103     }
1104 
1105     for_each_mc(cmd_info, domain, class, obj, cmd_info->handler_data,
1106 		cmd_info);
1107 }
1108 
1109 
1110 /*
1111  * Handling for iterating connections.
1112  */
1113 typedef struct conn_iter_info_s
1114 {
1115     int                    conn;
1116     ipmi_connection_ptr_cb handler;
1117     void                   *cb_data;
1118     ipmi_cmd_info_t        *cmd_info;
1119 } conn_iter_info_t;
1120 
1121 static void
for_each_conn_handler(ipmi_domain_t * domain,int conn,void * cb_data)1122 for_each_conn_handler(ipmi_domain_t *domain, int conn, void *cb_data)
1123 {
1124     conn_iter_info_t *info = cb_data;
1125 
1126     if ((info->conn == -1) || (info->conn == conn))
1127 	info->handler(domain, conn, info->cb_data);
1128 }
1129 
1130 static void
for_each_conn_domain_handler(ipmi_domain_t * domain,void * cb_data)1131 for_each_conn_domain_handler(ipmi_domain_t *domain, void *cb_data)
1132 {
1133     ipmi_domain_iterate_connections(domain, for_each_conn_handler, cb_data);
1134 }
1135 
1136 static void
for_each_connection(ipmi_cmd_info_t * cmd_info,char * domain,char * class,char * obj,ipmi_connection_ptr_cb handler,void * cb_data)1137 for_each_connection(ipmi_cmd_info_t        *cmd_info,
1138 		    char                   *domain,
1139 		    char                   *class,
1140 		    char                   *obj,
1141 		    ipmi_connection_ptr_cb handler,
1142 		    void                   *cb_data)
1143 {
1144     conn_iter_info_t info;
1145     char             *endptr;
1146 
1147     if (class) {
1148 	cmd_info->cmdlang->errstr = "Invalid connection";
1149 	cmd_info->cmdlang->err = EINVAL;
1150 	cmd_info->cmdlang->location = "cmdlang.c(for_each_connection)";
1151 	return;
1152     }
1153 
1154     if (obj) {
1155 	if (!isdigit(obj[0])) {
1156 	    cmd_info->cmdlang->errstr = "Invalid connection number";
1157 	    cmd_info->cmdlang->err = EINVAL;
1158 	    cmd_info->cmdlang->location = "cmdlang.c(for_each_connection)";
1159 	    return;
1160 	}
1161 	info.conn = strtoul(obj, &endptr, 0);
1162 	if (*endptr != '\0') {
1163 	    cmd_info->cmdlang->errstr = "Invalid connection number";
1164 	    cmd_info->cmdlang->err = EINVAL;
1165 	    cmd_info->cmdlang->location = "cmdlang.c(for_each_connection)";
1166 	    return;
1167 	}
1168     } else {
1169 	info.conn = -1;
1170     }
1171     info.handler = handler;
1172     info.cb_data = cb_data;
1173     info.cmd_info = cmd_info;
1174     for_each_domain(cmd_info, domain, NULL, NULL,
1175 		    for_each_conn_domain_handler, &info);
1176 }
1177 
1178 void
ipmi_cmdlang_connection_handler(ipmi_cmd_info_t * cmd_info)1179 ipmi_cmdlang_connection_handler(ipmi_cmd_info_t *cmd_info)
1180 {
1181     char *domain, *class, *obj;
1182 
1183     if (cmd_info->curr_arg >= cmd_info->argc) {
1184 	domain = class = obj = NULL;
1185     } else {
1186 	domain = cmd_info->argv[cmd_info->curr_arg];
1187 	class = NULL;
1188 	obj = strrchr(domain, '.');
1189 	if (!obj) {
1190 	    cmd_info->cmdlang->errstr = "Invalid connection";
1191 	    cmd_info->cmdlang->err = EINVAL;
1192 	    cmd_info->cmdlang->location
1193 		= "cmdlang.c(ipmi_cmdlang_connection_handler)";
1194 	    return;
1195 	}
1196 	*obj = '\0';
1197 	obj++;
1198 	cmd_info->curr_arg++;
1199     }
1200 
1201     for_each_connection(cmd_info,
1202 			domain, class, obj, cmd_info->handler_data,
1203 			cmd_info);
1204 }
1205 
1206 
1207 static int
parse_next_str(char ** tok,char ** istr)1208 parse_next_str(char **tok, char **istr)
1209 {
1210     char *str = *istr;
1211     char *tstr;
1212     char *start;
1213     char quote = 0;
1214 
1215     while (isspace(*str))
1216 	str++;
1217     if (!*str)
1218 	return ENOENT;
1219 
1220     if ((*str == '"') || (*str == '\'')) {
1221 	quote = *str;
1222 	str++;
1223     }
1224 
1225     start = str;
1226 
1227     while (*str) {
1228 	if (quote) {
1229 	    if (*str == quote)
1230 		break;
1231 	} else {
1232 	    if (isspace(*str))
1233 		break;
1234 	}
1235 
1236 	if (*str == '\\') {
1237 	    tstr = str;
1238 	    if (! *(tstr+1))
1239 		/* Nothing after a '\' */
1240 		return EINVAL;
1241 	    while (*(tstr+1)) {
1242 		*tstr = *(tstr+1);
1243 		tstr++;
1244 	    }
1245 	}
1246 	str++;
1247     }
1248 
1249     if (*str) {
1250 	*str = '\0';
1251 	*istr = str+1;
1252     } else {
1253 	*istr = str;
1254     }
1255     *tok = start;
1256 
1257     return 0;
1258 }
1259 
1260 static ipmi_cmdlang_cmd_t *cmd_list;
1261 
1262 #define MAXARGS 100
1263 void
ipmi_cmdlang_handle(ipmi_cmdlang_t * cmdlang,char * str)1264 ipmi_cmdlang_handle(ipmi_cmdlang_t *cmdlang, char *str)
1265 {
1266     int                argc;
1267     char               *argv[MAXARGS];
1268     int                curr_arg;
1269     ipmi_cmdlang_cmd_t *cmd;
1270     ipmi_cmd_info_t    *info;
1271     int                rv;
1272 
1273     if (*str == '#') {
1274 	/* A comment */
1275 	cmdlang->done(cmdlang);
1276 	return;
1277     }
1278 
1279     info = ipmi_mem_alloc(sizeof(*info));
1280     if (!info) {
1281 	cmdlang->errstr = "Out of memory";
1282 	cmdlang->err = ENOMEM;
1283 	cmdlang->location = "cmdlang.c(ipmi_cmdlang_handle)";
1284 	cmdlang->done(cmdlang);
1285 	return;
1286     }
1287     memset(info, 0, sizeof(*info));
1288     info->usecount = 1;
1289     info->cmdlang = cmdlang;
1290     rv = ipmi_create_lock_os_hnd(cmdlang->os_hnd, &info->lock);
1291     if (rv) {
1292 	cmdlang->errstr = "Could not allocate lock";
1293 	cmdlang->err = rv;
1294 	cmdlang->location = "cmdlang.c(ipmi_cmdlang_handle)";
1295 	goto done;
1296     }
1297 
1298     for (argc=0; argc<MAXARGS; argc++) {
1299 	rv = parse_next_str(&argv[argc], &str);
1300 	if (rv) {
1301 	    if (rv == ENOENT)
1302 		break;
1303 	    cmdlang->errstr = "Invalid string";
1304 	    cmdlang->err = rv;
1305 	    cmdlang->location = "cmdlang.c(ipmi_cmdlang_handle)";
1306 	    goto done;
1307 	}
1308     }
1309 
1310     if (*str) {
1311 	/* Too many arguments */
1312 	cmdlang->errstr = "Too many arguments";
1313 	cmdlang->err = E2BIG;
1314 	cmdlang->location = "cmdlang.c(ipmi_cmdlang_handle)";
1315 	goto done;
1316     }
1317 
1318     curr_arg = 0;
1319     rv = 0;
1320     cmd = cmd_list;
1321 
1322     if (argc == curr_arg) {
1323 	cmdlang->errstr = "No command";
1324 	cmdlang->err = ENOMSG;
1325 	cmdlang->location = "cmdlang.c(ipmi_cmdlang_handle)";
1326 	goto done;
1327     }
1328     if (strcmp(argv[curr_arg], "help") == 0) {
1329 	ipmi_cmdlang_cmd_t *parent = NULL;
1330 	int                old_help = cmdlang->help;
1331 	/* Help has special handling. */
1332 
1333 	cmdlang->help = 1;
1334 	curr_arg++;
1335 	for (;;) {
1336 	next_help:
1337 	    if (argc == curr_arg) {
1338 		rv = 0;
1339 		if (parent) {
1340 		    cmdlang->out(cmdlang, parent->name, parent->help);
1341 		    if (parent->help_finish)
1342 			parent->help_finish(cmdlang);
1343 		}else
1344 		    cmdlang->out(cmdlang, "help", NULL);
1345 		if (cmdlang->err)
1346 		    goto done_help;
1347 		cmdlang->down(cmdlang);
1348 		while (cmd) {
1349 		    cmdlang->out(cmdlang, cmd->name, cmd->help);
1350 		    if (cmdlang->err) {
1351 			cmdlang->up(cmdlang);
1352 			goto done_help;
1353 		    }
1354 		    if (cmd->help_finish)
1355 			cmd->help_finish(cmdlang);
1356 		    cmd = cmd->next;
1357 		}
1358 		cmdlang->up(cmdlang);
1359 		break;
1360 	    }
1361 	    if (!cmd) {
1362 		cmdlang->errstr = "Command not found";
1363 		cmdlang->err = ENOSYS;
1364 		cmdlang->location = "cmdlang.c(ipmi_cmdlang_handle)";
1365 		goto done_help;
1366 	    }
1367 
1368 	    while (cmd) {
1369 		if (strcmp(cmd->name, argv[curr_arg]) == 0) {
1370 		    curr_arg++;
1371 		    parent = cmd;
1372 		    cmd = cmd->subcmds;
1373 		    goto next_help;
1374 		}
1375 		cmd = cmd->next;
1376 	    }
1377 
1378 	    cmdlang->errstr = "Command not found";
1379 	    cmdlang->err = ENOSYS;
1380 	    cmdlang->location = "cmdlang.c(ipmi_cmdlang_handle)";
1381 	    goto done_help;
1382 	}
1383 
1384     done_help:
1385 	info->did_output = 1;
1386 	cmdlang->help = old_help;
1387 	goto done;
1388     }
1389 
1390     for (;;) {
1391 	if (argc == curr_arg) {
1392 	    cmdlang->errstr = "Missing command";
1393 	    cmdlang->err = ENOMSG;
1394 	    cmdlang->location = "cmdlang.c(ipmi_cmdlang_handle)";
1395 	    goto done;
1396 	}
1397 
1398 	while (cmd) {
1399 	    if (strcmp(cmd->name, argv[curr_arg]) == 0) {
1400 		if (cmd->subcmds) {
1401 		    cmd = cmd->subcmds;
1402 		    curr_arg++;
1403 		    /* Continue processing this subcommand list */
1404 		    break;
1405 		} else {
1406 		    curr_arg++;
1407 		    info->handler_data = cmd->handler_data;
1408 		    info->curr_arg = curr_arg;
1409 		    info->argc = argc;
1410 		    info->argv = argv;
1411 		    info->cmd = cmd;
1412 		    cmd->handler(info);
1413 		    goto done;
1414 		}
1415 	    }
1416 	    cmd = cmd->next;
1417 	}
1418 
1419 	if (!cmd) {
1420 	    cmdlang->errstr = "Command not found";
1421 	    cmdlang->err = ENOSYS;
1422 	    cmdlang->location = "cmdlang.c(ipmi_cmdlang_handle)";
1423 	    goto done;
1424 	}
1425     }
1426 
1427  done:
1428     ipmi_cmdlang_cmd_info_put(info);
1429 }
1430 
1431 int
ipmi_cmdlang_reg_cmd(ipmi_cmdlang_cmd_t * parent,char * name,char * help,ipmi_cmdlang_handler_cb handler,void * cb_data,ipmi_help_finisher_cb help_finish,ipmi_cmdlang_cmd_t ** new_val)1432 ipmi_cmdlang_reg_cmd(ipmi_cmdlang_cmd_t      *parent,
1433 		     char                    *name,
1434 		     char                    *help,
1435 		     ipmi_cmdlang_handler_cb handler,
1436 		     void                    *cb_data,
1437 		     ipmi_help_finisher_cb   help_finish,
1438 		     ipmi_cmdlang_cmd_t      **new_val)
1439 {
1440     ipmi_cmdlang_cmd_t *rv;
1441     ipmi_cmdlang_cmd_t *cmd;
1442 
1443     /* Check for dups. */
1444     if (!parent)
1445 	cmd = cmd_list;
1446     else
1447 	cmd = parent;
1448     while (cmd) {
1449 	if (strcmp(cmd->name, name) == 0)
1450 	    return EEXIST;
1451 	cmd = cmd->next;
1452     }
1453 
1454     rv = ipmi_mem_alloc(sizeof(*rv));
1455     if (!rv)
1456 	return ENOMEM;
1457 
1458     rv->name = name;
1459     rv->help = help;
1460     rv->handler = handler;
1461     rv->subcmds = NULL;
1462     rv->handler_data = cb_data;
1463     rv->help_finish = help_finish;
1464     rv->next = NULL;
1465 
1466     if (parent) {
1467 	if (!parent->subcmds) {
1468 	    parent->subcmds = rv;
1469 	    goto done;
1470 	}
1471 	cmd = parent->subcmds;
1472     } else {
1473 	if (!cmd_list) {
1474 	    cmd_list = rv;
1475 	    goto done;
1476 	}
1477 	cmd = cmd_list;
1478     }
1479     while (cmd->next) {
1480 	cmd = cmd->next;
1481     }
1482     cmd->next = rv;
1483 
1484  done:
1485     if (new_val)
1486 	*new_val = rv;
1487     return 0;
1488 }
1489 
1490 int
ipmi_cmdlang_reg_table(ipmi_cmdlang_init_t * table,int len)1491 ipmi_cmdlang_reg_table(ipmi_cmdlang_init_t *table, int len)
1492 {
1493     int                i;
1494     int                rv;
1495     ipmi_cmdlang_cmd_t *parent = NULL;
1496 
1497     for (i=0; i<len; i++) {
1498 	if (table[i].parent)
1499 	    parent = *table[i].parent;
1500 	rv = ipmi_cmdlang_reg_cmd(parent,
1501 				  table[i].name,
1502 				  table[i].help,
1503 				  table[i].handler,
1504 				  table[i].cb_data,
1505 				  table[i].help_finish,
1506 				  table[i].new_val);
1507 	if (rv)
1508 	    return rv;
1509     }
1510 
1511     return 0;
1512 }
1513 
1514 void
ipmi_cmdlang_lock(ipmi_cmd_info_t * info)1515 ipmi_cmdlang_lock(ipmi_cmd_info_t *info)
1516 {
1517     ipmi_lock(info->lock);
1518 }
1519 
1520 void
ipmi_cmdlang_unlock(ipmi_cmd_info_t * info)1521 ipmi_cmdlang_unlock(ipmi_cmd_info_t *info)
1522 {
1523     ipmi_unlock(info->lock);
1524 }
1525 
1526 void
ipmi_cmdlang_out(ipmi_cmd_info_t * info,const char * name,const char * value)1527 ipmi_cmdlang_out(ipmi_cmd_info_t *info,
1528 		 const char      *name,
1529 		 const char      *value)
1530 {
1531     info->did_output = 1;
1532     info->cmdlang->out(info->cmdlang, name, value);
1533 }
1534 
1535 void
ipmi_cmdlang_out_int(ipmi_cmd_info_t * info,const char * name,int value)1536 ipmi_cmdlang_out_int(ipmi_cmd_info_t *info,
1537 		     const char      *name,
1538 		     int             value)
1539 {
1540     char sval[20];
1541 
1542     sprintf(sval, "%d", value);
1543     ipmi_cmdlang_out(info, name, sval);
1544 }
1545 
1546 void
ipmi_cmdlang_out_double(ipmi_cmd_info_t * info,const char * name,double value)1547 ipmi_cmdlang_out_double(ipmi_cmd_info_t *info,
1548 			const char      *name,
1549 			double          value)
1550 {
1551     char sval[80];
1552 
1553     sprintf(sval, "%e", value);
1554     ipmi_cmdlang_out(info, name, sval);
1555 }
1556 
1557 void
ipmi_cmdlang_out_hex(ipmi_cmd_info_t * info,const char * name,int value)1558 ipmi_cmdlang_out_hex(ipmi_cmd_info_t *info,
1559 		     const char      *name,
1560 		     int             value)
1561 {
1562     char sval[20];
1563 
1564     sprintf(sval, "0x%x", value);
1565     ipmi_cmdlang_out(info, name, sval);
1566 }
1567 
1568 void
ipmi_cmdlang_out_long(ipmi_cmd_info_t * info,const char * name,long value)1569 ipmi_cmdlang_out_long(ipmi_cmd_info_t *info,
1570 		      const char      *name,
1571 		      long            value)
1572 {
1573     char sval[32];
1574 
1575     sprintf(sval, "%ld", value);
1576     ipmi_cmdlang_out(info, name, sval);
1577 }
1578 
1579 void
ipmi_cmdlang_out_binary(ipmi_cmd_info_t * info,const char * name,const char * value,unsigned int len)1580 ipmi_cmdlang_out_binary(ipmi_cmd_info_t *info,
1581 			const char      *name,
1582 			const char      *value,
1583 			unsigned int    len)
1584 {
1585     info->did_output = 1;
1586     info->cmdlang->out_binary(info->cmdlang, name, value, len);
1587 }
1588 
1589 void
ipmi_cmdlang_out_unicode(ipmi_cmd_info_t * info,const char * name,const char * value,unsigned int len)1590 ipmi_cmdlang_out_unicode(ipmi_cmd_info_t *info,
1591 			 const char      *name,
1592 			 const char      *value,
1593 			 unsigned int    len)
1594 {
1595     info->did_output = 1;
1596     info->cmdlang->out_unicode(info->cmdlang, name, value, len);
1597 }
1598 
1599 void
ipmi_cmdlang_out_type(ipmi_cmd_info_t * info,char * name,enum ipmi_str_type_e type,const char * value,unsigned int len)1600 ipmi_cmdlang_out_type(ipmi_cmd_info_t      *info,
1601 		      char                 *name,
1602 		      enum ipmi_str_type_e type,
1603 		      const char           *value,
1604 		      unsigned int         len)
1605 {
1606     switch(type) {
1607     case IPMI_ASCII_STR:
1608 	ipmi_cmdlang_out(info, name, value);
1609 	break;
1610     case IPMI_UNICODE_STR:
1611 	ipmi_cmdlang_out_unicode(info, name, value, len);
1612 	break;
1613     case IPMI_BINARY_STR:
1614 	ipmi_cmdlang_out_binary(info, name, value, len);
1615 	break;
1616     }
1617 }
1618 
1619 void
ipmi_cmdlang_out_bool(ipmi_cmd_info_t * info,const char * name,int value)1620 ipmi_cmdlang_out_bool(ipmi_cmd_info_t *info,
1621 		      const char      *name,
1622 		      int             value)
1623 {
1624     if (value)
1625 	ipmi_cmdlang_out(info, name, "true");
1626     else
1627 	ipmi_cmdlang_out(info, name, "false");
1628 }
1629 
1630 void
ipmi_cmdlang_out_time(ipmi_cmd_info_t * info,const char * name,ipmi_time_t value)1631 ipmi_cmdlang_out_time(ipmi_cmd_info_t *info,
1632 		      const char      *name,
1633 		      ipmi_time_t     value)
1634 {
1635     char sval[40];
1636 
1637     sprintf(sval, "%lld", (long long) value);
1638     ipmi_cmdlang_out(info, name, sval);
1639 }
1640 
1641 void
ipmi_cmdlang_out_timeout(ipmi_cmd_info_t * info,const char * name,ipmi_timeout_t value)1642 ipmi_cmdlang_out_timeout(ipmi_cmd_info_t *info,
1643 			 const char      *name,
1644 			 ipmi_timeout_t  value)
1645 {
1646     char sval[40];
1647 
1648     sprintf(sval, "%lld", (long long) value);
1649     ipmi_cmdlang_out(info, name, sval);
1650 }
1651 
1652 void
ipmi_cmdlang_out_ip(ipmi_cmd_info_t * info,const char * name,struct in_addr * ip_addr)1653 ipmi_cmdlang_out_ip(ipmi_cmd_info_t *info,
1654 		    const char      *name,
1655 		    struct in_addr  *ip_addr)
1656 {
1657     char outstr[16];
1658     uint32_t addr = ntohl(ip_addr->s_addr);
1659 
1660     /* Why isn't there an inet_ntoa_r? */
1661     sprintf(outstr, "%d.%d.%d.%d",
1662 	    (addr >> 24) & 0xff,
1663 	    (addr >> 16) & 0xff,
1664 	    (addr >> 8) & 0xff,
1665 	    (addr >> 0) & 0xff);
1666     ipmi_cmdlang_out(info, name, outstr);
1667 }
1668 
1669 void
ipmi_cmdlang_out_mac(ipmi_cmd_info_t * info,const char * name,unsigned char mac_addr[6])1670 ipmi_cmdlang_out_mac(ipmi_cmd_info_t *info,
1671 		     const char      *name,
1672 		     unsigned char   mac_addr[6])
1673 {
1674     char outstr[18];
1675 
1676     /* Why isn't there a standard ether_ntoa_r? */
1677     sprintf(outstr, "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
1678 	    mac_addr[0],
1679 	    mac_addr[1],
1680 	    mac_addr[2],
1681 	    mac_addr[3],
1682 	    mac_addr[4],
1683 	    mac_addr[5]);
1684     ipmi_cmdlang_out(info, name, outstr);
1685 }
1686 
1687 void
ipmi_cmdlang_down(ipmi_cmd_info_t * info)1688 ipmi_cmdlang_down(ipmi_cmd_info_t *info)
1689 {
1690     info->cmdlang->down(info->cmdlang);
1691 }
1692 
1693 void
ipmi_cmdlang_up(ipmi_cmd_info_t * info)1694 ipmi_cmdlang_up(ipmi_cmd_info_t *info)
1695 {
1696     info->cmdlang->up(info->cmdlang);
1697 }
1698 
1699 void
ipmi_cmdlang_cmd_info_get(ipmi_cmd_info_t * cmd_info)1700 ipmi_cmdlang_cmd_info_get(ipmi_cmd_info_t *cmd_info)
1701 {
1702     ipmi_cmdlang_lock(cmd_info);
1703     cmd_info->usecount++;
1704     ipmi_cmdlang_unlock(cmd_info);
1705 }
1706 
1707 void
ipmi_cmdlang_cmd_info_put(ipmi_cmd_info_t * cmd_info)1708 ipmi_cmdlang_cmd_info_put(ipmi_cmd_info_t *cmd_info)
1709 {
1710     ipmi_cmdlang_lock(cmd_info);
1711     cmd_info->usecount--;
1712     if (cmd_info->usecount == 0) {
1713 	if ((!cmd_info->cmdlang->err) && (!cmd_info->did_output)) {
1714 	    cmd_info->cmdlang->errstr = "Specified object not found";
1715 	    cmd_info->cmdlang->err = EINVAL;
1716 	    cmd_info->cmdlang->location = "cmdlang.c(ipmi_cmdlang_handle)";
1717 	}
1718 
1719 	cmd_info->cmdlang->done(cmd_info->cmdlang);
1720 	ipmi_cmdlang_unlock(cmd_info);
1721 	if (cmd_info->lock)
1722 	    ipmi_destroy_lock(cmd_info->lock);
1723 	ipmi_mem_free(cmd_info);
1724     } else
1725 	ipmi_cmdlang_unlock(cmd_info);
1726 }
1727 
1728 void
ipmi_cmdlang_get_int(char * str,int * val,ipmi_cmd_info_t * info)1729 ipmi_cmdlang_get_int(char *str, int *val, ipmi_cmd_info_t *info)
1730 {
1731     char *end;
1732     int  rv;
1733 
1734     if (info->cmdlang->err)
1735 	return;
1736 
1737     rv = strtoul(str, &end, 0);
1738     if (*end != '\0') {
1739 	info->cmdlang->errstr = "Invalid integer";
1740 	info->cmdlang->err = EINVAL;
1741 	info->cmdlang->location = "cmdlang.c(ipmi_cmdlang_get_int)";
1742 	return;
1743     }
1744 
1745     *val = rv;
1746 }
1747 
1748 void
ipmi_cmdlang_get_time(char * str,ipmi_time_t * val,ipmi_cmd_info_t * info)1749 ipmi_cmdlang_get_time(char *str, ipmi_time_t *val, ipmi_cmd_info_t *info)
1750 {
1751     char        *end;
1752     ipmi_time_t rv;
1753 
1754     if (info->cmdlang->err)
1755 	return;
1756 
1757     rv = strtoull(str, &end, 0);
1758     if (*end != '\0') {
1759 	info->cmdlang->errstr = "Invalid integer";
1760 	info->cmdlang->err = EINVAL;
1761 	info->cmdlang->location = "cmdlang.c(ipmi_cmdlang_get_int)";
1762 	return;
1763     }
1764 
1765     *val = rv;
1766 }
1767 
1768 void
ipmi_cmdlang_get_timeout(char * str,ipmi_timeout_t * val,ipmi_cmd_info_t * info)1769 ipmi_cmdlang_get_timeout(char *str, ipmi_timeout_t *val,
1770 			 ipmi_cmd_info_t *info)
1771 {
1772     char           *end;
1773     ipmi_timeout_t rv;
1774 
1775     if (info->cmdlang->err)
1776 	return;
1777 
1778     rv = strtoull(str, &end, 0);
1779     if (*end != '\0') {
1780 	info->cmdlang->errstr = "Invalid integer";
1781 	info->cmdlang->err = EINVAL;
1782 	info->cmdlang->location = "cmdlang.c(ipmi_cmdlang_get_int)";
1783 	return;
1784     }
1785 
1786     *val = rv;
1787 }
1788 
1789 void
ipmi_cmdlang_get_double(char * str,double * val,ipmi_cmd_info_t * info)1790 ipmi_cmdlang_get_double(char *str, double *val, ipmi_cmd_info_t *info)
1791 {
1792     char   *end;
1793     double rv;
1794 
1795     if (info->cmdlang->err)
1796 	return;
1797 
1798     rv = strtod(str, &end);
1799     if (*end != '\0') {
1800 	info->cmdlang->errstr = "Invalid double";
1801 	info->cmdlang->err = EINVAL;
1802 	info->cmdlang->location = "cmdlang.c(ipmi_cmdlang_get_double)";
1803 	return;
1804     }
1805 
1806     *val = rv;
1807 }
1808 
1809 void
ipmi_cmdlang_get_uchar(char * str,unsigned char * val,ipmi_cmd_info_t * info)1810 ipmi_cmdlang_get_uchar(char *str, unsigned char *val, ipmi_cmd_info_t *info)
1811 {
1812     char *end;
1813     int  rv;
1814 
1815     if (info->cmdlang->err)
1816 	return;
1817 
1818     rv = strtoul(str, &end, 0);
1819     if (*end != '\0') {
1820 	info->cmdlang->errstr = "Invalid integer";
1821 	info->cmdlang->err = EINVAL;
1822 	info->cmdlang->location = "cmdlang.c(ipmi_cmdlang_get_uchar)";
1823 	return;
1824     }
1825 
1826     *val = rv;
1827 }
1828 
1829 void
ipmi_cmdlang_get_bool(char * str,int * val,ipmi_cmd_info_t * info)1830 ipmi_cmdlang_get_bool(char *str, int *val, ipmi_cmd_info_t *info)
1831 {
1832     int  rv;
1833 
1834     if (info->cmdlang->err)
1835 	return;
1836 
1837     if ((strcasecmp(str, "true") == 0)
1838 	|| (strcasecmp(str, "on") == 0)
1839 	|| (strcasecmp(str, "t") == 0)
1840 	|| (strcmp(str, "1") == 0))
1841     {
1842 	rv = 1;
1843     } else if ((strcasecmp(str, "false") == 0)
1844 	       || (strcasecmp(str, "off") == 0)
1845 	       || (strcasecmp(str, "f") == 0)
1846 	       || (strcmp(str, "0") == 0))
1847     {
1848 	rv = 0;
1849     } else {
1850 	info->cmdlang->errstr = "Invalid boolean";
1851 	info->cmdlang->err = EINVAL;
1852 	info->cmdlang->location = "cmdlang.c(ipmi_cmdlang_get_bool)";
1853 	return;
1854     }
1855 
1856     *val = rv;
1857 }
1858 
1859 void
ipmi_cmdlang_get_user(char * str,int * val,ipmi_cmd_info_t * info)1860 ipmi_cmdlang_get_user(char *str, int *val, ipmi_cmd_info_t *info)
1861 {
1862     char *end;
1863     int  rv;
1864 
1865     if (info->cmdlang->err)
1866 	return;
1867 
1868     rv = strtoul(str, &end, 0);
1869     if (*end != '\0')
1870 	goto not_int;
1871 
1872     *val = rv;
1873     return;
1874 
1875  not_int:
1876     if (strcmp(str, "callback") == 0)
1877 	*val = IPMI_PRIVILEGE_CALLBACK;
1878     else if (strcmp(str, "user") == 0)
1879 	*val = IPMI_PRIVILEGE_USER;
1880     else if (strcmp(str, "operator") == 0)
1881 	*val = IPMI_PRIVILEGE_OPERATOR;
1882     else if (strcmp(str, "admin") == 0)
1883 	*val = IPMI_PRIVILEGE_ADMIN;
1884     else if (strcmp(str, "oem") == 0)
1885 	*val = IPMI_PRIVILEGE_OEM;
1886     else {
1887 	info->cmdlang->errstr = "Invalid privilege level";
1888 	info->cmdlang->err = EINVAL;
1889 	info->cmdlang->location = "cmdlang.c(ipmi_cmdlang_get_user)";
1890     }
1891 }
1892 
1893 void
ipmi_cmdlang_get_ip(char * str,struct in_addr * val,ipmi_cmd_info_t * info)1894 ipmi_cmdlang_get_ip(char *str, struct in_addr *val, ipmi_cmd_info_t *info)
1895 {
1896 #ifdef HAVE_GETADDRINFO
1897     struct addrinfo    hints, *res0;
1898     int                rv;
1899     struct sockaddr_in *paddr;
1900 
1901     if (info->cmdlang->err)
1902 	return;
1903 
1904     memset(&hints, 0, sizeof(hints));
1905     hints.ai_family = PF_INET;
1906     hints.ai_socktype = SOCK_DGRAM;
1907     rv = getaddrinfo(str, 0, &hints, &res0);
1908     if (rv == 0) {
1909 	/* Only get the first choice */
1910 	paddr = (struct sockaddr_in *) res0->ai_addr;
1911 	*val = paddr->sin_addr;
1912 	freeaddrinfo(res0);
1913     } else
1914 	info->cmdlang->err = rv;
1915 #else
1916     /* System does not support getaddrinfo, just for IPv4*/
1917     struct hostent     *ent;
1918     struct sockaddr_in *paddr;
1919 
1920     if (info->cmdlang->err)
1921 	return;
1922 
1923     ent = gethostbyname(str);
1924     if (!ent) {
1925 	info->cmdlang->err = EINVAL;
1926     } else {
1927 	paddr = (struct sockaddr_in *) &ent->h_addr_list[0];
1928 	*val = paddr->sin_addr;
1929 	memcpy(val, ent->h_addr_list[0], ent->h_length);
1930     }
1931 #endif
1932 }
1933 
1934 void
ipmi_cmdlang_get_mac(char * str,unsigned char val[6],ipmi_cmd_info_t * info)1935 ipmi_cmdlang_get_mac(char *str, unsigned char val[6], ipmi_cmd_info_t *info)
1936 {
1937     char          tmp[3];
1938     char          *tv;
1939     int           len;
1940     unsigned char tmp_val[6];
1941     int           i;
1942     char          *end;
1943 
1944     if (info->cmdlang->err)
1945 	return;
1946 
1947     for (i=0; i<6; i++) {
1948 	if (i == 5)
1949 	    tv = str + strlen(str);
1950 	else
1951 	    tv = strchr(str, ':');
1952 	if (!tv) {
1953 	    info->cmdlang->err = EINVAL;
1954 	    goto out;
1955 	}
1956 	len = tv-str;
1957 	if (len > 2) {
1958 	    info->cmdlang->err = EINVAL;
1959 	    goto out;
1960 	}
1961 	memset(tmp, 0, sizeof(tmp));
1962 	memcpy(tmp, str, len);
1963 	tmp_val[i] = strtoul(tmp, &end, 16);
1964 	if (*end != '\0') {
1965 	    info->cmdlang->err = EINVAL;
1966 	    goto out;
1967 	}
1968 	str = tv+1;
1969     }
1970 
1971     memcpy(val, tmp_val, sizeof(tmp_val));
1972     return;
1973 
1974  out:
1975     return;
1976 }
1977 
1978 void
ipmi_cmdlang_get_color(char * str,int * val,ipmi_cmd_info_t * info)1979 ipmi_cmdlang_get_color(char *str, int *val, ipmi_cmd_info_t *info)
1980 {
1981     int i;
1982 
1983     for (i=IPMI_CONTROL_COLOR_BLACK; i<IPMI_CONTROL_COLOR_ORANGE; i++){
1984 	if (strcmp(str, ipmi_get_color_string(i)) == 0) {
1985 	    *val = i;
1986 	    return;
1987 	}
1988     }
1989 
1990     info->cmdlang->errstr = "Invalid color";
1991     info->cmdlang->err = EINVAL;
1992     info->cmdlang->location = "cmdlang.c(ipmi_cmdlang_get_color)";
1993 }
1994 
1995 static int
issep(char val)1996 issep(char val)
1997 {
1998     return ((val == ' ')
1999 	    || (val == '\t')
2000 	    || (val == '\n')
2001 	    || (val == '\r'));
2002 }
2003 
2004 void
ipmi_cmdlang_get_threshold_ev(char * str,enum ipmi_thresh_e * rthresh,enum ipmi_event_value_dir_e * rvalue_dir,enum ipmi_event_dir_e * rdir,ipmi_cmd_info_t * info)2005 ipmi_cmdlang_get_threshold_ev(char                        *str,
2006 			      enum ipmi_thresh_e          *rthresh,
2007 			      enum ipmi_event_value_dir_e *rvalue_dir,
2008 			      enum ipmi_event_dir_e       *rdir,
2009 			      ipmi_cmd_info_t             *info)
2010 {
2011     enum ipmi_thresh_e          thresh;
2012     enum ipmi_event_value_dir_e value_dir;
2013     enum ipmi_event_dir_e       dir;
2014     char                        val[4][20];
2015     int                         len;
2016     int                         vc;
2017 
2018 
2019     vc = 0;
2020     for (;;) {
2021 	char *start, *end;
2022 
2023 	while (issep(*str))
2024 	    str++;
2025 	if (! *str)
2026 	    break;
2027 
2028 	if (vc == 4)
2029 	    goto out_err;
2030 
2031 	start = str;
2032 	while (*str && (!issep(*str)))
2033 	    str++;
2034 	end = str;
2035 	len = end - start;
2036 	if (len >= 20)
2037 	    goto out_err;
2038 
2039 	memcpy(val[vc], start, len);
2040 	val[vc][len] = '\0';
2041 	vc++;
2042     }
2043 
2044     if (vc == 1) {
2045 	/* One value, it is a compressed form. */
2046 	if (strlen(val[0]) != 4)
2047 	    goto out_err;
2048 
2049 	if ((val[0][0] == 'u') || (val[0][0] == 'U')) {
2050 	    if ((val[0][1] == 'n') || (val[0][1] == 'N'))
2051 		thresh = IPMI_UPPER_NON_CRITICAL;
2052 	    else if ((val[0][1] == 'c') || (val[0][1] == 'C'))
2053 		thresh = IPMI_UPPER_CRITICAL;
2054 	    else if ((val[0][1] == 'f') || (val[0][1] == 'F'))
2055 		thresh = IPMI_UPPER_NON_RECOVERABLE;
2056 	    else if ((val[0][1] == 'r') || (val[0][1] == 'R'))
2057 		thresh = IPMI_UPPER_NON_RECOVERABLE;
2058 	    else
2059 		goto out_err;
2060 	} else if ((val[0][0] == 'l') || (val[0][0] == 'L')) {
2061 	    if ((val[0][1] == 'n') || (val[0][1] == 'N'))
2062 		thresh = IPMI_LOWER_NON_CRITICAL;
2063 	    else if ((val[0][1] == 'c') || (val[0][1] == 'C'))
2064 		thresh = IPMI_LOWER_CRITICAL;
2065 	    else if ((val[0][1] == 'f') || (val[0][1] == 'F'))
2066 		thresh = IPMI_LOWER_NON_RECOVERABLE;
2067 	    else if ((val[0][1] == 'r') || (val[0][1] == 'R'))
2068 		thresh = IPMI_LOWER_NON_RECOVERABLE;
2069 	    else
2070 		goto out_err;
2071 	} else
2072 	    goto out_err;
2073 
2074 	if ((val[0][2] == 'h') || (val[0][2] == 'H'))
2075 	    value_dir = IPMI_GOING_HIGH;
2076 	else if ((val[0][2] == 'l') || (val[0][2] == 'L'))
2077 	    value_dir = IPMI_GOING_LOW;
2078 	else
2079 	    goto out_err;
2080 
2081 	if ((val[0][3] == 'a') || (val[0][2] == 'A'))
2082 	    dir = IPMI_ASSERTION;
2083 	else if ((val[0][3] == 'd') || (val[0][3] == 'D'))
2084 	    dir = IPMI_DEASSERTION;
2085 	else
2086 	    goto out_err;
2087     } else if (vc == 4) {
2088 	/* Four values, uncompressed form */
2089 	if (strcasecmp(val[0], "upper") == 0) {
2090 	    if (strcasecmp(val[1], "non-critical") == 0)
2091 		thresh = IPMI_UPPER_NON_CRITICAL;
2092 	    else if (strcasecmp(val[1], "critical") == 0)
2093 		thresh = IPMI_UPPER_CRITICAL;
2094 	    else if (strcasecmp(val[1], "non-recoverable") == 0)
2095 		thresh = IPMI_UPPER_NON_RECOVERABLE;
2096 	    else
2097 		goto out_err;
2098 	} else if (strcasecmp(val[0], "lower") == 0) {
2099 	    if (strcasecmp(val[1], "non-critical") == 0)
2100 		thresh = IPMI_LOWER_NON_CRITICAL;
2101 	    else if (strcasecmp(val[1], "critical") == 0)
2102 		thresh = IPMI_LOWER_CRITICAL;
2103 	    else if (strcasecmp(val[1], "non-recoverable") == 0)
2104 		thresh = IPMI_LOWER_NON_RECOVERABLE;
2105 	    else
2106 		goto out_err;
2107 	} else
2108 	    goto out_err;
2109 
2110 	if (strcasecmp(val[2], "going-high") == 0)
2111 	    value_dir = IPMI_GOING_HIGH;
2112 	else if (strcasecmp(val[2], "going-low") == 0)
2113 	    value_dir = IPMI_GOING_LOW;
2114 	else
2115 	    goto out_err;
2116 
2117 	if (strcasecmp(val[3], "assertion") == 0)
2118 	    dir = IPMI_ASSERTION;
2119 	else if (strcasecmp(val[3], "deassertion") == 0)
2120 	    dir = IPMI_DEASSERTION;
2121 	else
2122 	    goto out_err;
2123     } else
2124 	goto out_err;
2125     if (rdir)
2126 	*rdir = dir;
2127     if (rvalue_dir)
2128 	*rvalue_dir = value_dir;
2129     if (rthresh)
2130 	*rthresh = thresh;
2131     return;
2132 
2133  out_err:
2134     info->cmdlang->errstr = "Invalid threshold event";
2135     info->cmdlang->err = EINVAL;
2136     info->cmdlang->location = "cmdlang.c(ipmi_cmdlang_get_threshold_ev)";
2137 }
2138 
2139 void
ipmi_cmdlang_get_threshold(char * str,enum ipmi_thresh_e * rthresh,ipmi_cmd_info_t * info)2140 ipmi_cmdlang_get_threshold(char               *str,
2141 			   enum ipmi_thresh_e *rthresh,
2142 			   ipmi_cmd_info_t    *info)
2143 {
2144     enum ipmi_thresh_e thresh;
2145 
2146     for (thresh = IPMI_LOWER_NON_CRITICAL;
2147 	 thresh <= IPMI_UPPER_NON_RECOVERABLE;
2148 	 thresh++)
2149     {
2150 	if (strcmp(str, ipmi_get_threshold_string(thresh)) == 0) {
2151 	    if (rthresh)
2152 		*rthresh = thresh;
2153 	    return;
2154 	}
2155     }
2156     if (strcasecmp(str, "un") == 0)
2157 	thresh = IPMI_UPPER_NON_CRITICAL;
2158     else if (strcasecmp(str, "uc") == 0)
2159 	thresh = IPMI_UPPER_CRITICAL;
2160     else if (strcasecmp(str, "ur") == 0)
2161 	thresh = IPMI_UPPER_NON_RECOVERABLE;
2162     else if (strcasecmp(str, "ln") == 0)
2163 	thresh = IPMI_LOWER_NON_CRITICAL;
2164     else if (strcasecmp(str, "lc") == 0)
2165 	thresh = IPMI_LOWER_CRITICAL;
2166     else if (strcasecmp(str, "lr") == 0)
2167 	thresh = IPMI_LOWER_NON_RECOVERABLE;
2168     else
2169 	goto out_err;
2170 
2171     if (rthresh)
2172 	*rthresh = thresh;
2173     return;
2174 
2175  out_err:
2176     info->cmdlang->errstr = "Invalid threshold";
2177     info->cmdlang->err = EINVAL;
2178     info->cmdlang->location = "cmdlang.c(ipmi_cmdlang_get_threshold)";
2179 }
2180 
2181 void
ipmi_cmdlang_get_discrete_ev(char * str,int * roffset,enum ipmi_event_dir_e * rdir,ipmi_cmd_info_t * info)2182 ipmi_cmdlang_get_discrete_ev(char                  *str,
2183 			     int                   *roffset,
2184 			     enum ipmi_event_dir_e *rdir,
2185 			     ipmi_cmd_info_t       *info)
2186 {
2187     int                   offset;
2188     enum ipmi_event_dir_e dir;
2189     char                  val[4][20];
2190     int                   len;
2191     int                   vc;
2192     char                  *end;
2193 
2194 
2195     vc = 0;
2196     for (;;) {
2197 	char *start, *end;
2198 
2199 	while (issep(*str))
2200 	    str++;
2201 	if (! *str)
2202 	    break;
2203 
2204 	if (vc == 4)
2205 	    goto out_err;
2206 
2207 	start = str;
2208 	while (*str && (!issep(*str)))
2209 	    str++;
2210 	end = str;
2211 	len = end - start;
2212 	if (len >= 20)
2213 	    goto out_err;
2214 
2215 	memcpy(val[vc], start, len);
2216 	val[vc][len] = '\0';
2217 	vc++;
2218     }
2219 
2220     if (vc == 1) {
2221 	/* One value, it is a compressed form. */
2222 
2223 	offset = strtoul(val[0], &end, 0);
2224 	if (end == val[0])
2225 	    goto out_err;
2226 	if ((*end == 'd') || (*end == 'D'))
2227 	    dir = IPMI_DEASSERTION;
2228 	else if ((*end == 'a') || (*end == 'A'))
2229 	    dir = IPMI_ASSERTION;
2230 	else
2231 	    goto out_err;
2232 	end++;
2233 	if (*end != '\0')
2234 	    goto out_err;
2235     } else if (vc == 2) {
2236 	offset = strtoul(val[0], &end, 0);
2237 	if ((end == val[0]) || (*end != '\0'))
2238 	    goto out_err;
2239 	if (strcasecmp(val[1], "deassertion")  == 0)
2240 	    dir = IPMI_DEASSERTION;
2241 	else if (strcasecmp(val[1], "assertion")  == 0)
2242 	    dir = IPMI_ASSERTION;
2243 	else
2244 	    goto out_err;
2245     } else
2246 	goto out_err;
2247 
2248     if (roffset)
2249 	*roffset = offset;
2250     if (rdir)
2251 	*rdir = dir;
2252     return;
2253 
2254  out_err:
2255     info->cmdlang->errstr = "Invalid discrete event";
2256     info->cmdlang->err = EINVAL;
2257     info->cmdlang->location = "cmdlang.c(ipmi_cmdlang_get_discrete_event)";
2258 }
2259 
2260 typedef struct ipmi_cmdlang_event_entry_s ipmi_cmdlang_event_entry_t;
2261 struct ipmi_cmdlang_event_entry_s
2262 {
2263     char *name;
2264     enum ipmi_cmdlang_out_types type;
2265     char *value;
2266     unsigned int len;
2267     int  level;
2268     ipmi_cmdlang_event_entry_t *next;
2269 };
2270 
2271 struct ipmi_cmdlang_event_s
2272 {
2273     int curr_level;
2274     ipmi_cmd_info_t *info;
2275     ipmi_cmdlang_event_entry_t *head, *tail;
2276     ipmi_cmdlang_event_entry_t *curr;
2277 };
2278 
2279 void
event_out(ipmi_cmdlang_t * cmdlang,const char * name,const char * value)2280 event_out(ipmi_cmdlang_t *cmdlang, const char *name, const char *value)
2281 {
2282     ipmi_cmdlang_event_entry_t *entry;
2283     ipmi_cmdlang_event_t       *event = cmdlang->user_data;
2284 
2285     if (cmdlang->err)
2286 	return;
2287 
2288     entry = ipmi_mem_alloc(sizeof(*entry));
2289     if (!entry)
2290 	goto out_nomem;
2291 
2292     entry->name = ipmi_strdup(name);
2293     if (!entry->name) {
2294 	ipmi_mem_free(entry);
2295 	goto out_nomem;
2296     }
2297 
2298     entry->type = IPMI_CMDLANG_STRING;
2299 
2300     if (value) {
2301 	entry->len = strlen(value);
2302 	entry->value = ipmi_strdup(value);
2303 	if (!entry->value) {
2304 	    ipmi_mem_free(entry->name);
2305 	    ipmi_mem_free(entry);
2306 	    goto out_nomem;
2307 	}
2308     } else {
2309 	entry->len = 0;
2310 	entry->value = NULL;
2311     }
2312 
2313     entry->level = event->curr_level;
2314 
2315     entry->next = NULL;
2316     if (event->head) {
2317 	event->tail->next = entry;
2318 	event->tail = entry;
2319     } else {
2320 	event->head = entry;
2321 	event->tail = entry;
2322     }
2323 
2324     return;
2325 
2326  out_nomem:
2327     cmdlang->err = ENOMEM;
2328     cmdlang->errstr = "Out of memory";
2329     cmdlang->location = "cmdlang.c(event_out)";
2330 }
2331 
2332 static void
event_out_binary(ipmi_cmdlang_t * cmdlang,const char * name,const char * value,unsigned int len)2333 event_out_binary(ipmi_cmdlang_t *cmdlang, const char *name,
2334 		 const char *value, unsigned int len)
2335 {
2336     ipmi_cmdlang_event_entry_t *entry;
2337     ipmi_cmdlang_event_t       *event = cmdlang->user_data;
2338 
2339     if (cmdlang->err)
2340 	return;
2341 
2342     entry = ipmi_mem_alloc(sizeof(*entry));
2343     if (!entry)
2344 	goto out_nomem;
2345 
2346     entry->name = ipmi_strdup(name);
2347     if (!entry->name) {
2348 	ipmi_mem_free(entry);
2349 	goto out_nomem;
2350     }
2351 
2352     entry->type = IPMI_CMDLANG_BINARY;
2353 
2354     entry->len = len;
2355     if (len > 0) {
2356 	entry->value = ipmi_mem_alloc(len);
2357 	if (!entry->value) {
2358 	    ipmi_mem_free(entry->name);
2359 	    ipmi_mem_free(entry);
2360 	    goto out_nomem;
2361 	}
2362 	memcpy(entry->value, value, len);
2363     } else
2364 	entry->value = NULL;
2365 
2366     entry->level = event->curr_level;
2367 
2368     entry->next = NULL;
2369     if (event->head) {
2370 	event->tail->next = entry;
2371 	event->tail = entry;
2372     } else {
2373 	event->head = entry;
2374 	event->tail = entry;
2375     }
2376 
2377     return;
2378 
2379  out_nomem:
2380     cmdlang->err = ENOMEM;
2381     cmdlang->errstr = "Out of memory";
2382     cmdlang->location = "cmdlang.c(event_out_binary)";
2383 }
2384 
2385 static void
event_out_unicode(ipmi_cmdlang_t * cmdlang,const char * name,const char * value,unsigned int len)2386 event_out_unicode(ipmi_cmdlang_t *cmdlang, const char *name,
2387 		  const char *value, unsigned int len)
2388 {
2389     ipmi_cmdlang_event_entry_t *entry;
2390     ipmi_cmdlang_event_t       *event = cmdlang->user_data;
2391 
2392     if (cmdlang->err)
2393 	return;
2394 
2395     entry = ipmi_mem_alloc(sizeof(*entry));
2396     if (!entry)
2397 	goto out_nomem;
2398 
2399     entry->name = ipmi_strdup(name);
2400     if (!entry->name) {
2401 	ipmi_mem_free(entry);
2402 	goto out_nomem;
2403     }
2404 
2405     entry->type = IPMI_CMDLANG_UNICODE;
2406 
2407     entry->len = len;
2408     if (len > 0) {
2409 	entry->value = ipmi_mem_alloc(len);
2410 	if (!entry->value) {
2411 	    ipmi_mem_free(entry->name);
2412 	    ipmi_mem_free(entry);
2413 	    goto out_nomem;
2414 	}
2415 	memcpy(entry->value, value, len);
2416     } else
2417 	entry->value = NULL;
2418 
2419     entry->level = event->curr_level;
2420 
2421     entry->next = NULL;
2422     if (event->head) {
2423 	event->tail->next = entry;
2424 	event->tail = entry;
2425     } else {
2426 	event->head = entry;
2427 	event->tail = entry;
2428     }
2429 
2430     return;
2431 
2432  out_nomem:
2433     cmdlang->err = ENOMEM;
2434     cmdlang->errstr = "Out of memory";
2435     cmdlang->location = "cmdlang.c(event_out_binary)";
2436 }
2437 
2438 void
event_up(ipmi_cmdlang_t * cmdlang)2439 event_up(ipmi_cmdlang_t *cmdlang)
2440 {
2441     ipmi_cmdlang_event_t *event = cmdlang->user_data;
2442 
2443     if (cmdlang->err)
2444 	return;
2445 
2446     event->curr_level--;
2447 }
2448 
2449 void
event_down(ipmi_cmdlang_t * cmdlang)2450 event_down(ipmi_cmdlang_t *cmdlang)
2451 {
2452     ipmi_cmdlang_event_t *event = cmdlang->user_data;
2453 
2454     if (cmdlang->err)
2455 	return;
2456 
2457     event->curr_level++;
2458 }
2459 
2460 void
event_done(ipmi_cmdlang_t * cmdlang)2461 event_done(ipmi_cmdlang_t *cmdlang)
2462 {
2463     ipmi_cmdlang_event_entry_t *entry;
2464     ipmi_cmdlang_event_t       *event = cmdlang->user_data;
2465     ipmi_cmd_info_t            *info = event->info;
2466 
2467     if (strlen(info->cmdlang->objstr) == 0) {
2468 	ipmi_mem_free(info->cmdlang->objstr);
2469 	cmdlang->objstr = NULL;
2470     }
2471 
2472     if (info->cmdlang->err) {
2473 	ipmi_cmdlang_global_err(cmdlang->objstr,
2474 				cmdlang->location,
2475 				cmdlang->errstr,
2476 				cmdlang->err);
2477 	if (cmdlang->errstr_dynalloc)
2478 	    ipmi_mem_free(cmdlang->errstr);
2479     } else {
2480 	ipmi_cmdlang_report_event(event);
2481     }
2482 
2483     if (cmdlang->objstr)
2484 	ipmi_mem_free(cmdlang->objstr);
2485     ipmi_mem_free(cmdlang);
2486 
2487     entry = event->head;
2488     while (entry) {
2489 	event->head = entry->next;
2490 	ipmi_mem_free(entry->name);
2491 	if (entry->value)
2492 	    ipmi_mem_free(entry->value);
2493 	ipmi_mem_free(entry);
2494 	entry = event->head;
2495     }
2496     ipmi_mem_free(event);
2497 }
2498 
2499 ipmi_cmd_info_t *
ipmi_cmdlang_alloc_event_info(void)2500 ipmi_cmdlang_alloc_event_info(void)
2501 {
2502     ipmi_cmd_info_t      *cmdinfo = NULL;
2503     ipmi_cmdlang_event_t *event;
2504     int                  rv;
2505 
2506     cmdinfo = ipmi_mem_alloc(sizeof(*cmdinfo));
2507     if (!cmdinfo)
2508 	return NULL;
2509     memset(cmdinfo, 0, sizeof(*cmdinfo));
2510     cmdinfo->usecount = 1;
2511 
2512     rv = ipmi_create_lock_os_hnd(cmdlang_os_hnd, &cmdinfo->lock);
2513     if (rv) {
2514 	ipmi_mem_free(cmdinfo);
2515 	return NULL;
2516     }
2517 
2518     cmdinfo->cmdlang = ipmi_mem_alloc(sizeof(*cmdinfo->cmdlang));
2519     if (!cmdinfo->cmdlang) {
2520 	ipmi_destroy_lock(cmdinfo->lock);
2521 	ipmi_mem_free(cmdinfo);
2522 	return NULL;
2523     }
2524     memset(cmdinfo->cmdlang, 0, sizeof(*cmdinfo->cmdlang));
2525 
2526     cmdinfo->cmdlang->objstr = ipmi_mem_alloc(IPMI_MAX_NAME_LEN);
2527     if (!cmdinfo->cmdlang->objstr) {
2528 	ipmi_mem_free(cmdinfo->cmdlang);
2529 	ipmi_destroy_lock(cmdinfo->lock);
2530 	ipmi_mem_free(cmdinfo);
2531 	return NULL;
2532     }
2533     cmdinfo->cmdlang->objstr[0] = '\0';
2534     cmdinfo->cmdlang->objstr_len = IPMI_MAX_NAME_LEN;
2535 
2536     cmdinfo->cmdlang->user_data	= ipmi_mem_alloc(sizeof(ipmi_cmdlang_event_t));
2537     if (!cmdinfo->cmdlang->user_data) {
2538 	ipmi_mem_free(cmdinfo->cmdlang->objstr);
2539 	ipmi_mem_free(cmdinfo->cmdlang);
2540 	ipmi_destroy_lock(cmdinfo->lock);
2541 	ipmi_mem_free(cmdinfo);
2542 	return NULL;
2543     }
2544 
2545     event = cmdinfo->cmdlang->user_data;
2546     memset(event, 0, sizeof(*event));
2547     event->info = cmdinfo;
2548 
2549     cmdinfo->cmdlang->out = event_out;
2550     cmdinfo->cmdlang->down = event_down;
2551     cmdinfo->cmdlang->out_binary = event_out_binary;
2552     cmdinfo->cmdlang->out_unicode = event_out_unicode;
2553     cmdinfo->cmdlang->up = event_up;
2554     cmdinfo->cmdlang->done = event_done;
2555 
2556     return cmdinfo;
2557 }
2558 
2559 /* Move to the first field. */
2560 void
ipmi_cmdlang_event_restart(ipmi_cmdlang_event_t * event)2561 ipmi_cmdlang_event_restart(ipmi_cmdlang_event_t *event)
2562 {
2563     event->curr = event->head;
2564 }
2565 
2566 /* Returns true if successful, false if no more fields left. */
2567 int
ipmi_cmdlang_event_next_field(ipmi_cmdlang_event_t * event,unsigned int * level,enum ipmi_cmdlang_out_types * type,char ** name,unsigned int * len,char ** value)2568 ipmi_cmdlang_event_next_field(ipmi_cmdlang_event_t        *event,
2569 			      unsigned int                *level,
2570 			      enum ipmi_cmdlang_out_types *type,
2571 			      char                        **name,
2572 			      unsigned int                *len,
2573 			      char                        **value)
2574 {
2575     ipmi_cmdlang_event_entry_t *curr = event->curr;
2576 
2577     if (!curr)
2578 	return 0;
2579 
2580     if (level)
2581 	*level = curr->level;
2582     if (name)
2583 	*name = curr->name;
2584     if (value)
2585 	*value = curr->value;
2586     if (type)
2587 	*type = curr->type;
2588     if (len)
2589 	*len = curr->len;
2590 
2591     event->curr = curr->next;
2592     return 1;
2593 }
2594 
2595 int
ipmi_cmdlang_get_argc(ipmi_cmd_info_t * info)2596 ipmi_cmdlang_get_argc(ipmi_cmd_info_t *info)
2597 {
2598     return info->argc;
2599 }
2600 
2601 char **
ipmi_cmdlang_get_argv(ipmi_cmd_info_t * info)2602 ipmi_cmdlang_get_argv(ipmi_cmd_info_t *info)
2603 {
2604     return info->argv;
2605 }
2606 
2607 int
ipmi_cmdlang_get_curr_arg(ipmi_cmd_info_t * info)2608 ipmi_cmdlang_get_curr_arg(ipmi_cmd_info_t *info)
2609 {
2610     return info->curr_arg;
2611 }
2612 
2613 ipmi_cmdlang_t *
ipmi_cmdinfo_get_cmdlang(ipmi_cmd_info_t * info)2614 ipmi_cmdinfo_get_cmdlang(ipmi_cmd_info_t *info)
2615 {
2616     return info->cmdlang;
2617 }
2618 
2619 static void
evinfo(ipmi_cmd_info_t * cmd_info)2620 evinfo(ipmi_cmd_info_t *cmd_info)
2621 {
2622     ipmi_cmdlang_t *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
2623     int            curr_arg = ipmi_cmdlang_get_curr_arg(cmd_info);
2624     int            argc = ipmi_cmdlang_get_argc(cmd_info);
2625     char           **argv = ipmi_cmdlang_get_argv(cmd_info);
2626     int            do_evinfo;
2627 
2628     if ((argc - curr_arg) < 1) {
2629 	cmdlang->errstr = "True or False not entered";
2630 	cmdlang->err = EINVAL;
2631 	goto out_err;
2632     }
2633 
2634     ipmi_cmdlang_get_bool(argv[curr_arg], &do_evinfo, cmd_info);
2635     if (cmdlang->err) {
2636 	cmdlang->errstr = "True or False not entered";
2637 	cmdlang->err = EINVAL;
2638 	goto out_err;
2639     }
2640 
2641     ipmi_cmdlang_set_evinfo(do_evinfo);
2642     ipmi_cmdlang_out(cmd_info, "event info set", NULL);
2643     return;
2644 
2645  out_err:
2646     cmdlang->location = "cmdlang.c(evinfo)";
2647 }
2648 
2649 static void
debug(ipmi_cmd_info_t * cmd_info)2650 debug(ipmi_cmd_info_t *cmd_info)
2651 {
2652     ipmi_cmdlang_t *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
2653     int            curr_arg = ipmi_cmdlang_get_curr_arg(cmd_info);
2654     int            argc = ipmi_cmdlang_get_argc(cmd_info);
2655     char           **argv = ipmi_cmdlang_get_argv(cmd_info);
2656     char           *type;
2657     int            val;
2658 
2659     if ((argc - curr_arg) < 2) {
2660 	cmdlang->errstr = "Not enough parameters";
2661 	cmdlang->err = EINVAL;
2662 	goto out_err;
2663     }
2664 
2665     type = argv[curr_arg];
2666     curr_arg++;
2667 
2668     ipmi_cmdlang_get_bool(argv[curr_arg], &val, cmd_info);
2669     if (cmdlang->err) {
2670 	cmdlang->errstr = "Invalid boolean setting";
2671 	cmdlang->err = EINVAL;
2672 	goto out_err;
2673     }
2674 
2675     if (strcmp(type, "msg") == 0) {
2676 	if (val) DEBUG_MSG_ENABLE(); else DEBUG_MSG_DISABLE();
2677     } else if (strcmp(type, "msgerr") == 0) {
2678 	if (val) DEBUG_MSG_ERR_ENABLE(); else DEBUG_MSG_ERR_DISABLE();
2679     } else if (strcmp(type, "rawmsg") == 0) {
2680 	if (val) DEBUG_RAWMSG_ENABLE(); else DEBUG_RAWMSG_DISABLE();
2681     } else if (strcmp(type, "locks") == 0) {
2682 	if (val) DEBUG_LOCKS_ENABLE(); else DEBUG_LOCKS_DISABLE();
2683     } else if (strcmp(type, "events") == 0) {
2684 	if (val) DEBUG_EVENTS_ENABLE(); else DEBUG_EVENTS_DISABLE();
2685     } else if (strcmp(type, "con0") == 0) {
2686 	if (val) DEBUG_CON_FAIL_ENABLE(0); else DEBUG_CON_FAIL_DISABLE(0);
2687     } else if (strcmp(type, "con1") == 0) {
2688 	if (val) DEBUG_CON_FAIL_ENABLE(1); else DEBUG_CON_FAIL_DISABLE(1);
2689     } else if (strcmp(type, "con2") == 0) {
2690 	if (val) DEBUG_CON_FAIL_ENABLE(2); else DEBUG_CON_FAIL_DISABLE(2);
2691     } else if (strcmp(type, "con3") == 0) {
2692 	if (val) DEBUG_CON_FAIL_ENABLE(3); else DEBUG_CON_FAIL_DISABLE(3);
2693     } else {
2694 	cmdlang->errstr = "Invalid debug setting";
2695 	cmdlang->err = EINVAL;
2696 	goto out_err;
2697     }
2698 
2699     ipmi_cmdlang_out(cmd_info, "Debugging set", NULL);
2700     return;
2701 
2702  out_err:
2703     if (cmdlang->err)
2704 	cmdlang->location = "cmdlang.c(debug)";
2705 }
2706 
2707 static ipmi_cmdlang_init_t cmds_global[] =
2708 {
2709     { "evinfo", NULL,
2710       "true | false - Enable/disable printing info about the object"
2711       " when an event is reported on it (such as entity info, domain"
2712       " info, etc.)",
2713       evinfo, NULL, NULL },
2714     { "debug", NULL,
2715       "<type> true | false - "
2716       " Turn on/off the specific debugging.  The debugging types are:"
2717       " msg, rawmsg, events, con0, con1, con2, con3.  This is primarily"
2718       " for designers of OpenIPMI trying to debug problems.",
2719       debug, NULL, NULL },
2720 };
2721 #define CMDS_GLOBAL_LEN (sizeof(cmds_global)/sizeof(ipmi_cmdlang_init_t))
2722 
2723 int ipmi_cmdlang_domain_init(os_handler_t *os_hnd);
2724 int ipmi_cmdlang_con_init(os_handler_t *os_hnd);
2725 int ipmi_cmdlang_entity_init(os_handler_t *os_hnd);
2726 int ipmi_cmdlang_mc_init(os_handler_t *os_hnd);
2727 int ipmi_cmdlang_pet_init(os_handler_t *os_hnd);
2728 int ipmi_cmdlang_lanparm_init(os_handler_t *os_hnd);
2729 int ipmi_cmdlang_solparm_init(os_handler_t *os_hnd);
2730 int ipmi_cmdlang_fru_init(os_handler_t *os_hnd);
2731 void ipmi_cmdlang_lanparm_shutdown();
2732 void ipmi_cmdlang_solparm_shutdown();
2733 int ipmi_cmdlang_pef_init(os_handler_t *os_hnd);
2734 void ipmi_cmdlang_pef_shutdown();
2735 int ipmi_cmdlang_sensor_init(os_handler_t *os_hnd);
2736 int ipmi_cmdlang_control_init(os_handler_t *os_hnd);
2737 int ipmi_cmdlang_sel_init(os_handler_t *os_hnd);
2738 
2739 int
ipmi_cmdlang_init(os_handler_t * os_hnd)2740 ipmi_cmdlang_init(os_handler_t *os_hnd)
2741 {
2742     int rv;
2743 
2744     rv = ipmi_cmdlang_domain_init(os_hnd);
2745     if (rv) return rv;
2746 
2747     rv = ipmi_cmdlang_con_init(os_hnd);
2748     if (rv) return rv;
2749 
2750     rv = ipmi_cmdlang_entity_init(os_hnd);
2751     if (rv) return rv;
2752 
2753     rv = ipmi_cmdlang_mc_init(os_hnd);
2754     if (rv) return rv;
2755 
2756     rv = ipmi_cmdlang_pet_init(os_hnd);
2757     if (rv) return rv;
2758 
2759     rv = ipmi_cmdlang_lanparm_init(os_hnd);
2760     if (rv) return rv;
2761 
2762     rv = ipmi_cmdlang_solparm_init(os_hnd);
2763     if (rv) return rv;
2764 
2765     rv = ipmi_cmdlang_fru_init(os_hnd);
2766     if (rv) return rv;
2767 
2768     rv = ipmi_cmdlang_pef_init(os_hnd);
2769     if (rv) return rv;
2770 
2771     rv = ipmi_cmdlang_sensor_init(os_hnd);
2772     if (rv) return rv;
2773 
2774     rv = ipmi_cmdlang_control_init(os_hnd);
2775     if (rv) return rv;
2776 
2777     rv = ipmi_cmdlang_sel_init(os_hnd);
2778     if (rv) return rv;
2779 
2780     rv = ipmi_cmdlang_reg_table(cmds_global, CMDS_GLOBAL_LEN);
2781     if (rv) return rv;
2782 
2783     return 0;
2784 }
2785 
2786 static void
cleanup_level(ipmi_cmdlang_cmd_t * cmds)2787 cleanup_level(ipmi_cmdlang_cmd_t *cmds)
2788 {
2789     ipmi_cmdlang_cmd_t *cmd;
2790 
2791     while (cmds) {
2792 	cmd = cmds;
2793 	cmds = cmd->next;
2794 	if (cmd->subcmds)
2795 	    cleanup_level(cmd->subcmds);
2796 	ipmi_mem_free(cmd);
2797     }
2798 }
2799 
2800 void
ipmi_cmdlang_cleanup(void)2801 ipmi_cmdlang_cleanup(void)
2802 {
2803     ipmi_cmdlang_pef_shutdown();
2804     ipmi_cmdlang_lanparm_shutdown();
2805     ipmi_cmdlang_solparm_shutdown();
2806     cleanup_level(cmd_list);
2807 }
2808 
2809 static int do_evinfo = 0;
2810 
2811 void
ipmi_cmdlang_set_evinfo(int evinfo)2812 ipmi_cmdlang_set_evinfo(int evinfo)
2813 {
2814     do_evinfo = evinfo;
2815 }
2816 
2817 int
ipmi_cmdlang_get_evinfo(void)2818 ipmi_cmdlang_get_evinfo(void)
2819 {
2820     return do_evinfo;
2821 }
2822