Main Page | Class List | Directories | File List | Class Members | File Members

cmdlang.c

Go to the documentation of this file.
00001 /*
00002  * cmdlang.c
00003  *
00004  * A command interpreter for OpenIPMI
00005  *
00006  * Author: MontaVista Software, Inc.
00007  *         Corey Minyard <minyard@mvista.com>
00008  *         source@mvista.com
00009  *
00010  * Copyright 2004 MontaVista Software Inc.
00011  *
00012  *  This program is free software; you can redistribute it and/or
00013  *  modify it under the terms of the GNU Lesser General Public License
00014  *  as published by the Free Software Foundation; either version 2 of
00015  *  the License, or (at your option) any later version.
00016  *
00017  *
00018  *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
00019  *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00020  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00021  *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00022  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00023  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00024  *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00025  *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
00026  *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00027  *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00028  *
00029  *  You should have received a copy of the GNU Lesser General Public
00030  *  License along with this program; if not, write to the Free
00031  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00032  */
00033 
00034 
00035 #include <errno.h>
00036 #include <string.h>
00037 #include <ctype.h>
00038 #include <stdlib.h>
00039 #include <stdio.h>
00040 #include <sys/types.h>
00041 #include <sys/socket.h>
00042 #include <netdb.h>
00043 #include <OpenIPMI/ipmiif.h>
00044 #include <OpenIPMI/ipmi_cmdlang.h>
00045 #include <OpenIPMI/ipmi_pet.h>
00046 #include <OpenIPMI/ipmi_lanparm.h>
00047 #include <OpenIPMI/ipmi_solparm.h>
00048 #include <OpenIPMI/ipmi_fru.h>
00049 #include <OpenIPMI/ipmi_pef.h>
00050 #include <OpenIPMI/ipmi_auth.h>
00051 #include <OpenIPMI/ipmi_debug.h>
00052 #include <OpenIPMI/ipmi_mc.h>
00053 
00054 /* Internal includes, do not use in your programs */
00055 #include <OpenIPMI/internal/ipmi_locks.h>
00056 #include <OpenIPMI/internal/ipmi_malloc.h>
00057 
00058 /*
00059  * This is the value passed to a command handler.
00060  */
00061 struct ipmi_cmd_info_s
00062 {
00063     void               *handler_data; /* From cb_data in the cmd reg */
00064     int                curr_arg;      /* Argument you should start at */
00065     int                argc;          /* Total number of arguments */
00066     char               **argv;        /* The arguments */
00067 
00068     /* Only allow one writer at a time */
00069     ipmi_lock_t        *lock;
00070 
00071     /* The cmdlang structure the user passed in.  Use this for output
00072        and error reporting. */
00073     ipmi_cmdlang_t     *cmdlang;
00074 
00075     /* The matching cmd structure for the command being executed.  May
00076        be NULL if no command is being processed. */
00077     ipmi_cmdlang_cmd_t *cmd;
00078 
00079     /* Refcount for the structure. */
00080     unsigned int       usecount;
00081 
00082     /* For use by the user commands */
00083     void *data;
00084 
00085     /* Used to know if the command generated output. */
00086     int did_output;
00087 };
00088 
00089 
00090 struct ipmi_cmdlang_cmd_s
00091 {
00092     char                  *name;
00093     char                  *help;
00094     ipmi_help_finisher_cb help_finish;
00095 
00096     /* Only one of handler or subcmds may be non-NULL. */
00097     ipmi_cmdlang_handler_cb handler;
00098     ipmi_cmdlang_cmd_t      *subcmds;
00099 
00100     void                    *handler_data;
00101 
00102     /* Used for a linked list. */
00103     ipmi_cmdlang_cmd_t *next;
00104 };
00105 
00106 static os_handler_t *cmdlang_os_hnd;
00107 
00108 /* Parse a string of the form [domain][(class)][.obj] and return each
00109    of the strings in the given string pointers. */
00110 static int
00111 parse_ipmi_objstr(char *str,
00112                   char **domain,
00113                   char **class,
00114                   char **obj)
00115 {
00116     int  i;
00117     char *class_start = NULL, *class_end = NULL;
00118 
00119     for (i=0; str[i]; i++) {
00120         if (str[i] == '(') {
00121             if (class_start)
00122                 /* Only one '(' allowed. */
00123                 return EINVAL;
00124             class_start = str + i;
00125         } else if (str[i] == ')') {
00126             if (class_start) {
00127                 /* a ')' only means something after a '('. */
00128                 class_end = str + i;
00129                 i++;
00130                 break;
00131             }
00132         }
00133     }
00134 
00135     if (str[i]) {
00136         if (str[i] != '.')
00137             return EINVAL;
00138     }
00139 
00140     if (class_start) {
00141         if (!class_end)
00142             /* If class starts, must see the end paren. */
00143             return EINVAL;
00144         *class_start = '\0';
00145         *class_end = '\0';
00146         *class = class_start + 1;
00147     } else {
00148         *class = NULL;
00149     }
00150 
00151     if (strlen(str) == 0)
00152         *domain = NULL;
00153     else
00154         *domain = str;
00155 
00156     if (str[i])
00157         *obj = str + i + 1;
00158     else
00159         *obj = NULL;
00160 
00161     return 0;
00162 }
00163 
00164 
00165 /*
00166  * Handling for iterating domains.
00167  */
00168 
00169 typedef struct domain_iter_info_s
00170 {
00171     char               *cmpstr;
00172     ipmi_domain_ptr_cb handler;
00173     void               *cb_data;
00174     ipmi_cmd_info_t    *cmd_info;
00175 } domain_iter_info_t;
00176 
00177 static void
00178 for_each_domain_handler(ipmi_domain_t *domain, void *cb_data)
00179 {
00180     domain_iter_info_t *info = cb_data;
00181     ipmi_cmd_info_t    *cmd_info = info->cmd_info;
00182     char               domain_name[IPMI_DOMAIN_NAME_LEN];
00183 
00184     if (cmd_info->cmdlang->err)
00185         return;
00186 
00187     ipmi_domain_get_name(domain, domain_name, sizeof(domain_name));
00188     if ((!info->cmpstr) || (strcmp(info->cmpstr, domain_name) == 0))
00189         info->handler(domain, info->cb_data);
00190 }
00191 
00192 static void
00193 for_each_domain(ipmi_cmd_info_t    *cmd_info,
00194                 char               *domain,
00195                 char               *class,
00196                 char               *obj,
00197                 ipmi_domain_ptr_cb handler,
00198                 void               *cb_data)
00199 {
00200     domain_iter_info_t info;
00201 
00202     if (class || obj) {
00203         cmd_info->cmdlang->errstr = "Invalid domain";
00204         cmd_info->cmdlang->err = EINVAL;
00205         cmd_info->cmdlang->location = "cmdlang.c(for_each_domain)";
00206         return;
00207     }
00208 
00209     info.cmpstr = domain;
00210     info.handler = handler;
00211     info.cb_data = cb_data;
00212     info.cmd_info = cmd_info;
00213     ipmi_domain_iterate_domains(for_each_domain_handler, &info);
00214 }
00215 
00216 void
00217 ipmi_cmdlang_domain_handler(ipmi_cmd_info_t *cmd_info)
00218 {
00219     char *domain, *class, *obj;
00220     int  rv;
00221 
00222     if (cmd_info->curr_arg >= cmd_info->argc) {
00223         domain = class = obj = NULL;
00224     } else {
00225         rv = parse_ipmi_objstr(cmd_info->argv[cmd_info->curr_arg],
00226                                &domain, &class, &obj);
00227         if (rv) {
00228             cmd_info->cmdlang->errstr = "Invalid domain";
00229             cmd_info->cmdlang->err = rv;
00230             cmd_info->cmdlang->location
00231                 = "cmdlang.c(ipmi_cmdlang_domain_handler)";
00232             return;
00233         }
00234         cmd_info->curr_arg++;
00235     }
00236 
00237     for_each_domain(cmd_info, domain, class, obj,
00238                     cmd_info->handler_data, cmd_info);
00239 }
00240 
00241 
00242 /*
00243  * Handling for iterating PETs.
00244  */
00245 typedef struct pet_iter_info_s
00246 {
00247     char            *cmdstr;
00248     ipmi_pet_ptr_cb handler;
00249     void            *cb_data;
00250     ipmi_cmd_info_t *cmd_info;
00251 } pet_iter_info_t;
00252 
00253 static void
00254 for_each_pet_handler(ipmi_pet_t *pet, void *cb_data)
00255 {
00256     pet_iter_info_t *info = cb_data;
00257     ipmi_cmd_info_t *cmd_info = info->cmd_info;
00258     ipmi_cmdlang_t  *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
00259     char            name[IPMI_PET_NAME_LEN];
00260     char            *c;
00261 
00262     if (cmdlang->err)
00263         return;
00264 
00265     ipmi_pet_get_name(pet, name, sizeof(name));
00266 
00267     c = strrchr(name, '.');
00268     if (!c)
00269         goto out_err;
00270     c++;
00271     if ((! info->cmdstr) || (strcmp(info->cmdstr, c) == 0))
00272         info->handler(pet, info->cb_data);
00273     return;
00274 
00275  out_err:
00276     ipmi_cmdlang_global_err(name,
00277                             "cmdlang.c(for_each_pet_handler)",
00278                             "Bad PET name", EINVAL);
00279 }
00280 
00281 static void
00282 for_each_pet_domain_handler(ipmi_domain_t *domain, void *cb_data)
00283 {
00284     ipmi_pet_iterate_pets(domain, for_each_pet_handler, cb_data);
00285 }
00286 
00287 static void
00288 for_each_pet(ipmi_cmd_info_t *cmd_info,
00289              char            *domain,
00290              char            *class,
00291              char            *obj,
00292              ipmi_pet_ptr_cb handler,
00293              void            *cb_data)
00294 {
00295     pet_iter_info_t info;
00296 
00297     if (class) {
00298         cmd_info->cmdlang->errstr = "Invalid PET";
00299         cmd_info->cmdlang->err = EINVAL;
00300         cmd_info->cmdlang->location = "cmdlang.c(for_each_pet)";
00301         return;
00302     }
00303 
00304     info.handler = handler;
00305     info.cb_data = cb_data;
00306     info.cmd_info = cmd_info;
00307     info.cmdstr = obj;
00308     for_each_domain(cmd_info, domain, NULL, NULL,
00309                     for_each_pet_domain_handler, &info);
00310 }
00311 
00312 void
00313 ipmi_cmdlang_pet_handler(ipmi_cmd_info_t *cmd_info)
00314 {
00315     char *domain, *class, *obj;
00316 
00317     if (cmd_info->curr_arg >= cmd_info->argc) {
00318         domain = class = obj = NULL;
00319     } else {
00320         domain = cmd_info->argv[cmd_info->curr_arg];
00321         class = NULL;
00322         obj = strrchr(domain, '.');
00323         if (!obj) {
00324             cmd_info->cmdlang->errstr = "Invalid PET";
00325             cmd_info->cmdlang->err = EINVAL;
00326             cmd_info->cmdlang->location
00327                 = "cmdlang.c(ipmi_cmdlang_pet_handler)";
00328             return;
00329         }
00330         *obj = '\0';
00331         obj++;
00332         cmd_info->curr_arg++;
00333     }
00334 
00335     for_each_pet(cmd_info, domain, class, obj, cmd_info->handler_data,
00336                  cmd_info);
00337 }
00338 
00339 /*
00340  * Handling for iterating LANPARMs.
00341  */
00342 typedef struct lanparm_iter_info_s
00343 {
00344     char                *cmdstr;
00345     ipmi_lanparm_ptr_cb handler;
00346     void                *cb_data;
00347     ipmi_cmd_info_t     *cmd_info;
00348 } lanparm_iter_info_t;
00349 
00350 static void
00351 for_each_lanparm_handler(ipmi_lanparm_t *lanparm, void *cb_data)
00352 {
00353     lanparm_iter_info_t *info = cb_data;
00354     ipmi_cmd_info_t *cmd_info = info->cmd_info;
00355     ipmi_cmdlang_t  *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
00356     char            name[IPMI_LANPARM_NAME_LEN];
00357     char            *c;
00358 
00359     if (cmdlang->err)
00360         return;
00361 
00362     ipmi_lanparm_get_name(lanparm, name, sizeof(name));
00363 
00364     c = strrchr(name, '.');
00365     if (!c)
00366         goto out_err;
00367     c++;
00368     if ((! info->cmdstr) || (strcmp(info->cmdstr, c) == 0))
00369         info->handler(lanparm, info->cb_data);
00370     return;
00371 
00372  out_err:
00373     ipmi_cmdlang_global_err(name,
00374                             "cmdlang.c(for_each_lanparm_handler)",
00375                             "Bad LANPARM name", EINVAL);
00376 }
00377 
00378 static void
00379 for_each_lanparm_domain_handler(ipmi_domain_t *domain, void *cb_data)
00380 {
00381     ipmi_lanparm_iterate_lanparms(domain, for_each_lanparm_handler, cb_data);
00382 }
00383 
00384 static void
00385 for_each_lanparm(ipmi_cmd_info_t *cmd_info,
00386              char            *domain,
00387              char            *class,
00388              char            *obj,
00389              ipmi_lanparm_ptr_cb handler,
00390              void            *cb_data)
00391 {
00392     lanparm_iter_info_t info;
00393 
00394     if (class) {
00395         cmd_info->cmdlang->errstr = "Invalid LANPARM";
00396         cmd_info->cmdlang->err = EINVAL;
00397         cmd_info->cmdlang->location = "cmdlang.c(for_each_lanparm)";
00398         return;
00399     }
00400 
00401     info.handler = handler;
00402     info.cb_data = cb_data;
00403     info.cmd_info = cmd_info;
00404     info.cmdstr = obj;
00405     for_each_domain(cmd_info, domain, NULL, NULL,
00406                     for_each_lanparm_domain_handler, &info);
00407 }
00408 
00409 void
00410 ipmi_cmdlang_lanparm_handler(ipmi_cmd_info_t *cmd_info)
00411 {
00412     char *domain, *class, *obj;
00413 
00414     if (cmd_info->curr_arg >= cmd_info->argc) {
00415         domain = class = obj = NULL;
00416     } else {
00417         domain = cmd_info->argv[cmd_info->curr_arg];
00418         class = NULL;
00419         obj = strrchr(domain, '.');
00420         if (!obj) {
00421             cmd_info->cmdlang->errstr = "Invalid LANPARM";
00422             cmd_info->cmdlang->err = EINVAL;
00423             cmd_info->cmdlang->location
00424                 = "cmdlang.c(ipmi_cmdlang_lanparm_handler)";
00425             return;
00426         }
00427         *obj = '\0';
00428         obj++;
00429         cmd_info->curr_arg++;
00430     }
00431 
00432     for_each_lanparm(cmd_info, domain, class, obj, cmd_info->handler_data,
00433                  cmd_info);
00434 }
00435 
00436 /*
00437  * Handling for iterating SOLPARMs.
00438  */
00439 typedef struct solparm_iter_info_s
00440 {
00441     char                *cmdstr;
00442     ipmi_solparm_ptr_cb handler;
00443     void                *cb_data;
00444     ipmi_cmd_info_t     *cmd_info;
00445 } solparm_iter_info_t;
00446 
00447 static void
00448 for_each_solparm_handler(ipmi_solparm_t *solparm, void *cb_data)
00449 {
00450     solparm_iter_info_t *info = cb_data;
00451     ipmi_cmd_info_t *cmd_info = info->cmd_info;
00452     ipmi_cmdlang_t  *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
00453     char            name[IPMI_SOLPARM_NAME_LEN];
00454     char            *c;
00455 
00456     if (cmdlang->err)
00457         return;
00458 
00459     ipmi_solparm_get_name(solparm, name, sizeof(name));
00460 
00461     c = strrchr(name, '.');
00462     if (!c)
00463         goto out_err;
00464     c++;
00465     if ((! info->cmdstr) || (strcmp(info->cmdstr, c) == 0))
00466         info->handler(solparm, info->cb_data);
00467     return;
00468 
00469  out_err:
00470     ipmi_cmdlang_global_err(name,
00471                             "cmdlang.c(for_each_solparm_handler)",
00472                             "Bad SOLPARM name", EINVAL);
00473 }
00474 
00475 static void
00476 for_each_solparm_domain_handler(ipmi_domain_t *domain, void *cb_data)
00477 {
00478     ipmi_solparm_iterate_solparms(domain, for_each_solparm_handler, cb_data);
00479 }
00480 
00481 static void
00482 for_each_solparm(ipmi_cmd_info_t *cmd_info,
00483              char            *domain,
00484              char            *class,
00485              char            *obj,
00486              ipmi_solparm_ptr_cb handler,
00487              void            *cb_data)
00488 {
00489     solparm_iter_info_t info;
00490 
00491     if (class) {
00492         cmd_info->cmdlang->errstr = "Invalid SOLPARM";
00493         cmd_info->cmdlang->err = EINVAL;
00494         cmd_info->cmdlang->location = "cmdlang.c(for_each_solparm)";
00495         return;
00496     }
00497 
00498     info.handler = handler;
00499     info.cb_data = cb_data;
00500     info.cmd_info = cmd_info;
00501     info.cmdstr = obj;
00502     for_each_domain(cmd_info, domain, NULL, NULL,
00503                     for_each_solparm_domain_handler, &info);
00504 }
00505 
00506 void
00507 ipmi_cmdlang_solparm_handler(ipmi_cmd_info_t *cmd_info)
00508 {
00509     char *domain, *class, *obj;
00510 
00511     if (cmd_info->curr_arg >= cmd_info->argc) {
00512         domain = class = obj = NULL;
00513     } else {
00514         domain = cmd_info->argv[cmd_info->curr_arg];
00515         class = NULL;
00516         obj = strrchr(domain, '.');
00517         if (!obj) {
00518             cmd_info->cmdlang->errstr = "Invalid SOLPARM";
00519             cmd_info->cmdlang->err = EINVAL;
00520             cmd_info->cmdlang->location
00521                 = "cmdlang.c(ipmi_cmdlang_solparm_handler)";
00522             return;
00523         }
00524         *obj = '\0';
00525         obj++;
00526         cmd_info->curr_arg++;
00527     }
00528 
00529     for_each_solparm(cmd_info, domain, class, obj, cmd_info->handler_data,
00530                  cmd_info);
00531 }
00532 
00533 /*
00534  * Handling for iterating PEFs.
00535  */
00536 typedef struct pef_iter_info_s
00537 {
00538     char            *cmdstr;
00539     ipmi_pef_ptr_cb handler;
00540     void            *cb_data;
00541     ipmi_cmd_info_t *cmd_info;
00542 } pef_iter_info_t;
00543 
00544 static void
00545 for_each_pef_handler(ipmi_pef_t *pef, void *cb_data)
00546 {
00547     pef_iter_info_t *info = cb_data;
00548     ipmi_cmd_info_t *cmd_info = info->cmd_info;
00549     ipmi_cmdlang_t  *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
00550     char            name[IPMI_PEF_NAME_LEN];
00551     char            *c;
00552 
00553     if (cmdlang->err)
00554         return;
00555 
00556     ipmi_pef_get_name(pef, name, sizeof(name));
00557 
00558     c = strrchr(name, '.');
00559     if (!c)
00560         goto out_err;
00561     c++;
00562     if ((! info->cmdstr) || (strcmp(info->cmdstr, c) == 0))
00563         info->handler(pef, info->cb_data);
00564     return;
00565 
00566  out_err:
00567     ipmi_cmdlang_global_err(name,
00568                             "cmdlang.c(for_each_pef_handler)",
00569                             "Bad PEF name", EINVAL);
00570 }
00571 
00572 static void
00573 for_each_pef_domain_handler(ipmi_domain_t *domain, void *cb_data)
00574 {
00575     ipmi_pef_iterate_pefs(domain, for_each_pef_handler, cb_data);
00576 }
00577 
00578 static void
00579 for_each_pef(ipmi_cmd_info_t *cmd_info,
00580              char            *domain,
00581              char            *class,
00582              char            *obj,
00583              ipmi_pef_ptr_cb handler,
00584              void            *cb_data)
00585 {
00586     pef_iter_info_t info;
00587 
00588     if (class) {
00589         cmd_info->cmdlang->errstr = "Invalid PEF";
00590         cmd_info->cmdlang->err = EINVAL;
00591         cmd_info->cmdlang->location = "cmdlang.c(for_each_pef)";
00592         return;
00593     }
00594 
00595     info.handler = handler;
00596     info.cb_data = cb_data;
00597     info.cmd_info = cmd_info;
00598     info.cmdstr = obj;
00599     for_each_domain(cmd_info, domain, NULL, NULL,
00600                     for_each_pef_domain_handler, &info);
00601 }
00602 
00603 void
00604 ipmi_cmdlang_pef_handler(ipmi_cmd_info_t *cmd_info)
00605 {
00606     char *domain, *class, *obj;
00607 
00608     if (cmd_info->curr_arg >= cmd_info->argc) {
00609         domain = class = obj = NULL;
00610     } else {
00611         domain = cmd_info->argv[cmd_info->curr_arg];
00612         class = NULL;
00613         obj = strrchr(domain, '.');
00614         if (!obj) {
00615             cmd_info->cmdlang->errstr = "Invalid PEF";
00616             cmd_info->cmdlang->err = EINVAL;
00617             cmd_info->cmdlang->location
00618                 = "cmdlang.c(ipmi_cmdlang_pef_handler)";
00619             return;
00620         }
00621         *obj = '\0';
00622         obj++;
00623         cmd_info->curr_arg++;
00624     }
00625 
00626     for_each_pef(cmd_info, domain, class, obj, cmd_info->handler_data,
00627                  cmd_info);
00628 }
00629 
00630 
00631 /*
00632  * Handling for iterating FRUs.
00633  */
00634 typedef struct fru_iter_info_s
00635 {
00636     char            *cmdstr;
00637     ipmi_fru_ptr_cb handler;
00638     void            *cb_data;
00639     ipmi_cmd_info_t *cmd_info;
00640 } fru_iter_info_t;
00641 
00642 static void
00643 for_each_fru_handler(ipmi_fru_t *fru, void *cb_data)
00644 {
00645     fru_iter_info_t *info = cb_data;
00646     ipmi_cmd_info_t *cmd_info = info->cmd_info;
00647     ipmi_cmdlang_t  *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
00648     char            name[IPMI_FRU_NAME_LEN];
00649     char            *c;
00650 
00651     if (cmdlang->err)
00652         return;
00653 
00654     ipmi_fru_get_name(fru, name, sizeof(name));
00655 
00656     c = strrchr(name, '.');
00657     if (!c)
00658         goto out_err;
00659     c++;
00660     if ((! info->cmdstr) || (strcmp(info->cmdstr, c) == 0))
00661         info->handler(fru, info->cb_data);
00662     return;
00663 
00664  out_err:
00665     ipmi_cmdlang_global_err(name,
00666                             "cmdlang.c(for_each_fru_handler)",
00667                             "Bad FRU name", EINVAL);
00668 }
00669 
00670 static void
00671 for_each_fru_domain_handler(ipmi_domain_t *domain, void *cb_data)
00672 {
00673     ipmi_fru_iterate_frus(domain, for_each_fru_handler, cb_data);
00674 }
00675 
00676 static void
00677 for_each_fru(ipmi_cmd_info_t *cmd_info,
00678              char            *domain,
00679              char            *class,
00680              char            *obj,
00681              ipmi_fru_ptr_cb handler,
00682              void            *cb_data)
00683 {
00684     fru_iter_info_t info;
00685 
00686     if (class) {
00687         cmd_info->cmdlang->errstr = "Invalid FRU";
00688         cmd_info->cmdlang->err = EINVAL;
00689         cmd_info->cmdlang->location = "cmdlang.c(for_each_fru)";
00690         return;
00691     }
00692 
00693     info.handler = handler;
00694     info.cb_data = cb_data;
00695     info.cmd_info = cmd_info;
00696     info.cmdstr = obj;
00697     for_each_domain(cmd_info, domain, NULL, NULL,
00698                     for_each_fru_domain_handler, &info);
00699 }
00700 
00701 void
00702 ipmi_cmdlang_fru_handler(ipmi_cmd_info_t *cmd_info)
00703 {
00704     char *domain, *class, *obj;
00705 
00706     if (cmd_info->curr_arg >= cmd_info->argc) {
00707         domain = class = obj = NULL;
00708     } else {
00709         domain = cmd_info->argv[cmd_info->curr_arg];
00710         class = NULL;
00711         obj = strrchr(domain, '.');
00712         if (!obj) {
00713             cmd_info->cmdlang->errstr = "Invalid FRU";
00714             cmd_info->cmdlang->err = EINVAL;
00715             cmd_info->cmdlang->location
00716                 = "cmdlang.c(ipmi_cmdlang_fru_handler)";
00717             return;
00718         }
00719         *obj = '\0';
00720         obj++;
00721         cmd_info->curr_arg++;
00722     }
00723 
00724     for_each_fru(cmd_info, domain, class, obj, cmd_info->handler_data,
00725                  cmd_info);
00726 }
00727 
00728 
00729 /*
00730  * Handling for iterating entities.
00731  */
00732 typedef struct entity_iter_info_s
00733 {
00734     char               *cmpstr;
00735     ipmi_entity_ptr_cb handler;
00736     void               *cb_data;
00737     ipmi_cmd_info_t    *cmd_info;
00738 } entity_iter_info_t;
00739 
00740 static void
00741 for_each_entity_handler(ipmi_entity_t *entity, void *cb_data)
00742 {
00743     entity_iter_info_t *info = cb_data;
00744     ipmi_cmd_info_t    *cmd_info = info->cmd_info;
00745     char               entity_name[IPMI_ENTITY_NAME_LEN];
00746     char               *c, *c2;
00747 
00748     if (cmd_info->cmdlang->err)
00749         return;
00750 
00751     ipmi_entity_get_name(entity, entity_name, sizeof(entity_name));
00752     c = strchr(entity_name, '(');
00753     if (!c)
00754         goto out_err;
00755     c++;
00756     c2 = strchr(c, ')');
00757     if (!c2)
00758         goto out_err;
00759     *c2 = '\0';
00760     if ((!info->cmpstr) || (strcmp(info->cmpstr, c) == 0)) {
00761         *c2 = ')';
00762         info->handler(entity, info->cb_data);
00763     } else
00764         *c2 = ')';
00765     return;
00766 
00767  out_err:
00768     ipmi_cmdlang_global_err(entity_name,
00769                             "cmdlang.c(for_each_entity_handler)",
00770                             "Bad entity name", EINVAL);
00771 }
00772 
00773 static void
00774 for_each_entity_domain_handler(ipmi_domain_t *domain, void *cb_data)
00775 {
00776     ipmi_domain_iterate_entities(domain, for_each_entity_handler, cb_data);
00777 }
00778 
00779 static void
00780 for_each_entity(ipmi_cmd_info_t    *cmd_info,
00781                 char               *domain,
00782                 char               *class,
00783                 char               *obj,
00784                 ipmi_entity_ptr_cb handler,
00785                 void               *cb_data)
00786 {
00787     entity_iter_info_t info;
00788 
00789     if (obj) {
00790         cmd_info->cmdlang->errstr = "Invalid entity";
00791         cmd_info->cmdlang->err = EINVAL;
00792         cmd_info->cmdlang->location = "cmdlang.c(for_each_entity)";
00793         return;
00794     }
00795 
00796     info.cmpstr = class;
00797     info.handler = handler;
00798     info.cb_data = cb_data;
00799     info.cmd_info = cmd_info;
00800     for_each_domain(cmd_info, domain, NULL, NULL,
00801                     for_each_entity_domain_handler, &info);
00802 }
00803 
00804 void
00805 ipmi_cmdlang_entity_handler(ipmi_cmd_info_t *cmd_info)
00806 {
00807     char *domain, *class, *obj;
00808     int  rv;
00809 
00810     if (cmd_info->curr_arg >= cmd_info->argc) {
00811         domain = class = obj = NULL;
00812     } else {
00813         rv = parse_ipmi_objstr(cmd_info->argv[cmd_info->curr_arg],
00814                                &domain, &class, &obj);
00815         if (rv) {
00816             cmd_info->cmdlang->errstr = "Invalid entity";
00817             cmd_info->cmdlang->err = rv;
00818             cmd_info->cmdlang->location
00819                 = "cmdlang.c(ipmi_cmdlang_entity_handler)";
00820             return;
00821         }
00822         cmd_info->curr_arg++;
00823     }
00824 
00825     for_each_entity(cmd_info, domain, class, obj,
00826                     cmd_info->handler_data, cmd_info);
00827 }
00828 
00829 
00830 /*
00831  * Handling for iterating sensors.
00832  */
00833 typedef struct sensor_iter_info_s
00834 {
00835     char               *cmpstr;
00836     ipmi_sensor_ptr_cb handler;
00837     void               *cb_data;
00838     ipmi_cmd_info_t    *cmd_info;
00839 } sensor_iter_info_t;
00840 
00841 static void
00842 for_each_sensor_handler(ipmi_entity_t *entity,
00843                         ipmi_sensor_t *sensor,
00844                         void          *cb_data)
00845 {
00846     sensor_iter_info_t *info = cb_data;
00847     char               sensor_name[IPMI_SENSOR_NAME_LEN];
00848     char               *c;
00849 
00850     ipmi_sensor_get_name(sensor, sensor_name, sizeof(sensor_name));
00851     c = strchr(sensor_name, '(');
00852     if (!c)
00853         goto out_err;
00854     c = strchr(c, ')');
00855     if (!c)
00856         goto out_err;
00857     c = strchr(c, '.');
00858     if (!c)
00859         goto out_err;
00860     c++;
00861     if ((!info->cmpstr) || (strcmp(info->cmpstr, c) == 0))
00862         info->handler(sensor, info->cb_data);
00863     return;
00864 
00865  out_err:
00866     ipmi_cmdlang_global_err(sensor_name,
00867                             "cmdlang.c(for_each_sensor_handler)",
00868                             "Bad sensor name", EINVAL);
00869 }
00870 
00871 static void
00872 for_each_sensor_entity_handler(ipmi_entity_t *entity, void *cb_data)
00873 {
00874     ipmi_entity_iterate_sensors(entity, for_each_sensor_handler, cb_data);
00875 }
00876 
00877 static void
00878 for_each_sensor(ipmi_cmd_info_t    *cmd_info,
00879                 char               *domain,
00880                 char               *class,
00881                 char               *obj,
00882                 ipmi_sensor_ptr_cb handler,
00883                 void               *cb_data)
00884 {
00885     sensor_iter_info_t info;
00886 
00887     info.cmpstr = obj;
00888     info.handler = handler;
00889     info.cb_data = cb_data;
00890     info.cmd_info = cmd_info;
00891     for_each_entity(cmd_info, domain, class, NULL,
00892                     for_each_sensor_entity_handler, &info);
00893 }
00894 
00895 void
00896 ipmi_cmdlang_sensor_handler(ipmi_cmd_info_t *cmd_info)
00897 {
00898     char *domain, *class, *obj;
00899     int  rv;
00900 
00901     if (cmd_info->curr_arg >= cmd_info->argc) {
00902         domain = class = obj = NULL;
00903     } else {
00904         rv = parse_ipmi_objstr(cmd_info->argv[cmd_info->curr_arg],
00905                                &domain, &class, &obj);
00906         if (rv) {
00907             cmd_info->cmdlang->errstr = "Invalid sensor";
00908             cmd_info->cmdlang->err = rv;
00909             cmd_info->cmdlang->location
00910                 = "cmdlang.c(ipmi_cmdlang_sensor_handler)";
00911             return;
00912         }
00913         cmd_info->curr_arg++;
00914     }
00915 
00916     for_each_sensor(cmd_info, domain, class, obj,
00917                     cmd_info->handler_data, cmd_info);
00918 }
00919 
00920 
00921 /*
00922  * Handling for iterating controls.
00923  */
00924 typedef struct control_iter_info_s
00925 {
00926     char                *cmpstr;
00927     ipmi_control_ptr_cb handler;
00928     void                *cb_data;
00929     ipmi_cmd_info_t     *cmd_info;
00930 } control_iter_info_t;
00931 
00932 static void
00933 for_each_control_handler(ipmi_entity_t  *entity,
00934                          ipmi_control_t *control,
00935                          void           *cb_data)
00936 {
00937     control_iter_info_t *info = cb_data;
00938     char                control_name[IPMI_CONTROL_NAME_LEN];
00939     char               *c;
00940 
00941     ipmi_control_get_name(control, control_name, sizeof(control_name));
00942     c = strchr(control_name, '(');
00943     if (!c)
00944         goto out_err;
00945     c = strchr(c, ')');
00946     if (!c)
00947         goto out_err;
00948     c = strchr(c, '.');
00949     if (!c)
00950         goto out_err;
00951     c++;
00952     if ((!info->cmpstr) || (strcmp(info->cmpstr, c) == 0))
00953         info->handler(control, info->cb_data);
00954     return;
00955 
00956  out_err:
00957     ipmi_cmdlang_global_err(control_name,
00958                             "cmdlang.c(for_each_control_handler)",
00959                             "Bad control name", EINVAL);
00960 }
00961 
00962 static void
00963 for_each_control_entity_handler(ipmi_entity_t *entity, void *cb_data)
00964 {
00965     ipmi_entity_iterate_controls(entity, for_each_control_handler, cb_data);
00966 }
00967 
00968 static void
00969 for_each_control(ipmi_cmd_info_t     *cmd_info,
00970                  char                *domain,
00971                  char                *class,
00972                  char                *obj,
00973                  ipmi_control_ptr_cb handler,
00974                  void                *cb_data)
00975 {
00976     control_iter_info_t info;
00977 
00978     info.cmpstr = obj;
00979     info.handler = handler;
00980     info.cb_data = cb_data;
00981     info.cmd_info = cmd_info;
00982     for_each_entity(cmd_info, domain, class, NULL,
00983                     for_each_control_entity_handler, &info);
00984 }
00985 
00986 void
00987 ipmi_cmdlang_control_handler(ipmi_cmd_info_t *cmd_info)
00988 {
00989     char *domain, *class, *obj;
00990     int  rv;
00991 
00992     if (cmd_info->curr_arg >= cmd_info->argc) {
00993         domain = class = obj = NULL;
00994     } else {
00995         rv = parse_ipmi_objstr(cmd_info->argv[cmd_info->curr_arg],
00996                                &domain, &class, &obj);
00997         if (rv) {
00998             cmd_info->cmdlang->errstr = "Invalid control";
00999             cmd_info->cmdlang->err = rv;
01000             cmd_info->cmdlang->location
01001                 = "cmdlang.c(ipmi_cmdlang_control_handler)";
01002             return;
01003         }
01004         cmd_info->curr_arg++;
01005     }
01006 
01007     for_each_control(cmd_info, domain, class, obj,
01008                      cmd_info->handler_data, cmd_info);
01009 }
01010 
01011 
01012 /*
01013  * Handling for iterating mcs.
01014  */
01015 typedef struct mc_iter_info_s
01016 {
01017     char            *cmpstr;
01018     ipmi_mc_ptr_cb  handler;
01019     void            *cb_data;
01020     ipmi_cmd_info_t *cmd_info;
01021 } mc_iter_info_t;
01022 
01023 static void
01024 for_each_mc_handler(ipmi_domain_t *domain, ipmi_mc_t *mc, void *cb_data)
01025 {
01026     mc_iter_info_t  *info = cb_data;
01027     char            mc_name[IPMI_MC_NAME_LEN];
01028     char            *c, *c2;
01029 
01030     ipmi_mc_get_name(mc, mc_name, sizeof(mc_name));
01031     c = strchr(mc_name, '(');
01032     if (!c)
01033         goto out_err;
01034     c++;
01035     c2 = strchr(c, ')');
01036     if (!c2)
01037         goto out_err;
01038     *c2 = '\0';
01039     if ((!info->cmpstr) || (strcmp(info->cmpstr, c) == 0)) {
01040         *c2 = ')';
01041         info->handler(mc, info->cb_data);
01042     } else
01043         *c2 = ')';
01044     return;
01045 
01046  out_err:
01047     ipmi_cmdlang_global_err(mc_name,
01048                             "cmdlang.c(for_each_entity_handler)",
01049                             "Bad mc name", EINVAL);
01050 }
01051 
01052 static void
01053 for_each_mc_domain_handler(ipmi_domain_t *domain, void *cb_data)
01054 {
01055     ipmi_domain_iterate_mcs(domain, for_each_mc_handler, cb_data);
01056 }
01057 
01058 static void
01059 for_each_mc(ipmi_cmd_info_t *cmd_info,
01060             char            *domain,
01061             char            *class,
01062             char            *obj,
01063             ipmi_mc_ptr_cb  handler,
01064             void            *cb_data)
01065 {
01066     mc_iter_info_t info;
01067 
01068     if (obj) {
01069         cmd_info->cmdlang->errstr = "Invalid MC";
01070         cmd_info->cmdlang->err = EINVAL;
01071         cmd_info->cmdlang->location = "cmdlang.c(for_each_mc)";
01072         return;
01073     }
01074 
01075     info.cmpstr = class;
01076     info.handler = handler;
01077     info.cb_data = cb_data;
01078     info.cmd_info = cmd_info;
01079     for_each_domain(cmd_info, domain, NULL, NULL,
01080                     for_each_mc_domain_handler, &info);
01081 }
01082 
01083 void
01084 ipmi_cmdlang_mc_handler(ipmi_cmd_info_t *cmd_info)
01085 {
01086     char *domain, *class, *obj;
01087     int  rv;
01088 
01089     if (cmd_info->curr_arg >= cmd_info->argc) {
01090         domain = class = obj = NULL;
01091     } else {
01092         rv = parse_ipmi_objstr(cmd_info->argv[cmd_info->curr_arg],
01093                                &domain, &class, &obj);
01094         if (rv) {
01095             cmd_info->cmdlang->errstr = "Invalid MC";
01096             cmd_info->cmdlang->err = rv;
01097             cmd_info->cmdlang->location
01098                 = "cmdlang.c(ipmi_cmdlang_mc_handler)";
01099             return;
01100         }
01101         cmd_info->curr_arg++;
01102     }
01103 
01104     for_each_mc(cmd_info, domain, class, obj, cmd_info->handler_data,
01105                 cmd_info);
01106 }
01107 
01108 
01109 /*
01110  * Handling for iterating connections.
01111  */
01112 typedef struct conn_iter_info_s
01113 {
01114     int                    conn;
01115     ipmi_connection_ptr_cb handler;
01116     void                   *cb_data;
01117     ipmi_cmd_info_t        *cmd_info;
01118 } conn_iter_info_t;
01119 
01120 static void
01121 for_each_conn_handler(ipmi_domain_t *domain, int conn, void *cb_data)
01122 {
01123     conn_iter_info_t *info = cb_data;
01124 
01125     if ((info->conn == -1) || (info->conn == conn))
01126         info->handler(domain, conn, info->cb_data);
01127 }
01128 
01129 static void
01130 for_each_conn_domain_handler(ipmi_domain_t *domain, void *cb_data)
01131 {
01132     ipmi_domain_iterate_connections(domain, for_each_conn_handler, cb_data);
01133 }
01134 
01135 static void
01136 for_each_connection(ipmi_cmd_info_t        *cmd_info,
01137                     char                   *domain,
01138                     char                   *class,
01139                     char                   *obj,
01140                     ipmi_connection_ptr_cb handler,
01141                     void                   *cb_data)
01142 {
01143     conn_iter_info_t info;
01144     char             *endptr;
01145 
01146     if (class) {
01147         cmd_info->cmdlang->errstr = "Invalid connection";
01148         cmd_info->cmdlang->err = EINVAL;
01149         cmd_info->cmdlang->location = "cmdlang.c(for_each_connection)";
01150         return;
01151     }
01152 
01153     if (obj) {
01154         if (!isdigit(obj[0])) {
01155             cmd_info->cmdlang->errstr = "Invalid connection number";
01156             cmd_info->cmdlang->err = EINVAL;
01157             cmd_info->cmdlang->location = "cmdlang.c(for_each_connection)";
01158             return;
01159         }
01160         info.