/* * cmdlang.c * * A command interpreter for OpenIPMI * * Author: MontaVista Software, Inc. * Corey Minyard * source@mvista.com * * Copyright 2004 MontaVista Software Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* Internal includes, do not use in your programs */ #include #include /* * This is the value passed to a command handler. */ struct ipmi_cmd_info_s { void *handler_data; /* From cb_data in the cmd reg */ int curr_arg; /* Argument you should start at */ int argc; /* Total number of arguments */ char **argv; /* The arguments */ /* Only allow one writer at a time */ ipmi_lock_t *lock; /* The cmdlang structure the user passed in. Use this for output and error reporting. */ ipmi_cmdlang_t *cmdlang; /* The matching cmd structure for the command being executed. May be NULL if no command is being processed. */ ipmi_cmdlang_cmd_t *cmd; /* Refcount for the structure. */ unsigned int usecount; /* For use by the user commands */ void *data; /* Used to know if the command generated output. */ int did_output; }; struct ipmi_cmdlang_cmd_s { char *name; char *help; ipmi_help_finisher_cb help_finish; /* Only one of handler or subcmds may be non-NULL. */ ipmi_cmdlang_handler_cb handler; ipmi_cmdlang_cmd_t *subcmds; void *handler_data; /* Used for a linked list. */ ipmi_cmdlang_cmd_t *next; }; static os_handler_t *cmdlang_os_hnd; /* Parse a string of the form [domain][(class)][.obj] and return each of the strings in the given string pointers. */ static int parse_ipmi_objstr(char *str, char **domain, char **class, char **obj) { int i; char *class_start = NULL, *class_end = NULL; for (i=0; str[i]; i++) { if (str[i] == '(') { if (class_start) /* Only one '(' allowed. */ return EINVAL; class_start = str + i; } else if (str[i] == ')') { if (class_start) { /* a ')' only means something after a '('. */ class_end = str + i; i++; break; } } } if (str[i]) { if (str[i] != '.') return EINVAL; } if (class_start) { if (!class_end) /* If class starts, must see the end paren. */ return EINVAL; *class_start = '\0'; *class_end = '\0'; *class = class_start + 1; } else { *class = NULL; } if (strlen(str) == 0) *domain = NULL; else *domain = str; if (str[i]) *obj = str + i + 1; else *obj = NULL; return 0; } /* * Handling for iterating domains. */ typedef struct domain_iter_info_s { char *cmpstr; ipmi_domain_ptr_cb handler; void *cb_data; ipmi_cmd_info_t *cmd_info; } domain_iter_info_t; static void for_each_domain_handler(ipmi_domain_t *domain, void *cb_data) { domain_iter_info_t *info = cb_data; ipmi_cmd_info_t *cmd_info = info->cmd_info; char domain_name[IPMI_DOMAIN_NAME_LEN]; if (cmd_info->cmdlang->err) return; ipmi_domain_get_name(domain, domain_name, sizeof(domain_name)); if ((!info->cmpstr) || (strcmp(info->cmpstr, domain_name) == 0)) info->handler(domain, info->cb_data); } 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) { domain_iter_info_t info; if (class || obj) { cmd_info->cmdlang->errstr = "Invalid domain"; cmd_info->cmdlang->err = EINVAL; cmd_info->cmdlang->location = "cmdlang.c(for_each_domain)"; return; } info.cmpstr = domain; info.handler = handler; info.cb_data = cb_data; info.cmd_info = cmd_info; ipmi_domain_iterate_domains(for_each_domain_handler, &info); } void ipmi_cmdlang_domain_handler(ipmi_cmd_info_t *cmd_info) { char *domain, *class, *obj; int rv; if (cmd_info->curr_arg >= cmd_info->argc) { domain = class = obj = NULL; } else { rv = parse_ipmi_objstr(cmd_info->argv[cmd_info->curr_arg], &domain, &class, &obj); if (rv) { cmd_info->cmdlang->errstr = "Invalid domain"; cmd_info->cmdlang->err = rv; cmd_info->cmdlang->location = "cmdlang.c(ipmi_cmdlang_domain_handler)"; return; } cmd_info->curr_arg++; } for_each_domain(cmd_info, domain, class, obj, cmd_info->handler_data, cmd_info); } /* * Handling for iterating PETs. */ typedef struct pet_iter_info_s { char *cmdstr; ipmi_pet_ptr_cb handler; void *cb_data; ipmi_cmd_info_t *cmd_info; } pet_iter_info_t; static void for_each_pet_handler(ipmi_pet_t *pet, void *cb_data) { pet_iter_info_t *info = cb_data; ipmi_cmd_info_t *cmd_info = info->cmd_info; ipmi_cmdlang_t *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info); char name[IPMI_PET_NAME_LEN]; char *c; if (cmdlang->err) return; ipmi_pet_get_name(pet, name, sizeof(name)); c = strrchr(name, '.'); if (!c) goto out_err; c++; if ((! info->cmdstr) || (strcmp(info->cmdstr, c) == 0)) info->handler(pet, info->cb_data); return; out_err: ipmi_cmdlang_global_err(name, "cmdlang.c(for_each_pet_handler)", "Bad PET name", EINVAL); } static void for_each_pet_domain_handler(ipmi_domain_t *domain, void *cb_data) { ipmi_pet_iterate_pets(domain, for_each_pet_handler, cb_data); } 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) { pet_iter_info_t info; if (class) { cmd_info->cmdlang->errstr = "Invalid PET"; cmd_info->cmdlang->err = EINVAL; cmd_info->cmdlang->location = "cmdlang.c(for_each_pet)"; return; } info.handler = handler; info.cb_data = cb_data; info.cmd_info = cmd_info; info.cmdstr = obj; for_each_domain(cmd_info, domain, NULL, NULL, for_each_pet_domain_handler, &info); } void ipmi_cmdlang_pet_handler(ipmi_cmd_info_t *cmd_info) { char *domain, *class, *obj; if (cmd_info->curr_arg >= cmd_info->argc) { domain = class = obj = NULL; } else { domain = cmd_info->argv[cmd_info->curr_arg]; class = NULL; obj = strrchr(domain, '.'); if (!obj) { cmd_info->cmdlang->errstr = "Invalid PET"; cmd_info->cmdlang->err = EINVAL; cmd_info->cmdlang->location = "cmdlang.c(ipmi_cmdlang_pet_handler)"; return; } *obj = '\0'; obj++; cmd_info->curr_arg++; } for_each_pet(cmd_info, domain, class, obj, cmd_info->handler_data, cmd_info); } /* * Handling for iterating LANPARMs. */ typedef struct lanparm_iter_info_s { char *cmdstr; ipmi_lanparm_ptr_cb handler; void *cb_data; ipmi_cmd_info_t *cmd_info; } lanparm_iter_info_t; static void for_each_lanparm_handler(ipmi_lanparm_t *lanparm, void *cb_data) { lanparm_iter_info_t *info = cb_data; ipmi_cmd_info_t *cmd_info = info->cmd_info; ipmi_cmdlang_t *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info); char name[IPMI_LANPARM_NAME_LEN]; char *c; if (cmdlang->err) return; ipmi_lanparm_get_name(lanparm, name, sizeof(name)); c = strrchr(name, '.'); if (!c) goto out_err; c++; if ((! info->cmdstr) || (strcmp(info->cmdstr, c) == 0)) info->handler(lanparm, info->cb_data); return; out_err: ipmi_cmdlang_global_err(name, "cmdlang.c(for_each_lanparm_handler)", "Bad LANPARM name", EINVAL); } static void for_each_lanparm_domain_handler(ipmi_domain_t *domain, void *cb_data) { ipmi_lanparm_iterate_lanparms(domain, for_each_lanparm_handler, cb_data); } 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) { lanparm_iter_info_t info; if (class) { cmd_info->cmdlang->errstr = "Invalid LANPARM"; cmd_info->cmdlang->err = EINVAL; cmd_info->cmdlang->location = "cmdlang.c(for_each_lanparm)"; return; } info.handler = handler; info.cb_data = cb_data; info.cmd_info = cmd_info; info.cmdstr = obj; for_each_domain(cmd_info, domain, NULL, NULL, for_each_lanparm_domain_handler, &info); } void ipmi_cmdlang_lanparm_handler(ipmi_cmd_info_t *cmd_info) { char *domain, *class, *obj; if (cmd_info->curr_arg >= cmd_info->argc) { domain = class = obj = NULL; } else { domain = cmd_info->argv[cmd_info->curr_arg]; class = NULL; obj = strrchr(domain, '.'); if (!obj) { cmd_info->cmdlang->errstr = "Invalid LANPARM"; cmd_info->cmdlang->err = EINVAL; cmd_info->cmdlang->location = "cmdlang.c(ipmi_cmdlang_lanparm_handler)"; return; } *obj = '\0'; obj++; cmd_info->curr_arg++; } for_each_lanparm(cmd_info, domain, class, obj, cmd_info->handler_data, cmd_info); } /* * Handling for iterating SOLPARMs. */ typedef struct solparm_iter_info_s { char *cmdstr; ipmi_solparm_ptr_cb handler; void *cb_data; ipmi_cmd_info_t *cmd_info; } solparm_iter_info_t; static void for_each_solparm_handler(ipmi_solparm_t *solparm, void *cb_data) { solparm_iter_info_t *info = cb_data; ipmi_cmd_info_t *cmd_info = info->cmd_info; ipmi_cmdlang_t *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info); char name[IPMI_SOLPARM_NAME_LEN]; char *c; if (cmdlang->err) return; ipmi_solparm_get_name(solparm, name, sizeof(name)); c = strrchr(name, '.'); if (!c) goto out_err; c++; if ((! info->cmdstr) || (strcmp(info->cmdstr, c) == 0)) info->handler(solparm, info->cb_data); return; out_err: ipmi_cmdlang_global_err(name, "cmdlang.c(for_each_solparm_handler)", "Bad SOLPARM name", EINVAL); } static void for_each_solparm_domain_handler(ipmi_domain_t *domain, void *cb_data) { ipmi_solparm_iterate_solparms(domain, for_each_solparm_handler, cb_data); } 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) { solparm_iter_info_t info; if (class) { cmd_info->cmdlang->errstr = "Invalid SOLPARM"; cmd_info->cmdlang->err = EINVAL; cmd_info->cmdlang->location = "cmdlang.c(for_each_solparm)"; return; } info.handler = handler; info.cb_data = cb_data; info.cmd_info = cmd_info; info.cmdstr = obj; for_each_domain(cmd_info, domain, NULL, NULL, for_each_solparm_domain_handler, &info); } void ipmi_cmdlang_solparm_handler(ipmi_cmd_info_t *cmd_info) { char *domain, *class, *obj; if (cmd_info->curr_arg >= cmd_info->argc) { domain = class = obj = NULL; } else { domain = cmd_info->argv[cmd_info->curr_arg]; class = NULL; obj = strrchr(domain, '.'); if (!obj) { cmd_info->cmdlang->errstr = "Invalid SOLPARM"; cmd_info->cmdlang->err = EINVAL; cmd_info->cmdlang->location = "cmdlang.c(ipmi_cmdlang_solparm_handler)"; return; } *obj = '\0'; obj++; cmd_info->curr_arg++; } for_each_solparm(cmd_info, domain, class, obj, cmd_info->handler_data, cmd_info); } /* * Handling for iterating PEFs. */ typedef struct pef_iter_info_s { char *cmdstr; ipmi_pef_ptr_cb handler; void *cb_data; ipmi_cmd_info_t *cmd_info; } pef_iter_info_t; static void for_each_pef_handler(ipmi_pef_t *pef, void *cb_data) { pef_iter_info_t *info = cb_data; ipmi_cmd_info_t *cmd_info = info->cmd_info; ipmi_cmdlang_t *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info); char name[IPMI_PEF_NAME_LEN]; char *c; if (cmdlang->err) return; ipmi_pef_get_name(pef, name, sizeof(name)); c = strrchr(name, '.'); if (!c) goto out_err; c++; if ((! info->cmdstr) || (strcmp(info->cmdstr, c) == 0)) info->handler(pef, info->cb_data); return; out_err: ipmi_cmdlang_global_err(name, "cmdlang.c(for_each_pef_handler)", "Bad PEF name", EINVAL); } static void for_each_pef_domain_handler(ipmi_domain_t *domain, void *cb_data) { ipmi_pef_iterate_pefs(domain, for_each_pef_handler, cb_data); } 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) { pef_iter_info_t info; if (class) { cmd_info->cmdlang->errstr = "Invalid PEF"; cmd_info->cmdlang->err = EINVAL; cmd_info->cmdlang->location = "cmdlang.c(for_each_pef)"; return; } info.handler = handler; info.cb_data = cb_data; info.cmd_info = cmd_info; info.cmdstr = obj; for_each_domain(cmd_info, domain, NULL, NULL, for_each_pef_domain_handler, &info); } void ipmi_cmdlang_pef_handler(ipmi_cmd_info_t *cmd_info) { char *domain, *class, *obj; if (cmd_info->curr_arg >= cmd_info->argc) { domain = class = obj = NULL; } else { domain = cmd_info->argv[cmd_info->curr_arg]; class = NULL; obj = strrchr(domain, '.'); if (!obj) { cmd_info->cmdlang->errstr = "Invalid PEF"; cmd_info->cmdlang->err = EINVAL; cmd_info->cmdlang->location = "cmdlang.c(ipmi_cmdlang_pef_handler)"; return; } *obj = '\0'; obj++; cmd_info->curr_arg++; } for_each_pef(cmd_info, domain, class, obj, cmd_info->handler_data, cmd_info); } /* * Handling for iterating FRUs. */ typedef struct fru_iter_info_s { char *cmdstr; ipmi_fru_ptr_cb handler; void *cb_data; ipmi_cmd_info_t *cmd_info; } fru_iter_info_t; static void for_each_fru_handler(ipmi_fru_t *fru, void *cb_data) { fru_iter_info_t *info = cb_data; ipmi_cmd_info_t *cmd_info = info->cmd_info; ipmi_cmdlang_t *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info); char name[IPMI_FRU_NAME_LEN]; char *c; if (cmdlang->err) return; ipmi_fru_get_name(fru, name, sizeof(name)); c = strrchr(name, '.'); if (!c) goto out_err; c++; if ((! info->cmdstr) || (strcmp(info->cmdstr, c) == 0)) info->handler(fru, info->cb_data); return; out_err: ipmi_cmdlang_global_err(name, "cmdlang.c(for_each_fru_handler)", "Bad FRU name", EINVAL); } static void for_each_fru_domain_handler(ipmi_domain_t *domain, void *cb_data) { ipmi_fru_iterate_frus(domain, for_each_fru_handler, cb_data); } 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) { fru_iter_info_t info; if (class) { cmd_info->cmdlang->errstr = "Invalid FRU"; cmd_info->cmdlang->err = EINVAL; cmd_info->cmdlang->location = "cmdlang.c(for_each_fru)"; return; } info.handler = handler; info.cb_data = cb_data; info.cmd_info = cmd_info; info.cmdstr = obj; for_each_domain(cmd_info, domain, NULL, NULL, for_each_fru_domain_handler, &info); } void ipmi_cmdlang_fru_handler(ipmi_cmd_info_t *cmd_info) { char *domain, *class, *obj; if (cmd_info->curr_arg >= cmd_info->argc) { domain = class = obj = NULL; } else { domain = cmd_info->argv[cmd_info->curr_arg]; class = NULL; obj = strrchr(domain, '.'); if (!obj) { cmd_info->cmdlang->errstr = "Invalid FRU"; cmd_info->cmdlang->err = EINVAL; cmd_info->cmdlang->location = "cmdlang.c(ipmi_cmdlang_fru_handler)"; return; } *obj = '\0'; obj++; cmd_info->curr_arg++; } for_each_fru(cmd_info, domain, class, obj, cmd_info->handler_data, cmd_info); } /* * Handling for iterating entities. */ typedef struct entity_iter_info_s { char *cmpstr; ipmi_entity_ptr_cb handler; void *cb_data; ipmi_cmd_info_t *cmd_info; } entity_iter_info_t; static void for_each_entity_handler(ipmi_entity_t *entity, void *cb_data) { entity_iter_info_t *info = cb_data; ipmi_cmd_info_t *cmd_info = info->cmd_info; char entity_name[IPMI_ENTITY_NAME_LEN]; char *c, *c2; if (cmd_info->cmdlang->err) return; ipmi_entity_get_name(entity, entity_name, sizeof(entity_name)); c = strchr(entity_name, '('); if (!c) goto out_err; c++; c2 = strchr(c, ')'); if (!c2) goto out_err; *c2 = '\0'; if ((!info->cmpstr) || (strcmp(info->cmpstr, c) == 0)) { *c2 = ')'; info->handler(entity, info->cb_data); } else *c2 = ')'; return; out_err: ipmi_cmdlang_global_err(entity_name, "cmdlang.c(for_each_entity_handler)", "Bad entity name", EINVAL); } static void for_each_entity_domain_handler(ipmi_domain_t *domain, void *cb_data) { ipmi_domain_iterate_entities(domain, for_each_entity_handler, cb_data); } 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) { entity_iter_info_t info; if (obj) { cmd_info->cmdlang->errstr = "Invalid entity"; cmd_info->cmdlang->err = EINVAL; cmd_info->cmdlang->location = "cmdlang.c(for_each_entity)"; return; } info.cmpstr = class; info.handler = handler; info.cb_data = cb_data; info.cmd_info = cmd_info; for_each_domain(cmd_info, domain, NULL, NULL, for_each_entity_domain_handler, &info); } void ipmi_cmdlang_entity_handler(ipmi_cmd_info_t *cmd_info) { char *domain, *class, *obj; int rv; if (cmd_info->curr_arg >= cmd_info->argc) { domain = class = obj = NULL; } else { rv = parse_ipmi_objstr(cmd_info->argv[cmd_info->curr_arg], &domain, &class, &obj); if (rv) { cmd_info->cmdlang->errstr = "Invalid entity"; cmd_info->cmdlang->err = rv; cmd_info->cmdlang->location = "cmdlang.c(ipmi_cmdlang_entity_handler)"; return; } cmd_info->curr_arg++; } for_each_entity(cmd_info, domain, class, obj, cmd_info->handler_data, cmd_info); } /* * Handling for iterating sensors. */ typedef struct sensor_iter_info_s { char *cmpstr; ipmi_sensor_ptr_cb handler; void *cb_data; ipmi_cmd_info_t *cmd_info; } sensor_iter_info_t; static void for_each_sensor_handler(ipmi_entity_t *entity, ipmi_sensor_t *sensor, void *cb_data) { sensor_iter_info_t *info = cb_data; char sensor_name[IPMI_SENSOR_NAME_LEN]; char *c; ipmi_sensor_get_name(sensor, sensor_name, sizeof(sensor_name)); c = strchr(sensor_name, '('); if (!c) goto out_err; c = strchr(c, ')'); if (!c) goto out_err; c = strchr(c, '.'); if (!c) goto out_err; c++; if ((!info->cmpstr) || (strcmp(info->cmpstr, c) == 0)) info->handler(sensor, info->cb_data); return; out_err: ipmi_cmdlang_global_err(sensor_name, "cmdlang.c(for_each_sensor_handler)", "Bad sensor name", EINVAL); } static void for_each_sensor_entity_handler(ipmi_entity_t *entity, void *cb_data) { ipmi_entity_iterate_sensors(entity, for_each_sensor_handler, cb_data); } 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) { sensor_iter_info_t info; info.cmpstr = obj; info.handler = handler; info.cb_data = cb_data; info.cmd_info = cmd_info; for_each_entity(cmd_info, domain, class, NULL, for_each_sensor_entity_handler, &info); } void ipmi_cmdlang_sensor_handler(ipmi_cmd_info_t *cmd_info) { char *domain, *class, *obj; int rv; if (cmd_info->curr_arg >= cmd_info->argc) { domain = class = obj = NULL; } else { rv = parse_ipmi_objstr(cmd_info->argv[cmd_info->curr_arg], &domain, &class, &obj); if (rv) { cmd_info->cmdlang->errstr = "Invalid sensor"; cmd_info->cmdlang->err = rv; cmd_info->cmdlang->location = "cmdlang.c(ipmi_cmdlang_sensor_handler)"; return; } cmd_info->curr_arg++; } for_each_sensor(cmd_info, domain, class, obj, cmd_info->handler_data, cmd_info); } /* * Handling for iterating controls. */ typedef struct control_iter_info_s { char *cmpstr; ipmi_control_ptr_cb handler; void *cb_data; ipmi_cmd_info_t *cmd_info; } control_iter_info_t; static void for_each_control_handler(ipmi_entity_t *entity, ipmi_control_t *control, void *cb_data) { control_iter_info_t *info = cb_data; char control_name[IPMI_CONTROL_NAME_LEN]; char *c; ipmi_control_get_name(control, control_name, sizeof(control_name)); c = strchr(control_name, '('); if (!c) goto out_err; c = strchr(c, ')'); if (!c) goto out_err; c = strchr(c, '.'); if (!c) goto out_err; c++; if ((!info->cmpstr) || (strcmp(info->cmpstr, c) == 0)) info->handler(control, info->cb_data); return; out_err: ipmi_cmdlang_global_err(control_name, "cmdlang.c(for_each_control_handler)", "Bad control name", EINVAL); } static void for_each_control_entity_handler(ipmi_entity_t *entity, void *cb_data) { ipmi_entity_iterate_controls(entity, for_each_control_handler, cb_data); } 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) { control_iter_info_t info; info.cmpstr = obj; info.handler = handler; info.cb_data = cb_data; info.cmd_info = cmd_info; for_each_entity(cmd_info, domain, class, NULL, for_each_control_entity_handler, &info); } void ipmi_cmdlang_control_handler(ipmi_cmd_info_t *cmd_info) { char *domain, *class, *obj; int rv; if (cmd_info->curr_arg >= cmd_info->argc) { domain = class = obj = NULL; } else { rv = parse_ipmi_objstr(cmd_info->argv[cmd_info->curr_arg], &domain, &class, &obj); if (rv) { cmd_info->cmdlang->errstr = "Invalid control"; cmd_info->cmdlang->err = rv; cmd_info->cmdlang->location = "cmdlang.c(ipmi_cmdlang_control_handler)"; return; } cmd_info->curr_arg++; } for_each_control(cmd_info, domain, class, obj, cmd_info->handler_data, cmd_info); } /* * Handling for iterating mcs. */ typedef struct mc_iter_info_s { char *cmpstr; ipmi_mc_ptr_cb handler; void *cb_data; ipmi_cmd_info_t *cmd_info; } mc_iter_info_t; static void for_each_mc_handler(ipmi_domain_t *domain, ipmi_mc_t *mc, void *cb_data) { mc_iter_info_t *info = cb_data; char mc_name[IPMI_MC_NAME_LEN]; char *c, *c2; ipmi_mc_get_name(mc, mc_name, sizeof(mc_name)); c = strchr(mc_name, '('); if (!c) goto out_err; c++; c2 = strchr(c, ')'); if (!c2) goto out_err; *c2 = '\0'; if ((!info->cmpstr) || (strcmp(info->cmpstr, c) == 0)) { *c2 = ')'; info->handler(mc, info->cb_data); } else *c2 = ')'; return; out_err: ipmi_cmdlang_global_err(mc_name, "cmdlang.c(for_each_entity_handler)", "Bad mc name", EINVAL); } static void for_each_mc_domain_handler(ipmi_domain_t *domain, void *cb_data) { ipmi_domain_iterate_mcs(domain, for_each_mc_handler, cb_data); } 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) { mc_iter_info_t info; if (obj) { cmd_info->cmdlang->errstr = "Invalid MC"; cmd_info->cmdlang->err = EINVAL; cmd_info->cmdlang->location = "cmdlang.c(for_each_mc)"; return; } info.cmpstr = class; info.handler = handler; info.cb_data = cb_data; info.cmd_info = cmd_info; for_each_domain(cmd_info, domain, NULL, NULL, for_each_mc_domain_handler, &info); } void ipmi_cmdlang_mc_handler(ipmi_cmd_info_t *cmd_info) { char *domain, *class, *obj; int rv; if (cmd_info->curr_arg >= cmd_info->argc) { domain = class = obj = NULL; } else { rv = parse_ipmi_objstr(cmd_info->argv[cmd_info->curr_arg], &domain, &class, &obj); if (rv) { cmd_info->cmdlang->errstr = "Invalid MC"; cmd_info->cmdlang->err = rv; cmd_info->cmdlang->location = "cmdlang.c(ipmi_cmdlang_mc_handler)"; return; } cmd_info->curr_arg++; } for_each_mc(cmd_info, domain, class, obj, cmd_info->handler_data, cmd_info); } /* * Handling for iterating connections. */ typedef struct conn_iter_info_s { int conn; ipmi_connection_ptr_cb handler; void *cb_data; ipmi_cmd_info_t *cmd_info; } conn_iter_info_t; static void for_each_conn_handler(ipmi_domain_t *domain, int conn, void *cb_data) { conn_iter_info_t *info = cb_data; if ((info->conn == -1) || (info->conn == conn)) info->handler(domain, conn, info->cb_data); } static void for_each_conn_domain_handler(ipmi_domain_t *domain, void *cb_data) { ipmi_domain_iterate_connections(domain, for_each_conn_handler, cb_data); } 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) { conn_iter_info_t info; char *endptr; if (class) { cmd_info->cmdlang->errstr = "Invalid connection"; cmd_info->cmdlang->err = EINVAL; cmd_info->cmdlang->location = "cmdlang.c(for_each_connection)"; return; } if (obj) { if (!isdigit(obj[0])) { cmd_info->cmdlang->errstr = "Invalid connection number"; cmd_info->cmdlang->err = EINVAL; cmd_info->cmdlang->location = "cmdlang.c(for_each_connection)"; return; } info.conn = strtoul(obj, &endptr, 0); if (*endptr != '\0') { cmd_info->cmdlang->errstr = "Invalid connection number"; cmd_info->cmdlang->err = EINVAL; cmd_info->cmdlang->location = "cmdlang.c(for_each_connection)"; return; } } else { info.conn = -1; } info.handler = handler; info.cb_data = cb_data; info.cmd_info = cmd_info; for_each_domain(cmd_info, domain, NULL, NULL, for_each_conn_domain_handler, &info); } void ipmi_cmdlang_connection_handler(ipmi_cmd_info_t *cmd_info) { char *domain, *class, *obj; if (cmd_info->curr_arg >= cmd_info->argc) { domain = class = obj = NULL; } else { domain = cmd_info->argv[cmd_info->curr_arg]; class = NULL; obj = strrchr(domain, '.'); if (!obj) { cmd_info->cmdlang->errstr = "Invalid connection"; cmd_info->cmdlang->err = EINVAL; cmd_info->cmdlang->location = "cmdlang.c(ipmi_cmdlang_connection_handler)"; return; } *obj = '\0'; obj++; cmd_info->curr_arg++; } for_each_connection(cmd_info, domain, class, obj, cmd_info->handler_data, cmd_info); } static int parse_next_str(char **tok, char **istr) { char *str = *istr; char *tstr; char *start; char quote = 0; while (isspace(*str)) str++; if (!*str) return ENOENT; if ((*str == '"') || (*str == '\'')) { quote = *str; str++; } start = str; while (*str) { if (quote) { if (*str == quote) break; } else { if (isspace(*str)) break; } if (*str == '\\') { tstr = str; if (! *(tstr+1)) /* Nothing after a '\' */ return EINVAL; while (*(tstr+1)) { *tstr = *(tstr+1); tstr++; } } str++; } if (*str) { *str = '\0'; *istr = str+1; } else { *istr = str; } *tok = start; return 0; } static ipmi_cmdlang_cmd_t *cmd_list; #define MAXARGS 100 void ipmi_cmdlang_handle(ipmi_cmdlang_t *cmdlang, char *str) { int argc; char *argv[MAXARGS]; int curr_arg; ipmi_cmdlang_cmd_t *cmd; ipmi_cmd_info_t *info; int rv; if (*str == '#') { /* A comment */ cmdlang->done(cmdlang); return; } info = ipmi_mem_alloc(sizeof(*info)); if (!info) { cmdlang->errstr = "Out of memory"; cmdlang->err = ENOMEM; cmdlang->location = "cmdlang.c(ipmi_cmdlang_handle)"; cmdlang->done(cmdlang); return; } memset(info, 0, sizeof(*info)); info->usecount = 1; info->cmdlang = cmdlang; rv = ipmi_create_lock_os_hnd(cmdlang->os_hnd, &info->lock); if (rv) { cmdlang->errstr = "Could not allocate lock"; cmdlang->err = rv; cmdlang->location = "cmdlang.c(ipmi_cmdlang_handle)"; goto done; } for (argc=0; argcerrstr = "Invalid string"; cmdlang->err = rv; cmdlang->location = "cmdlang.c(ipmi_cmdlang_handle)"; goto done; } } if (*str) { /* Too many arguments */ cmdlang->errstr = "Too many arguments"; cmdlang->err = E2BIG; cmdlang->location = "cmdlang.c(ipmi_cmdlang_handle)"; goto done; } curr_arg = 0; rv = 0; cmd = cmd_list; if (argc == curr_arg) { cmdlang->errstr = "No command"; cmdlang->err = ENOMSG; cmdlang->location = "cmdlang.c(ipmi_cmdlang_handle)"; goto done; } if (strcmp(argv[curr_arg], "help") == 0) { ipmi_cmdlang_cmd_t *parent = NULL; int old_help = cmdlang->help; /* Help has special handling. */ cmdlang->help = 1; curr_arg++; for (;;) { next_help: if (argc == curr_arg) { rv = 0; if (parent) { cmdlang->out(cmdlang, parent->name, parent->help); if (parent->help_finish) parent->help_finish(cmdlang); }else cmdlang->out(cmdlang, "help", NULL); if (cmdlang->err) goto done_help; cmdlang->down(cmdlang); while (cmd) { cmdlang->out(cmdlang, cmd->name, cmd->help); if (cmdlang->err) { cmdlang->up(cmdlang); goto done_help; } if (cmd->help_finish) cmd->help_finish(cmdlang); cmd = cmd->next; } cmdlang->up(cmdlang); break; } if (!cmd) { cmdlang->errstr = "Command not found"; cmdlang->err = ENOSYS; cmdlang->location = "cmdlang.c(ipmi_cmdlang_handle)"; goto done_help; } while (cmd) { if (strcmp(cmd->name, argv[curr_arg]) == 0) { curr_arg++; parent = cmd; cmd = cmd->subcmds; goto next_help; } cmd = cmd->next; } cmdlang->errstr = "Command not found"; cmdlang->err = ENOSYS; cmdlang->location = "cmdlang.c(ipmi_cmdlang_handle)"; goto done_help; } done_help: info->did_output = 1; cmdlang->help = old_help; goto done; } for (;;) { if (argc == curr_arg) { cmdlang->errstr = "Missing command"; cmdlang->err = ENOMSG; cmdlang->location = "cmdlang.c(ipmi_cmdlang_handle)"; goto done; } while (cmd) { if (strcmp(cmd->name, argv[curr_arg]) == 0) { if (cmd->subcmds) { cmd = cmd->subcmds; curr_arg++; /* Continue processing this subcommand list */ break; } else { curr_arg++; info->handler_data = cmd->handler_data; info->curr_arg = curr_arg; info->argc = argc; info->argv = argv; info->cmd = cmd; cmd->handler(info); goto done; } } cmd = cmd->next; } if (!cmd) { cmdlang->errstr = "Command not found"; cmdlang->err = ENOSYS; cmdlang->location = "cmdlang.c(ipmi_cmdlang_handle)"; goto done; } } done: ipmi_cmdlang_cmd_info_put(info); } 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) { ipmi_cmdlang_cmd_t *rv; ipmi_cmdlang_cmd_t *cmd; /* Check for dups. */ if (!parent) cmd = cmd_list; else cmd = parent; while (cmd) { if (strcmp(cmd->name, name) == 0) return EEXIST; cmd = cmd->next; } rv = ipmi_mem_alloc(sizeof(*rv)); if (!rv) return ENOMEM; rv->name = name; rv->help = help; rv->handler = handler; rv->subcmds = NULL; rv->handler_data = cb_data; rv->help_finish = help_finish; rv->next = NULL; if (parent) { if (!parent->subcmds) { parent->subcmds = rv; goto done; } cmd = parent->subcmds; } else { if (!cmd_list) { cmd_list = rv; goto done; } cmd = cmd_list; } while (cmd->next) { cmd = cmd->next; } cmd->next = rv; done: if (new_val) *new_val = rv; return 0; } int ipmi_cmdlang_reg_table(ipmi_cmdlang_init_t *table, int len) { int i; int rv; ipmi_cmdlang_cmd_t *parent = NULL; for (i=0; ilock); } void ipmi_cmdlang_unlock(ipmi_cmd_info_t *info) { ipmi_unlock(info->lock); } void ipmi_cmdlang_out(ipmi_cmd_info_t *info, const char *name, const char *value) { info->did_output = 1; info->cmdlang->out(info->cmdlang, name, value); } void ipmi_cmdlang_out_int(ipmi_cmd_info_t *info, const char *name, int value) { char sval[20]; sprintf(sval, "%d", value); ipmi_cmdlang_out(info, name, sval); } void ipmi_cmdlang_out_double(ipmi_cmd_info_t *info, const char *name, double value) { char sval[80]; sprintf(sval, "%e", value); ipmi_cmdlang_out(info, name, sval); } void ipmi_cmdlang_out_hex(ipmi_cmd_info_t *info, const char *name, int value) { char sval[20]; sprintf(sval, "0x%x", value); ipmi_cmdlang_out(info, name, sval); } void ipmi_cmdlang_out_long(ipmi_cmd_info_t *info, const char *name, long value) { char sval[32]; sprintf(sval, "%ld", value); ipmi_cmdlang_out(info, name, sval); } void ipmi_cmdlang_out_binary(ipmi_cmd_info_t *info, const char *name, const char *value, unsigned int len) { info->did_output = 1; info->cmdlang->out_binary(info->cmdlang, name, value, len); } void ipmi_cmdlang_out_unicode(ipmi_cmd_info_t *info, const char *name, const char *value, unsigned int len) { info->did_output = 1; info->cmdlang->out_unicode(info->cmdlang, name, value, len); } void ipmi_cmdlang_out_type(ipmi_cmd_info_t *info, char *name, enum ipmi_str_type_e type, const char *value, unsigned int len) { switch(type) { case IPMI_ASCII_STR: ipmi_cmdlang_out(info, name, value); break; case IPMI_UNICODE_STR: ipmi_cmdlang_out_unicode(info, name, value, len); break; case IPMI_BINARY_STR: ipmi_cmdlang_out_binary(info, name, value, len); break; } } void ipmi_cmdlang_out_bool(ipmi_cmd_info_t *info, const char *name, int value) { if (value) ipmi_cmdlang_out(info, name, "true"); else ipmi_cmdlang_out(info, name, "false"); } void ipmi_cmdlang_out_time(ipmi_cmd_info_t *info, const char *name, ipmi_time_t value) { char sval[40]; sprintf(sval, "%lld", (long long) value); ipmi_cmdlang_out(info, name, sval); } void ipmi_cmdlang_out_timeout(ipmi_cmd_info_t *info, const char *name, ipmi_timeout_t value) { char sval[40]; sprintf(sval, "%lld", (long long) value); ipmi_cmdlang_out(info, name, sval); } void ipmi_cmdlang_out_ip(ipmi_cmd_info_t *info, const char *name, struct in_addr *ip_addr) { char outstr[16]; uint32_t addr = ntohl(ip_addr->s_addr); /* Why isn't there an inet_ntoa_r? */ sprintf(outstr, "%d.%d.%d.%d", (addr >> 24) & 0xff, (addr >> 16) & 0xff, (addr >> 8) & 0xff, (addr >> 0) & 0xff); ipmi_cmdlang_out(info, name, outstr); } void ipmi_cmdlang_out_mac(ipmi_cmd_info_t *info, const char *name, unsigned char mac_addr[6]) { char outstr[18]; /* Why isn't there a standard ether_ntoa_r? */ sprintf(outstr, "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x", mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); ipmi_cmdlang_out(info, name, outstr); } void ipmi_cmdlang_down(ipmi_cmd_info_t *info) { info->cmdlang->down(info->cmdlang); } void ipmi_cmdlang_up(ipmi_cmd_info_t *info) { info->cmdlang->up(info->cmdlang); } void ipmi_cmdlang_cmd_info_get(ipmi_cmd_info_t *cmd_info) { ipmi_cmdlang_lock(cmd_info); cmd_info->usecount++; ipmi_cmdlang_unlock(cmd_info); } void ipmi_cmdlang_cmd_info_put(ipmi_cmd_info_t *cmd_info) { ipmi_cmdlang_lock(cmd_info); cmd_info->usecount--; if (cmd_info->usecount == 0) { if ((!cmd_info->cmdlang->err) && (!cmd_info->did_output)) { cmd_info->cmdlang->errstr = "Specified object not found"; cmd_info->cmdlang->err = EINVAL; cmd_info->cmdlang->location = "cmdlang.c(ipmi_cmdlang_handle)"; } cmd_info->cmdlang->done(cmd_info->cmdlang); ipmi_cmdlang_unlock(cmd_info); if (cmd_info->lock) ipmi_destroy_lock(cmd_info->lock); ipmi_mem_free(cmd_info); } else ipmi_cmdlang_unlock(cmd_info); } void ipmi_cmdlang_get_int(char *str, int *val, ipmi_cmd_info_t *info) { char *end; int rv; if (info->cmdlang->err) return; rv = strtoul(str, &end, 0); if (*end != '\0') { info->cmdlang->errstr = "Invalid integer"; info->cmdlang->err = EINVAL; info->cmdlang->location = "cmdlang.c(ipmi_cmdlang_get_int)"; return; } *val = rv; } void ipmi_cmdlang_get_time(char *str, ipmi_time_t *val, ipmi_cmd_info_t *info) { char *end; ipmi_time_t rv; if (info->cmdlang->err) return; rv = strtoull(str, &end, 0); if (*end != '\0') { info->cmdlang->errstr = "Invalid integer"; info->cmdlang->err = EINVAL; info->cmdlang->location = "cmdlang.c(ipmi_cmdlang_get_int)"; return; } *val = rv; } void ipmi_cmdlang_get_timeout(char *str, ipmi_timeout_t *val, ipmi_cmd_info_t *info) { char *end; ipmi_timeout_t rv; if (info->cmdlang->err) return; rv = strtoull(str, &end, 0); if (*end != '\0') { info->cmdlang->errstr = "Invalid integer"; info->cmdlang->err = EINVAL; info->cmdlang->location = "cmdlang.c(ipmi_cmdlang_get_int)"; return; } *val = rv; } void ipmi_cmdlang_get_double(char *str, double *val, ipmi_cmd_info_t *info) { char *end; double rv; if (info->cmdlang->err) return; rv = strtod(str, &end); if (*end != '\0') { info->cmdlang->errstr = "Invalid double"; info->cmdlang->err = EINVAL; info->cmdlang->location = "cmdlang.c(ipmi_cmdlang_get_double)"; return; } *val = rv; } void ipmi_cmdlang_get_uchar(char *str, unsigned char *val, ipmi_cmd_info_t *info) { char *end; int rv; if (info->cmdlang->err) return; rv = strtoul(str, &end, 0); if (*end != '\0') { info->cmdlang->errstr = "Invalid integer"; info->cmdlang->err = EINVAL; info->cmdlang->location = "cmdlang.c(ipmi_cmdlang_get_uchar)"; return; } *val = rv; } void ipmi_cmdlang_get_bool(char *str, int *val, ipmi_cmd_info_t *info) { int rv; if (info->cmdlang->err) return; if ((strcasecmp(str, "true") == 0) || (strcasecmp(str, "on") == 0) || (strcasecmp(str, "t") == 0) || (strcmp(str, "1") == 0)) { rv = 1; } else if ((strcasecmp(str, "false") == 0) || (strcasecmp(str, "off") == 0) || (strcasecmp(str, "f") == 0) || (strcmp(str, "0") == 0)) { rv = 0; } else { info->cmdlang->errstr = "Invalid boolean"; info->cmdlang->err = EINVAL; info->cmdlang->location = "cmdlang.c(ipmi_cmdlang_get_bool)"; return; } *val = rv; } void ipmi_cmdlang_get_user(char *str, int *val, ipmi_cmd_info_t *info) { char *end; int rv; if (info->cmdlang->err) return; rv = strtoul(str, &end, 0); if (*end != '\0') goto not_int; *val = rv; return; not_int: if (strcmp(str, "callback") == 0) *val = IPMI_PRIVILEGE_CALLBACK; else if (strcmp(str, "user") == 0) *val = IPMI_PRIVILEGE_USER; else if (strcmp(str, "operator") == 0) *val = IPMI_PRIVILEGE_OPERATOR; else if (strcmp(str, "admin") == 0) *val = IPMI_PRIVILEGE_ADMIN; else if (strcmp(str, "oem") == 0) *val = IPMI_PRIVILEGE_OEM; else { info->cmdlang->errstr = "Invalid privilege level"; info->cmdlang->err = EINVAL; info->cmdlang->location = "cmdlang.c(ipmi_cmdlang_get_user)"; } } void ipmi_cmdlang_get_ip(char *str, struct in_addr *val, ipmi_cmd_info_t *info) { #ifdef HAVE_GETADDRINFO struct addrinfo hints, *res0; int rv; struct sockaddr_in *paddr; if (info->cmdlang->err) return; memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_INET; hints.ai_socktype = SOCK_DGRAM; rv = getaddrinfo(str, 0, &hints, &res0); if (rv == 0) { /* Only get the first choice */ paddr = (struct sockaddr_in *) res0->ai_addr; *val = paddr->sin_addr; freeaddrinfo(res0); } else info->cmdlang->err = rv; #else /* System does not support getaddrinfo, just for IPv4*/ struct hostent *ent; struct sockaddr_in *paddr; if (info->cmdlang->err) return; ent = gethostbyname(str); if (!ent) { info->cmdlang->err = EINVAL; } else { paddr = (struct sockaddr_in *) &ent->h_addr_list[0]; *val = paddr->sin_addr; memcpy(val, ent->h_addr_list[0], ent->h_length); } #endif } void ipmi_cmdlang_get_mac(char *str, unsigned char val[6], ipmi_cmd_info_t *info) { char tmp[3]; char *tv; int len; unsigned char tmp_val[6]; int i; char *end; if (info->cmdlang->err) return; for (i=0; i<6; i++) { if (i == 5) tv = str + strlen(str); else tv = strchr(str, ':'); if (!tv) { info->cmdlang->err = EINVAL; goto out; } len = tv-str; if (len > 2) { info->cmdlang->err = EINVAL; goto out; } memset(tmp, 0, sizeof(tmp)); memcpy(tmp, str, len); tmp_val[i] = strtoul(tmp, &end, 16); if (*end != '\0') { info->cmdlang->err = EINVAL; goto out; } str = tv+1; } memcpy(val, tmp_val, sizeof(tmp_val)); return; out: return; } void ipmi_cmdlang_get_color(char *str, int *val, ipmi_cmd_info_t *info) { int i; for (i=IPMI_CONTROL_COLOR_BLACK; icmdlang->errstr = "Invalid color"; info->cmdlang->err = EINVAL; info->cmdlang->location = "cmdlang.c(ipmi_cmdlang_get_color)"; } static int issep(char val) { return ((val == ' ') || (val == '\t') || (val == '\n') || (val == '\r')); } 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) { enum ipmi_thresh_e thresh; enum ipmi_event_value_dir_e value_dir; enum ipmi_event_dir_e dir; char val[4][20]; int len; int vc; vc = 0; for (;;) { char *start, *end; while (issep(*str)) str++; if (! *str) break; if (vc == 4) goto out_err; start = str; while (*str && (!issep(*str))) str++; end = str; len = end - start; if (len >= 20) goto out_err; memcpy(val[vc], start, len); val[vc][len] = '\0'; vc++; } if (vc == 1) { /* One value, it is a compressed form. */ if (strlen(val[0]) != 4) goto out_err; if ((val[0][0] == 'u') || (val[0][0] == 'U')) { if ((val[0][1] == 'n') || (val[0][1] == 'N')) thresh = IPMI_UPPER_NON_CRITICAL; else if ((val[0][1] == 'c') || (val[0][1] == 'C')) thresh = IPMI_UPPER_CRITICAL; else if ((val[0][1] == 'f') || (val[0][1] == 'F')) thresh = IPMI_UPPER_NON_RECOVERABLE; else if ((val[0][1] == 'r') || (val[0][1] == 'R')) thresh = IPMI_UPPER_NON_RECOVERABLE; else goto out_err; } else if ((val[0][0] == 'l') || (val[0][0] == 'L')) { if ((val[0][1] == 'n') || (val[0][1] == 'N')) thresh = IPMI_LOWER_NON_CRITICAL; else if ((val[0][1] == 'c') || (val[0][1] == 'C')) thresh = IPMI_LOWER_CRITICAL; else if ((val[0][1] == 'f') || (val[0][1] == 'F')) thresh = IPMI_LOWER_NON_RECOVERABLE; else if ((val[0][1] == 'r') || (val[0][1] == 'R')) thresh = IPMI_LOWER_NON_RECOVERABLE; else goto out_err; } else goto out_err; if ((val[0][2] == 'h') || (val[0][2] == 'H')) value_dir = IPMI_GOING_HIGH; else if ((val[0][2] == 'l') || (val[0][2] == 'L')) value_dir = IPMI_GOING_LOW; else goto out_err; if ((val[0][3] == 'a') || (val[0][2] == 'A')) dir = IPMI_ASSERTION; else if ((val[0][3] == 'd') || (val[0][3] == 'D')) dir = IPMI_DEASSERTION; else goto out_err; } else if (vc == 4) { /* Four values, uncompressed form */ if (strcasecmp(val[0], "upper") == 0) { if (strcasecmp(val[1], "non-critical") == 0) thresh = IPMI_UPPER_NON_CRITICAL; else if (strcasecmp(val[1], "critical") == 0) thresh = IPMI_UPPER_CRITICAL; else if (strcasecmp(val[1], "non-recoverable") == 0) thresh = IPMI_UPPER_NON_RECOVERABLE; else goto out_err; } else if (strcasecmp(val[0], "lower") == 0) { if (strcasecmp(val[1], "non-critical") == 0) thresh = IPMI_LOWER_NON_CRITICAL; else if (strcasecmp(val[1], "critical") == 0) thresh = IPMI_LOWER_CRITICAL; else if (strcasecmp(val[1], "non-recoverable") == 0) thresh = IPMI_LOWER_NON_RECOVERABLE; else goto out_err; } else goto out_err; if (strcasecmp(val[2], "going-high") == 0) value_dir = IPMI_GOING_HIGH; else if (strcasecmp(val[2], "going-low") == 0) value_dir = IPMI_GOING_LOW; else goto out_err; if (strcasecmp(val[3], "assertion") == 0) dir = IPMI_ASSERTION; else if (strcasecmp(val[3], "deassertion") == 0) dir = IPMI_DEASSERTION; else goto out_err; } else goto out_err; if (rdir) *rdir = dir; if (rvalue_dir) *rvalue_dir = value_dir; if (rthresh) *rthresh = thresh; return; out_err: info->cmdlang->errstr = "Invalid threshold event"; info->cmdlang->err = EINVAL; info->cmdlang->location = "cmdlang.c(ipmi_cmdlang_get_threshold_ev)"; } void ipmi_cmdlang_get_threshold(char *str, enum ipmi_thresh_e *rthresh, ipmi_cmd_info_t *info) { enum ipmi_thresh_e thresh; for (thresh = IPMI_LOWER_NON_CRITICAL; thresh <= IPMI_UPPER_NON_RECOVERABLE; thresh++) { if (strcmp(str, ipmi_get_threshold_string(thresh)) == 0) { if (rthresh) *rthresh = thresh; return; } } if (strcasecmp(str, "un") == 0) thresh = IPMI_UPPER_NON_CRITICAL; else if (strcasecmp(str, "uc") == 0) thresh = IPMI_UPPER_CRITICAL; else if (strcasecmp(str, "ur") == 0) thresh = IPMI_UPPER_NON_RECOVERABLE; else if (strcasecmp(str, "ln") == 0) thresh = IPMI_LOWER_NON_CRITICAL; else if (strcasecmp(str, "lc") == 0) thresh = IPMI_LOWER_CRITICAL; else if (strcasecmp(str, "lr") == 0) thresh = IPMI_LOWER_NON_RECOVERABLE; else goto out_err; if (rthresh) *rthresh = thresh; return; out_err: info->cmdlang->errstr = "Invalid threshold"; info->cmdlang->err = EINVAL; info->cmdlang->location = "cmdlang.c(ipmi_cmdlang_get_threshold)"; } void ipmi_cmdlang_get_discrete_ev(char *str, int *roffset, enum ipmi_event_dir_e *rdir, ipmi_cmd_info_t *info) { int offset; enum ipmi_event_dir_e dir; char val[4][20]; int len; int vc; char *end; vc = 0; for (;;) { char *start, *end; while (issep(*str)) str++; if (! *str) break; if (vc == 4) goto out_err; start = str; while (*str && (!issep(*str))) str++; end = str; len = end - start; if (len >= 20) goto out_err; memcpy(val[vc], start, len); val[vc][len] = '\0'; vc++; } if (vc == 1) { /* One value, it is a compressed form. */ offset = strtoul(val[0], &end, 0); if (end == val[0]) goto out_err; if ((*end == 'd') || (*end == 'D')) dir = IPMI_DEASSERTION; else if ((*end == 'a') || (*end == 'A')) dir = IPMI_ASSERTION; else goto out_err; end++; if (*end != '\0') goto out_err; } else if (vc == 2) { offset = strtoul(val[0], &end, 0); if ((end == val[0]) || (*end != '\0')) goto out_err; if (strcasecmp(val[1], "deassertion") == 0) dir = IPMI_DEASSERTION; else if (strcasecmp(val[1], "assertion") == 0) dir = IPMI_ASSERTION; else goto out_err; } else goto out_err; if (roffset) *roffset = offset; if (rdir) *rdir = dir; return; out_err: info->cmdlang->errstr = "Invalid discrete event"; info->cmdlang->err = EINVAL; info->cmdlang->location = "cmdlang.c(ipmi_cmdlang_get_discrete_event)"; } typedef struct ipmi_cmdlang_event_entry_s ipmi_cmdlang_event_entry_t; struct ipmi_cmdlang_event_entry_s { char *name; enum ipmi_cmdlang_out_types type; char *value; unsigned int len; int level; ipmi_cmdlang_event_entry_t *next; }; struct ipmi_cmdlang_event_s { int curr_level; ipmi_cmd_info_t *info; ipmi_cmdlang_event_entry_t *head, *tail; ipmi_cmdlang_event_entry_t *curr; }; void event_out(ipmi_cmdlang_t *cmdlang, const char *name, const char *value) { ipmi_cmdlang_event_entry_t *entry; ipmi_cmdlang_event_t *event = cmdlang->user_data; if (cmdlang->err) return; entry = ipmi_mem_alloc(sizeof(*entry)); if (!entry) goto out_nomem; entry->name = ipmi_strdup(name); if (!entry->name) { ipmi_mem_free(entry); goto out_nomem; } entry->type = IPMI_CMDLANG_STRING; if (value) { entry->len = strlen(value); entry->value = ipmi_strdup(value); if (!entry->value) { ipmi_mem_free(entry->name); ipmi_mem_free(entry); goto out_nomem; } } else { entry->len = 0; entry->value = NULL; } entry->level = event->curr_level; entry->next = NULL; if (event->head) { event->tail->next = entry; event->tail = entry; } else { event->head = entry; event->tail = entry; } return; out_nomem: cmdlang->err = ENOMEM; cmdlang->errstr = "Out of memory"; cmdlang->location = "cmdlang.c(event_out)"; } static void event_out_binary(ipmi_cmdlang_t *cmdlang, const char *name, const char *value, unsigned int len) { ipmi_cmdlang_event_entry_t *entry; ipmi_cmdlang_event_t *event = cmdlang->user_data; if (cmdlang->err) return; entry = ipmi_mem_alloc(sizeof(*entry)); if (!entry) goto out_nomem; entry->name = ipmi_strdup(name); if (!entry->name) { ipmi_mem_free(entry); goto out_nomem; } entry->type = IPMI_CMDLANG_BINARY; entry->len = len; if (len > 0) { entry->value = ipmi_mem_alloc(len); if (!entry->value) { ipmi_mem_free(entry->name); ipmi_mem_free(entry); goto out_nomem; } memcpy(entry->value, value, len); } else entry->value = NULL; entry->level = event->curr_level; entry->next = NULL; if (event->head) { event->tail->next = entry; event->tail = entry; } else { event->head = entry; event->tail = entry; } return; out_nomem: cmdlang->err = ENOMEM; cmdlang->errstr = "Out of memory"; cmdlang->location = "cmdlang.c(event_out_binary)"; } static void event_out_unicode(ipmi_cmdlang_t *cmdlang, const char *name, const char *value, unsigned int len) { ipmi_cmdlang_event_entry_t *entry; ipmi_cmdlang_event_t *event = cmdlang->user_data; if (cmdlang->err) return; entry = ipmi_mem_alloc(sizeof(*entry)); if (!entry) goto out_nomem; entry->name = ipmi_strdup(name); if (!entry->name) { ipmi_mem_free(entry); goto out_nomem; } entry->type = IPMI_CMDLANG_UNICODE; entry->len = len; if (len > 0) { entry->value = ipmi_mem_alloc(len); if (!entry->value) { ipmi_mem_free(entry->name); ipmi_mem_free(entry); goto out_nomem; } memcpy(entry->value, value, len); } else entry->value = NULL; entry->level = event->curr_level; entry->next = NULL; if (event->head) { event->tail->next = entry; event->tail = entry; } else { event->head = entry; event->tail = entry; } return; out_nomem: cmdlang->err = ENOMEM; cmdlang->errstr = "Out of memory"; cmdlang->location = "cmdlang.c(event_out_binary)"; } void event_up(ipmi_cmdlang_t *cmdlang) { ipmi_cmdlang_event_t *event = cmdlang->user_data; if (cmdlang->err) return; event->curr_level--; } void event_down(ipmi_cmdlang_t *cmdlang) { ipmi_cmdlang_event_t *event = cmdlang->user_data; if (cmdlang->err) return; event->curr_level++; } void event_done(ipmi_cmdlang_t *cmdlang) { ipmi_cmdlang_event_entry_t *entry; ipmi_cmdlang_event_t *event = cmdlang->user_data; ipmi_cmd_info_t *info = event->info; if (strlen(info->cmdlang->objstr) == 0) { ipmi_mem_free(info->cmdlang->objstr); cmdlang->objstr = NULL; } if (info->cmdlang->err) { ipmi_cmdlang_global_err(cmdlang->objstr, cmdlang->location, cmdlang->errstr, cmdlang->err); if (cmdlang->errstr_dynalloc) ipmi_mem_free(cmdlang->errstr); } else { ipmi_cmdlang_report_event(event); } if (cmdlang->objstr) ipmi_mem_free(cmdlang->objstr); ipmi_mem_free(cmdlang); entry = event->head; while (entry) { event->head = entry->next; ipmi_mem_free(entry->name); if (entry->value) ipmi_mem_free(entry->value); ipmi_mem_free(entry); entry = event->head; } ipmi_mem_free(event); } ipmi_cmd_info_t * ipmi_cmdlang_alloc_event_info(void) { ipmi_cmd_info_t *cmdinfo = NULL; ipmi_cmdlang_event_t *event; int rv; cmdinfo = ipmi_mem_alloc(sizeof(*cmdinfo)); if (!cmdinfo) return NULL; memset(cmdinfo, 0, sizeof(*cmdinfo)); cmdinfo->usecount = 1; rv = ipmi_create_lock_os_hnd(cmdlang_os_hnd, &cmdinfo->lock); if (rv) { ipmi_mem_free(cmdinfo); return NULL; } cmdinfo->cmdlang = ipmi_mem_alloc(sizeof(*cmdinfo->cmdlang)); if (!cmdinfo->cmdlang) { ipmi_destroy_lock(cmdinfo->lock); ipmi_mem_free(cmdinfo); return NULL; } memset(cmdinfo->cmdlang, 0, sizeof(*cmdinfo->cmdlang)); cmdinfo->cmdlang->objstr = ipmi_mem_alloc(IPMI_MAX_NAME_LEN); if (!cmdinfo->cmdlang->objstr) { ipmi_mem_free(cmdinfo->cmdlang); ipmi_destroy_lock(cmdinfo->lock); ipmi_mem_free(cmdinfo); return NULL; } cmdinfo->cmdlang->objstr[0] = '\0'; cmdinfo->cmdlang->objstr_len = IPMI_MAX_NAME_LEN; cmdinfo->cmdlang->user_data = ipmi_mem_alloc(sizeof(ipmi_cmdlang_event_t)); if (!cmdinfo->cmdlang->user_data) { ipmi_mem_free(cmdinfo->cmdlang->objstr); ipmi_mem_free(cmdinfo->cmdlang); ipmi_destroy_lock(cmdinfo->lock); ipmi_mem_free(cmdinfo); return NULL; } event = cmdinfo->cmdlang->user_data; memset(event, 0, sizeof(*event)); event->info = cmdinfo; cmdinfo->cmdlang->out = event_out; cmdinfo->cmdlang->down = event_down; cmdinfo->cmdlang->out_binary = event_out_binary; cmdinfo->cmdlang->out_unicode = event_out_unicode; cmdinfo->cmdlang->up = event_up; cmdinfo->cmdlang->done = event_done; return cmdinfo; } /* Move to the first field. */ void ipmi_cmdlang_event_restart(ipmi_cmdlang_event_t *event) { event->curr = event->head; } /* Returns true if successful, false if no more fields left. */ 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) { ipmi_cmdlang_event_entry_t *curr = event->curr; if (!curr) return 0; if (level) *level = curr->level; if (name) *name = curr->name; if (value) *value = curr->value; if (type) *type = curr->type; if (len) *len = curr->len; event->curr = curr->next; return 1; } int ipmi_cmdlang_get_argc(ipmi_cmd_info_t *info) { return info->argc; } char ** ipmi_cmdlang_get_argv(ipmi_cmd_info_t *info) { return info->argv; } int ipmi_cmdlang_get_curr_arg(ipmi_cmd_info_t *info) { return info->curr_arg; } ipmi_cmdlang_t * ipmi_cmdinfo_get_cmdlang(ipmi_cmd_info_t *info) { return info->cmdlang; } static void evinfo(ipmi_cmd_info_t *cmd_info) { ipmi_cmdlang_t *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info); int curr_arg = ipmi_cmdlang_get_curr_arg(cmd_info); int argc = ipmi_cmdlang_get_argc(cmd_info); char **argv = ipmi_cmdlang_get_argv(cmd_info); int do_evinfo; if ((argc - curr_arg) < 1) { cmdlang->errstr = "True or False not entered"; cmdlang->err = EINVAL; goto out_err; } ipmi_cmdlang_get_bool(argv[curr_arg], &do_evinfo, cmd_info); if (cmdlang->err) { cmdlang->errstr = "True or False not entered"; cmdlang->err = EINVAL; goto out_err; } ipmi_cmdlang_set_evinfo(do_evinfo); ipmi_cmdlang_out(cmd_info, "event info set", NULL); return; out_err: cmdlang->location = "cmdlang.c(evinfo)"; } static void debug(ipmi_cmd_info_t *cmd_info) { ipmi_cmdlang_t *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info); int curr_arg = ipmi_cmdlang_get_curr_arg(cmd_info); int argc = ipmi_cmdlang_get_argc(cmd_info); char **argv = ipmi_cmdlang_get_argv(cmd_info); char *type; int val; if ((argc - curr_arg) < 2) { cmdlang->errstr = "Not enough parameters"; cmdlang->err = EINVAL; goto out_err; } type = argv[curr_arg]; curr_arg++; ipmi_cmdlang_get_bool(argv[curr_arg], &val, cmd_info); if (cmdlang->err) { cmdlang->errstr = "Invalid boolean setting"; cmdlang->err = EINVAL; goto out_err; } if (strcmp(type, "msg") == 0) { if (val) DEBUG_MSG_ENABLE(); else DEBUG_MSG_DISABLE(); } else if (strcmp(type, "msgerr") == 0) { if (val) DEBUG_MSG_ERR_ENABLE(); else DEBUG_MSG_ERR_DISABLE(); } else if (strcmp(type, "rawmsg") == 0) { if (val) DEBUG_RAWMSG_ENABLE(); else DEBUG_RAWMSG_DISABLE(); } else if (strcmp(type, "locks") == 0) { if (val) DEBUG_LOCKS_ENABLE(); else DEBUG_LOCKS_DISABLE(); } else if (strcmp(type, "events") == 0) { if (val) DEBUG_EVENTS_ENABLE(); else DEBUG_EVENTS_DISABLE(); } else if (strcmp(type, "con0") == 0) { if (val) DEBUG_CON_FAIL_ENABLE(0); else DEBUG_CON_FAIL_DISABLE(0); } else if (strcmp(type, "con1") == 0) { if (val) DEBUG_CON_FAIL_ENABLE(1); else DEBUG_CON_FAIL_DISABLE(1); } else if (strcmp(type, "con2") == 0) { if (val) DEBUG_CON_FAIL_ENABLE(2); else DEBUG_CON_FAIL_DISABLE(2); } else if (strcmp(type, "con3") == 0) { if (val) DEBUG_CON_FAIL_ENABLE(3); else DEBUG_CON_FAIL_DISABLE(3); } else { cmdlang->errstr = "Invalid debug setting"; cmdlang->err = EINVAL; goto out_err; } ipmi_cmdlang_out(cmd_info, "Debugging set", NULL); return; out_err: if (cmdlang->err) cmdlang->location = "cmdlang.c(debug)"; } static ipmi_cmdlang_init_t cmds_global[] = { { "evinfo", NULL, "true | false - Enable/disable printing info about the object" " when an event is reported on it (such as entity info, domain" " info, etc.)", evinfo, NULL, NULL }, { "debug", NULL, " true | false - " " Turn on/off the specific debugging. The debugging types are:" " msg, rawmsg, events, con0, con1, con2, con3. This is primarily" " for designers of OpenIPMI trying to debug problems.", debug, NULL, NULL }, }; #define CMDS_GLOBAL_LEN (sizeof(cmds_global)/sizeof(ipmi_cmdlang_init_t)) int ipmi_cmdlang_domain_init(os_handler_t *os_hnd); int ipmi_cmdlang_con_init(os_handler_t *os_hnd); int ipmi_cmdlang_entity_init(os_handler_t *os_hnd); int ipmi_cmdlang_mc_init(os_handler_t *os_hnd); int ipmi_cmdlang_pet_init(os_handler_t *os_hnd); int ipmi_cmdlang_lanparm_init(os_handler_t *os_hnd); int ipmi_cmdlang_solparm_init(os_handler_t *os_hnd); int ipmi_cmdlang_fru_init(os_handler_t *os_hnd); void ipmi_cmdlang_lanparm_shutdown(); void ipmi_cmdlang_solparm_shutdown(); int ipmi_cmdlang_pef_init(os_handler_t *os_hnd); void ipmi_cmdlang_pef_shutdown(); int ipmi_cmdlang_sensor_init(os_handler_t *os_hnd); int ipmi_cmdlang_control_init(os_handler_t *os_hnd); int ipmi_cmdlang_sel_init(os_handler_t *os_hnd); int ipmi_cmdlang_init(os_handler_t *os_hnd) { int rv; rv = ipmi_cmdlang_domain_init(os_hnd); if (rv) return rv; rv = ipmi_cmdlang_con_init(os_hnd); if (rv) return rv; rv = ipmi_cmdlang_entity_init(os_hnd); if (rv) return rv; rv = ipmi_cmdlang_mc_init(os_hnd); if (rv) return rv; rv = ipmi_cmdlang_pet_init(os_hnd); if (rv) return rv; rv = ipmi_cmdlang_lanparm_init(os_hnd); if (rv) return rv; rv = ipmi_cmdlang_solparm_init(os_hnd); if (rv) return rv; rv = ipmi_cmdlang_fru_init(os_hnd); if (rv) return rv; rv = ipmi_cmdlang_pef_init(os_hnd); if (rv) return rv; rv = ipmi_cmdlang_sensor_init(os_hnd); if (rv) return rv; rv = ipmi_cmdlang_control_init(os_hnd); if (rv) return rv; rv = ipmi_cmdlang_sel_init(os_hnd); if (rv) return rv; rv = ipmi_cmdlang_reg_table(cmds_global, CMDS_GLOBAL_LEN); if (rv) return rv; return 0; } static void cleanup_level(ipmi_cmdlang_cmd_t *cmds) { ipmi_cmdlang_cmd_t *cmd; while (cmds) { cmd = cmds; cmds = cmd->next; if (cmd->subcmds) cleanup_level(cmd->subcmds); ipmi_mem_free(cmd); } } void ipmi_cmdlang_cleanup(void) { ipmi_cmdlang_pef_shutdown(); ipmi_cmdlang_lanparm_shutdown(); ipmi_cmdlang_solparm_shutdown(); cleanup_level(cmd_list); } static int do_evinfo = 0; void ipmi_cmdlang_set_evinfo(int evinfo) { do_evinfo = evinfo; } int ipmi_cmdlang_get_evinfo(void) { return do_evinfo; }