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

ipmish.c

Go to the documentation of this file.
00001 /*
00002  * ipmish.c
00003  *
00004  * MontaVista IPMI basic UI to use the main UI code.
00005  *
00006  * Author: MontaVista Software, Inc.
00007  *         Corey Minyard <minyard@mvista.com>
00008  *         source@mvista.com
00009  *
00010  * Copyright 2002,2003 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 #include <config.h>
00035 
00036 #include <stdio.h>
00037 #include <stdlib.h>
00038 #include <string.h>
00039 #include <ctype.h>
00040 #include <errno.h>
00041 #include <termios.h>
00042 #include <unistd.h>
00043 #include <signal.h>
00044 #include <OpenIPMI/selector.h>
00045 #include <OpenIPMI/ipmi_conn.h>
00046 #include <OpenIPMI/ipmi_err.h>
00047 #include <OpenIPMI/ipmi_posix.h>
00048 #include <OpenIPMI/ipmi_glib.h>
00049 #include <OpenIPMI/ipmi_cmdlang.h>
00050 #include <OpenIPMI/ipmi_debug.h>
00051 #include <editline/readline.h>
00052 
00053 #ifdef HAVE_GLIB
00054 #include <glib.h>
00055 #endif
00056 
00057 /* Internal includes, do not use in your programs */
00058 #include <OpenIPMI/internal/ipmi_malloc.h>
00059 
00060 #ifdef HAVE_UCDSNMP
00061 # ifdef HAVE_NETSNMP
00062 #  include <net-snmp/net-snmp-config.h>
00063 #  include <net-snmp/net-snmp-includes.h>
00064 # elif defined(HAVE_ALT_UCDSNMP_DIR)
00065 #  include <ucd-snmp/asn1.h>
00066 #  include <ucd-snmp/snmp_api.h>
00067 #  include <ucd-snmp/snmp.h>
00068 # else
00069 #  include <asn1.h>
00070 #  include <snmp_api.h>
00071 #  include <snmp.h>
00072 # endif
00073 #endif
00074 
00075 extern os_handler_t ipmi_debug_os_handlers;
00076 selector_t *debug_sel;
00077 
00078 os_hnd_fd_id_t *term_fd_id;
00079 
00080 static int done = 0;
00081 static int evcount = 0;
00082 static int handling_input = 0;
00083 static int cmd_redisp = 1;
00084 
00085 static void user_input_ready(int fd, void *data, os_hnd_fd_id_t *id);
00086 
00087 static void
00088 redraw_cmdline(int force)
00089 {
00090     int redisp = cmd_redisp;
00091 
00092     if (force)
00093         redisp = 1;
00094     if (!done && handling_input && redisp) {
00095         rl_redisplay();
00096         fflush(stdout);
00097     }
00098 }
00099 
00100 static void
00101 my_vlog(os_handler_t         *handler,
00102         const char           *format,
00103         enum ipmi_log_type_e log_type,
00104         va_list              ap)
00105 {
00106     int do_nl = 1;
00107     static int last_was_cont = 0;
00108 
00109     if (handling_input && !last_was_cont && !done && cmd_redisp) 
00110         fputc('\n', stdout);
00111 
00112     last_was_cont = 0;
00113     switch(log_type) {
00114     case IPMI_LOG_INFO:
00115         printf("INFO: ");
00116         break;
00117 
00118     case IPMI_LOG_WARNING:
00119         printf("WARN: ");
00120         break;
00121 
00122     case IPMI_LOG_SEVERE:
00123         printf("SEVR: ");
00124         break;
00125 
00126     case IPMI_LOG_FATAL:
00127         printf("FATL: ");
00128         break;
00129 
00130     case IPMI_LOG_ERR_INFO:
00131         printf("EINF: ");
00132         break;
00133 
00134     case IPMI_LOG_DEBUG_START:
00135         do_nl = 0;
00136         last_was_cont = 1;
00137         /* FALLTHROUGH */
00138     case IPMI_LOG_DEBUG:
00139         printf("DEBG: ");
00140         break;
00141 
00142     case IPMI_LOG_DEBUG_CONT:
00143         last_was_cont = 1;
00144         do_nl = 0;
00145         /* FALLTHROUGH */
00146     case IPMI_LOG_DEBUG_END:
00147         break;
00148     }
00149 
00150     vprintf(format, ap);
00151     if (do_nl) {
00152         printf("\n");
00153         redraw_cmdline(0);
00154     }
00155 }
00156 
00157 #ifdef HAVE_GLIB
00158 void glib_handle_log(const gchar *log_domain,
00159                      GLogLevelFlags log_level,
00160                      const gchar *message,
00161                      gpointer user_data)
00162 {
00163     char *pfx = "";
00164 
00165     if (log_level & G_LOG_LEVEL_ERROR)
00166         pfx = "FATL: ";
00167     else if (log_level & G_LOG_LEVEL_CRITICAL)
00168         pfx = "SEVR: ";
00169     else if (log_level & G_LOG_LEVEL_WARNING)
00170         pfx = "WARN: ";
00171     else if (log_level & G_LOG_LEVEL_MESSAGE)
00172         pfx = "EINF: ";
00173     else if (log_level & G_LOG_LEVEL_INFO)
00174         pfx = "INFO: ";
00175     else if (log_level & G_LOG_LEVEL_DEBUG)
00176         pfx = "DEBG: ";
00177     printf("%s%s\n", pfx, message);
00178     redraw_cmdline(0);
00179 }
00180 #endif
00181 
00182 static void
00183 enable_term_fd(ipmi_cmdlang_t *cmdlang)
00184 {
00185     int rv;
00186 
00187     if (term_fd_id)
00188         return;
00189 
00190     rv = cmdlang->os_hnd->add_fd_to_wait_for(cmdlang->os_hnd, 0, 
00191                                              user_input_ready,
00192                                              cmdlang,
00193                                              NULL, &term_fd_id);
00194     if (rv) {
00195         fprintf(stderr, "error enabling terminal handler, giving up\n");
00196         exit(1);
00197     }
00198 }
00199 
00200 static void
00201 disable_term_fd(ipmi_cmdlang_t *cmdlang)
00202 {
00203     int rv;
00204 
00205     if (!term_fd_id)
00206         return;
00207 
00208     rv = cmdlang->os_hnd->remove_fd_to_wait_for(cmdlang->os_hnd, term_fd_id);
00209     if (rv) {
00210         fprintf(stderr, "error removing terminal handler, giving up\n");
00211         exit(1);
00212     }
00213     term_fd_id = NULL;
00214 }
00215 
00216 #ifdef HAVE_UCDSNMP
00217 #define IPMI_OID_SIZE 9
00218 static oid ipmi_oid[IPMI_OID_SIZE] = {1,3,6,1,4,1,3183,1,1};
00219 int snmp_input(int op,
00220                struct snmp_session *session,
00221                int reqid,
00222                struct snmp_pdu *pdu,
00223                void *magic)
00224 {
00225     struct sockaddr_in   *src_ip;
00226     uint32_t             specific;
00227     struct variable_list *var;
00228 
00229 #ifdef HAVE_NETSNMP
00230     if (op != NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE)
00231         goto out;
00232 #else
00233     if (op != RECEIVED_MESSAGE)
00234         goto out;
00235 #endif
00236     if (pdu->command != SNMP_MSG_TRAP)
00237         goto out;
00238     if (snmp_oid_compare(ipmi_oid, IPMI_OID_SIZE,
00239                          pdu->enterprise, pdu->enterprise_length)
00240         != 0)
00241     {
00242         goto out;
00243     }
00244     if (pdu->trap_type != SNMP_TRAP_ENTERPRISESPECIFIC)
00245         goto out;
00246 
00247     src_ip = (struct sockaddr_in *) &pdu->agent_addr;
00248     specific = pdu->specific_type;
00249 
00250     var = pdu->variables;
00251     if (var == NULL)
00252         goto out;
00253     if (var->type != ASN_OCTET_STR)
00254         goto out;
00255     if (snmp_oid_compare(ipmi_oid, IPMI_OID_SIZE, var->name, var->name_length)
00256         != 0)
00257     {
00258         goto out;
00259     }
00260     if (var->val_len < 46)
00261         goto out;
00262     
00263     ipmi_handle_snmp_trap_data(src_ip,
00264                                sizeof(*src_ip),
00265                                IPMI_EXTERN_ADDR_IP,
00266                                specific,
00267                                var->val.string,
00268                                var->val_len);
00269 
00270  out:
00271     return 1;
00272 }
00273 
00274 #ifdef HAVE_NETSNMP
00275 static int
00276 snmp_pre_parse(netsnmp_session * session, netsnmp_transport *transport,
00277                void *transport_data, int transport_data_length)
00278 {
00279     return 1;
00280 }
00281 #else
00282 static int
00283 snmp_pre_parse(struct snmp_session *session, snmp_ipaddr from)
00284 {
00285     return 1;
00286 }
00287 #endif
00288 
00289 static struct snmp_session *snmp_session;
00290 
00291 static void
00292 snmp_add_read_fds(selector_t     *sel,
00293                   int            *num_fds,
00294                   fd_set         *fdset,
00295                   struct timeval *timeout,
00296                   int            *timeout_invalid,
00297                   void           *cb_data)
00298 {
00299     snmp_select_info(num_fds, fdset, timeout, timeout_invalid);
00300 }
00301 
00302 static void
00303 snmp_check_read_fds(selector_t *sel,
00304                     fd_set     *fds,
00305                     void       *cb_data)
00306 {
00307     snmp_read(fds);
00308 }
00309 
00310 static void
00311 snmp_check_timeout(selector_t *sel,
00312                    void       *cb_data)
00313 {
00314     snmp_timeout();
00315 }
00316 
00317 static int
00318 snmp_init(selector_t *sel)
00319 {
00320     struct snmp_session session;
00321 #ifdef HAVE_NETSNMP
00322     netsnmp_transport *transport = NULL;
00323     static char *snmp_default_port = "udp:162";
00324 
00325     netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID,
00326                            NETSNMP_DS_LIB_MIB_ERRORS,
00327                            0);
00328 
00329     init_snmp("ipmish");
00330 
00331     transport = netsnmp_tdomain_transport(snmp_default_port, 1, "udp");
00332     if (!transport) {
00333         snmp_sess_perror("ipmish", &session);
00334         return -1;
00335     }
00336 #else
00337     void *transport = NULL;
00338 #endif
00339     snmp_sess_init(&session);
00340     session.peername = SNMP_DEFAULT_PEERNAME;
00341     session.version = SNMP_DEFAULT_VERSION;
00342     session.community_len = SNMP_DEFAULT_COMMUNITY_LEN;
00343     session.retries = SNMP_DEFAULT_RETRIES;
00344     session.timeout = SNMP_DEFAULT_TIMEOUT;
00345     session.local_port = SNMP_TRAP_PORT;
00346     session.callback = snmp_input;
00347     session.callback_magic = transport;
00348     session.authenticator = NULL;
00349     session.isAuthoritative = SNMP_SESS_UNKNOWNAUTH;
00350 
00351 #ifdef HAVE_NETSNMP
00352     snmp_session = snmp_add(&session, transport, snmp_pre_parse, NULL);
00353 #else
00354     snmp_session = snmp_open_ex(&session, snmp_pre_parse,
00355                                 NULL, NULL, NULL, NULL);
00356 #endif
00357     if (snmp_session == NULL) {
00358         snmp_sess_perror("ipmish", &session);
00359         return -1;
00360     }
00361 
00362     ipmi_sel_set_read_fds_handler(sel,
00363                                   snmp_add_read_fds,
00364                                   snmp_check_read_fds,
00365                                   snmp_check_timeout,
00366                                   NULL);
00367 
00368     return 0;
00369 }
00370 #endif /* HAVE_UCDSNMP */
00371 
00372 typedef struct out_data_s
00373 {
00374     FILE *stream;
00375     int  indent;
00376 } out_data_t;
00377 
00378 static int columns = 80;
00379 
00380 static void
00381 out_help(FILE *s, int indent, const char *name, const char *v)
00382 {
00383     int pos, endpos;
00384     const char *endword;
00385     const char *endspace;
00386 
00387     pos = fprintf(s, "%*s%s ", indent, "", name);
00388     while (*v) {
00389         endword = v;
00390         while (isspace(*endword)) {
00391             if (*endword == '\n') {
00392                 v = endword + 1;
00393                 fprintf(s, "\n%*s", indent+2, "");
00394                 pos = indent + 2;
00395             }
00396             endword++;
00397         }
00398         endspace = endword;
00399         while (*endword && !isspace(*endword))
00400             endword++;
00401         endpos = pos + endword - v;
00402         if (endpos > columns) {
00403             v = endspace;
00404             fprintf(s, "\n%*s", indent+2, "");
00405             pos = indent + 2;
00406         }
00407         fwrite(v, 1, endword-v, s);
00408         pos += endword - v;
00409         v = endword;
00410     }
00411     fputc('\n', s);
00412 }
00413 
00414 static void
00415 out_value(ipmi_cmdlang_t *info, const char *name, const char *value)
00416 {
00417     out_data_t *out_data = info->user_data;
00418 
00419     if (value) {
00420         if (info->help) {
00421             out_help(out_data->stream, out_data->indent*2, name, value);
00422         } else {
00423             fprintf(out_data->stream, "%*s%s: %s\n", out_data->indent*2, "",
00424                     name, value);
00425         }
00426     } else
00427         fprintf(out_data->stream, "%*s%s\n", out_data->indent*2, "", name);
00428     fflush(out_data->stream);
00429 }
00430 
00431 static void
00432 out_binary(ipmi_cmdlang_t *info, const char *name, const char *value,
00433            unsigned int len)
00434 {
00435     out_data_t *out_data = info->user_data;
00436     unsigned char *data = (unsigned char *) value;
00437     int indent2 = (out_data->indent * 2) + strlen(name) + 1;
00438     int i;
00439     char *sep = ":";
00440 
00441     if (info->help)
00442       sep = "";
00443 
00444     fprintf(out_data->stream, "%*s%s%s", out_data->indent*2, "", name, sep);
00445     for (i=0; i<len; i++) {
00446         if ((i != 0) && ((i % 8) == 0))
00447             fprintf(out_data->stream, "\n%*s", indent2, "");
00448         fprintf(out_data->stream, " 0x%2.2x", (data[i] & 0xff));
00449     }
00450     fprintf(out_data->stream, "\n");
00451     
00452     fflush(out_data->stream);
00453 }
00454 
00455 static void
00456 out_unicode(ipmi_cmdlang_t *info, const char *name, const char *value,
00457             unsigned int len)
00458 {
00459     out_binary(info, name, value, len);
00460 }
00461 
00462 static void
00463 down_level(ipmi_cmdlang_t *info)
00464 {
00465     out_data_t *out_data = info->user_data;
00466 
00467     out_data->indent++;
00468 }
00469 
00470 static void
00471 up_level(ipmi_cmdlang_t *info)
00472 {
00473     out_data_t *out_data = info->user_data;
00474 
00475     out_data->indent--;
00476 }
00477 
00478 static void cmd_done(ipmi_cmdlang_t *info);
00479 
00480 static out_data_t lout_data =
00481 {
00482     .stream = NULL,
00483     .indent = 0,
00484 };
00485 static char cmdlang_objstr[IPMI_MAX_NAME_LEN];
00486 static ipmi_cmdlang_t cmdlang =
00487 {
00488     .out = out_value,
00489     .out_binary = out_binary,
00490     .out_unicode = out_unicode,
00491     .down = down_level,
00492     .up = up_level,
00493     .done = cmd_done,
00494 
00495     .os_hnd = NULL,
00496 
00497     .user_data = &lout_data,
00498 
00499     .objstr = cmdlang_objstr,
00500     .objstr_len = sizeof(cmdlang_objstr),
00501 };
00502 
00503 int *done_ptr = NULL;
00504 
00505 static void
00506 cmd_done(ipmi_cmdlang_t *info)
00507 {
00508     out_data_t *out_data = info->user_data;
00509 
00510     if (info->err) {
00511         char errval[128];
00512         if (!info->location)
00513             info->location = "";
00514         if (strlen(info->objstr) == 0) {
00515             fprintf(out_data->stream, "error: %s: %s (0x%x, %s)\n",
00516                     info->location, info->errstr,
00517                     info->err,
00518                     ipmi_get_error_string(info->err, errval, sizeof(errval)));
00519         } else {
00520             fprintf(out_data->stream, "error: %s %s: %s (0x%x, %s)\n",
00521                     info->location, info->objstr, info->errstr,
00522                     info->err,
00523                     ipmi_get_error_string(info->err, errval, sizeof(errval)));
00524         }
00525         if (info->errstr_dynalloc)
00526             ipmi_mem_free(info->errstr);
00527         info->errstr_dynalloc = 0;
00528         info->errstr = NULL;
00529         info->location = NULL;
00530         info->objstr[0] = '\0';
00531         info->err = 0;
00532     }
00533 
00534     if (done_ptr) {
00535         *done_ptr = 1;
00536     } else {
00537         handling_input = 1;
00538         redraw_cmdline(1);
00539         enable_term_fd(info);
00540         fflush(out_data->stream);
00541     }
00542 }
00543 
00544 void
00545 ipmi_cmdlang_global_err(char *objstr,
00546                         char *location,
00547                         char *errstr,
00548                         int  errval)
00549 {
00550     if (handling_input && !done && cmd_redisp)
00551         fputc('\n', stdout);
00552     if (objstr)
00553         fprintf(stderr, "global error: %s %s: %s (0x%x)", location, objstr,
00554                 errstr, errval);
00555     else
00556         fprintf(stderr, "global error: %s: %s (0x%x)", location,
00557                 errstr, errval);
00558     evcount = 0;
00559     redraw_cmdline(0);
00560 }
00561 
00562 void
00563 ipmi_cmdlang_report_event(ipmi_cmdlang_event_t *event)
00564 {
00565     unsigned int                level, len;
00566     enum ipmi_cmdlang_out_types type;
00567     char                        *name, *value;
00568     int                         indent2;
00569     int                         i;
00570 
00571     if (handling_input && !done && cmd_redisp)
00572         fputc('\n', stdout);
00573     ipmi_cmdlang_event_restart(event);
00574     printf("Event\n");
00575     while (ipmi_cmdlang_event_next_field(event, &level, &type, &name, &len,
00576                                          &value))
00577     {
00578         switch (type) {
00579         case IPMI_CMDLANG_STRING:
00580             if (value)
00581                 printf("  %*s%s: %s\n", level*2, "", name, value);
00582             else
00583                 printf("  %*s%s\n", level*2, "", name);
00584             break;
00585 
00586         case IPMI_CMDLANG_BINARY:
00587         case IPMI_CMDLANG_UNICODE:
00588             indent2 = (level * 2) + strlen(name) + 1;
00589             printf("  %*s%s:", level*2, "", name);
00590             for (i=0; i<len; i++) {
00591                 if ((i != 0) && ((i % 8) == 0))
00592                     printf("\n  %*s", indent2, "");
00593                 printf(" 0x%2.2x", value[i] & 0xff);
00594             }
00595             printf("\n");
00596     
00597             fflush(stdout);
00598             break;
00599         }
00600     }
00601     evcount = 0;
00602     redraw_cmdline(0);
00603 }
00604 
00605 static void
00606 user_input_ready(int fd, void *data, os_hnd_fd_id_t *id)
00607 {
00608     rl_callback_read_char();
00609 }
00610 
00611 static void
00612 rl_ipmish_cb_handler(char *cmdline)
00613 {
00614     char *expansion = NULL;
00615     int result;
00616 
00617     if (cmdline == NULL) {
00618         done = 1;
00619         evcount = 1; /* Force a newline */
00620         return;
00621     }
00622     result = history_expand(cmdline, &expansion);
00623     if (result < 0 || result == 2) {
00624         fprintf(stderr, "%s\n", expansion);
00625     } else if (expansion && strlen(expansion)){
00626         cmdlang.err = 0;
00627         cmdlang.errstr = NULL;
00628         cmdlang.errstr_dynalloc = 0;
00629         cmdlang.location = NULL;
00630         handling_input = 0;
00631         add_history(expansion);
00632         ipmi_cmdlang_handle(&cmdlang, expansion);
00633     }
00634     if (expansion)
00635         free(expansion);
00636 }
00637 
00638 static void
00639 cleanup_term(void)
00640 {
00641     rl_callback_handler_remove();
00642     disable_term_fd(&cmdlang);
00643 }
00644 
00645 static void cleanup_sig(int sig);
00646 
00647 static void
00648 setup_term(os_handler_t *os_hnd)
00649 {
00650     signal(SIGINT, cleanup_sig);
00651     signal(SIGPIPE, cleanup_sig);
00652     signal(SIGUSR1, cleanup_sig);
00653     signal(SIGUSR2, cleanup_sig);
00654     signal(SIGPWR, cleanup_sig);
00655 
00656     stifle_history(500);
00657     rl_callback_handler_install("> ", rl_ipmish_cb_handler);
00658     lout_data.stream = stdout;
00659 
00660     cmdlang.os_hnd = os_hnd;
00661 }
00662 
00663 static void
00664 redisp_cmd(ipmi_cmd_info_t *cmd_info)
00665 {
00666     ipmi_cmdlang_t  *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
00667     int             curr_arg = ipmi_cmdlang_get_curr_arg(cmd_info);
00668     int             argc = ipmi_cmdlang_get_argc(cmd_info);
00669     char            **argv = ipmi_cmdlang_get_argv(cmd_info);
00670     int             redisp;
00671 
00672     if ((argc - curr_arg) < 1) {
00673         /* Not enough parameters */
00674         cmdlang->errstr = "Not enough parameters";
00675         cmdlang->err = EINVAL;
00676         goto out_err;
00677     }
00678 
00679     ipmi_cmdlang_get_bool(argv[curr_arg], &redisp, cmd_info);
00680     if (cmdlang->err) {
00681         cmdlang->errstr = "redisp setting invalid";
00682         goto out_err;
00683     }
00684     curr_arg++;
00685 
00686     cmd_redisp = redisp;
00687 
00688     ipmi_cmdlang_out(cmd_info, "redisp set", NULL);
00689 
00690  out_err:
00691     cmdlang->location = "ipmish.c(redisp_cmd)";
00692 }
00693 
00694 static void
00695 exit_cmd(ipmi_cmd_info_t *cmd_info)
00696 {
00697     done = 1;
00698     evcount = 0;
00699     ipmi_cmdlang_out(cmd_info, "Exiting ipmish", NULL);
00700 }
00701 
00702 static int read_nest = 0;
00703 static void
00704 read_cmd(ipmi_cmd_info_t *cmd_info)
00705 {
00706     ipmi_cmdlang_t *cmdlang = ipmi_cmdinfo_get_cmdlang(cmd_info);
00707     int            cdone;
00708     char           cmdline[256];
00709     FILE           *s;
00710     out_data_t     my_out_data;
00711     ipmi_cmdlang_t my_cmdlang = *cmdlang;
00712     int            curr_arg = ipmi_cmdlang_get_curr_arg(cmd_info);
00713     int            argc = ipmi_cmdlang_get_argc(cmd_info);
00714     char           **argv = ipmi_cmdlang_get_argv(cmd_info);
00715     int            *saved_done_ptr;
00716     char           *fname;
00717 
00718     if ((argc - curr_arg) < 1) {
00719         cmdlang->errstr = "No filename entered";
00720         cmdlang->err = EINVAL;
00721         goto out_err;
00722     }
00723 
00724     fname = argv[curr_arg];
00725     curr_arg++;
00726     s = fopen(fname, "r");
00727     if (!s) {
00728         cmdlang->errstr = "Unable to openfile";
00729         cmdlang->err = errno;
00730         goto out_err;
00731     }
00732 
00733     if (!read_nest) {
00734         handling_input = 0;
00735         disable_term_fd(cmdlang);
00736     }
00737     read_nest++;
00738     saved_done_ptr = done_ptr;
00739 
00740     /* not record the file's commands into history */
00741     while (fgets(cmdline, sizeof(cmdline), s)) {
00742         my_out_data.stream = stdout;
00743         my_out_data.indent = 0;
00744         my_cmdlang.user_data = &my_out_data;
00745         cdone = 0;
00746         done_ptr = &cdone;
00747         printf("> %s", cmdline);
00748         fflush(stdout);
00749         ipmi_cmdlang_handle(&my_cmdlang, cmdline);
00750         while (!cdone)
00751             cmdlang->os_hnd->perform_one_op(cmdlang->os_hnd, NULL);
00752         done_ptr = NULL;
00753     }
00754     fclose(s);
00755 
00756     done_ptr = saved_done_ptr;
00757     read_nest--;
00758     if (!read_nest) {
00759         handling_input = 1;
00760         enable_term_fd(cmdlang);
00761     }
00762 
00763     ipmi_cmdlang_out(cmd_info, "File read", fname);
00764 
00765     return;
00766 
00767  out_err:
00768     cmdlang->location = "ipmish.c(read_cmd)";
00769 }
00770 
00771 static void
00772 setup_cmds(void)
00773 {
00774     int rv;
00775 
00776     rv = ipmi_cmdlang_reg_cmd(NULL,
00777                               "redisp_cmd",
00778                               "on|off - If an asynchronous event comes in,"
00779                               " redisplay the current working command.  This"
00780                               " is on by default.",
00781                               redisp_cmd, NULL, NULL, NULL);
00782     if (rv) {
00783         fprintf(stderr, "Error adding exit command: 0x%x\n", rv);
00784         exit(1);
00785     }
00786 
00787     rv = ipmi_cmdlang_reg_cmd(NULL,
00788                               "exit",
00789                               "- leave the program",
00790                               exit_cmd, NULL, NULL, NULL);
00791     if (rv) {
00792         fprintf(stderr, "Error adding exit command: 0x%x\n", rv);
00793         exit(1);
00794     }
00795 
00796     rv = ipmi_cmdlang_reg_cmd(NULL,
00797                               "read",
00798                               "<file> - Read commands from the file and"
00799                               " execute them",
00800                               read_cmd, NULL, NULL, NULL);
00801     if (rv) {
00802         fprintf(stderr, "Error adding read command: 0x%x\n", rv);
00803         exit(1);
00804     }
00805 }
00806 
00807 static void
00808 domain_down(void *cb_data)
00809 {
00810     int *count = cb_data;
00811     (*count)--;
00812 }
00813 
00814 static void
00815 shutdown_domain_handler(ipmi_domain_t *domain, void *cb_data)
00816 {
00817     int *count = cb_data;
00818     int rv;
00819 
00820     rv = ipmi_domain_close(domain, domain_down, cb_data);
00821     if (!rv)
00822         (*count)++;
00823 }
00824 
00825 static void
00826 cleanup_sig(int sig)
00827 {
00828     fprintf(stderr, "Exiting due to signal %d\n", sig);
00829     done = 0;
00830     ipmi_domain_iterate_domains(shutdown_domain_handler, &done);
00831     while (done)
00832         cmdlang.os_hnd->perform_one_op(cmdlang.os_hnd, NULL);
00833     cleanup_term();
00834     exit(1);
00835 }
00836 
00837 typedef struct exec_list_s
00838 {
00839     char *str;
00840     struct exec_list_s *next;
00841 } exec_list_t;
00842 static exec_list_t *execs, *execs_tail;
00843 
00844 static void
00845 add_exec_str(char *str)
00846 {
00847     exec_list_t *e;
00848 
00849     e = malloc(sizeof(*e));
00850     if (!e) {
00851         fprintf(stderr, "Out of memory");
00852         exit(1);
00853     }
00854     e->str = str;
00855     e->next = NULL;
00856     if (execs)
00857         execs_tail->next = e;
00858     else
00859         execs = e;
00860     execs_tail = e;
00861 }
00862 
00863 static char *usage_str =
00864 "%s is a program that gives access to the OpenIPMI library from a command\n"
00865 "line.  It is designed to be script driven.  Format is:\n"
00866 "  %s [options]\n"
00867 "Options are:\n"
00868 "  --execute <string> - execute the given string at startup.  This may be\n"
00869 "    entered multiple times for multiple commands.\n"
00870 "  -x <string> - same as --execute\n"
00871 "  --dlock - turn on lock debugging.\n"
00872 "  --dmem - turn on memory debugging.\n"
00873 "  --drawmsg - turn on raw message tracing.\n"
00874 "  --dmsg - turn on message tracing debugging.\n"
00875 "  --dmsgerr - turn on printing out low-level message errors.\n"
00876 #ifdef HAVE_GLIB
00877 "  --glib - use glib for the OS handler.\n"
00878 #endif
00879 #ifdef HAVE_UCDSNMP
00880 "  --snmp - turn on SNMP trap handling.\n"
00881 #endif
00882 "  --help - This output.\n"
00883 ;
00884 static void usage(char *name)
00885 {
00886     fprintf(stderr, usage_str, name, name);
00887 }
00888 
00889 int
00890 main(int argc, char *argv[])
00891 {
00892     int              rv;
00893     int              curr_arg = 1;
00894     const char       *arg;
00895 #ifdef HAVE_UCDSNMP
00896     int              init_snmp = 0;
00897     selector_t       *sel;
00898 #endif
00899     os_handler_t     *os_hnd;
00900     int              use_debug_os = 0;
00901     char             *colstr;
00902 #ifdef HAVE_GLIB
00903     int              use_glib = 0;
00904 #endif
00905 
00906     colstr = getenv("COLUMNS");
00907     if (colstr) {
00908         int tmp = strtoul(colstr, NULL, 0);
00909         if (tmp) 
00910             columns = tmp;
00911     }
00912 
00913     while ((curr_arg < argc) && (argv[curr_arg][0] == '-')) {
00914         arg = argv[curr_arg];
00915         curr_arg++;
00916         if (strcmp(arg, "--") == 0) {
00917             break;
00918         } else if ((strcmp(arg, "-x") == 0) || (strcmp(arg, "--execute") == 0))
00919         {
00920             if (curr_arg >= argc) {
00921                 fprintf(stderr, "No option given for %s", arg);
00922                 usage(argv[0]);
00923                 return 1;
00924             }
00925             add_exec_str(argv[curr_arg]);
00926             curr_arg++;
00927         } else if (strcmp(arg, "--dlock") == 0) {
00928             DEBUG_LOCKS_ENABLE();
00929             use_debug_os = 1;
00930         } else if (strcmp(arg, "--dmem") == 0) {
00931             DEBUG_MALLOC_ENABLE();
00932         } else if (strcmp(arg, "--drawmsg") == 0) {
00933             DEBUG_RAWMSG_ENABLE();
00934         } else if (strcmp(arg, "--dmsg") == 0) {
00935             DEBUG_MSG_ENABLE();
00936         } else if (strcmp(arg, "--dmsgerr") == 0) {
00937             DEBUG_MSG_ERR_ENABLE();
00938 #ifdef HAVE_UCDSNMP
00939         } else if (strcmp(arg, "--snmp") == 0) {
00940             init_snmp = 1;
00941 #endif
00942 #ifdef HAVE_GLIB
00943         } else if (strcmp(arg, "--glib") == 0) {
00944             use_glib = 1;
00945 #endif
00946         } else if (strcmp(arg, "--help") == 0) {
00947             usage(argv[0]);
00948             return 0;
00949         } else {
00950             fprintf(stderr, "Unknown option: %s\n", arg);
00951             usage(argv[0]);
00952             return 1;
00953         }
00954     }
00955 
00956     if (use_debug_os) {
00957         os_hnd = &ipmi_debug_os_handlers;
00958         rv = sel_alloc_selector(os_hnd, &debug_sel);
00959         if (rv) {
00960             fprintf(stderr, "Could not allocate selector\n");
00961             return 1;
00962         }
00963 #ifdef HAVE_UCDSNMP
00964         sel = debug_sel;
00965 #endif
00966 #ifdef HAVE_GLIB
00967     } else if (use_glib) {
00968 #ifdef HAVE_UCDSNMP
00969         init_snmp = 0; /* No SNMP support for glib yet. */
00970         sel = NULL;
00971 #endif
00972         g_thread_init(NULL);
00973         os_hnd = ipmi_glib_get_os_handler();
00974         if (!os_hnd) {
00975             fprintf(stderr,
00976                     "ipmi_smi_setup_con: Unable to allocate os handler\n");
00977             return 1;
00978         }
00979         g_log_set_handler("OpenIPMI",
00980                           G_LOG_LEVEL_ERROR
00981                           | G_LOG_LEVEL_CRITICAL
00982                           | G_LOG_LEVEL_WARNING
00983                           | G_LOG_LEVEL_MESSAGE
00984                           | G_LOG_LEVEL_INFO
00985                           | G_LOG_LEVEL_DEBUG
00986                           | G_LOG_FLAG_FATAL,
00987                           glib_handle_log,
00988                           NULL);
00989 #endif
00990     } else {
00991         os_hnd = ipmi_posix_setup_os_handler();
00992         if (!os_hnd) {
00993             fprintf(stderr,
00994                     "ipmi_smi_setup_con: Unable to allocate os handler\n");
00995             return 1;
00996         }
00997 #ifdef HAVE_UCDSNMP
00998         sel = ipmi_posix_os_handler_get_sel(os_hnd);
00999 #endif
01000     }
01001 
01002     os_hnd->set_log_handler(os_hnd, my_vlog);
01003 
01004     /* Initialize the OpenIPMI library. */
01005     ipmi_init(os_hnd);
01006 
01007 #ifdef HAVE_UCDSNMP
01008     if (init_snmp) {
01009         if (snmp_init(sel) < 0)
01010             return 1;
01011     }
01012 #endif
01013 
01014     rv = ipmi_cmdlang_init(os_hnd);
01015     if (rv) {
01016         fprintf(stderr, "Unable to initialize command processor: 0x%x\n", rv);
01017         return 1;
01018     }
01019 
01020     setup_cmds();
01021 
01022     setup_term(os_hnd);
01023 
01024     while (execs) {
01025         exec_list_t *e = execs;
01026         int         cdone = 0;
01027         read_nest = 1;
01028         execs = e->next;
01029         printf("> %s\n", e->str);
01030         fflush(stdout);
01031         done_ptr = &cdone;
01032         rl_ipmish_cb_handler(e->str);
01033         while (!cdone)
01034             os_hnd->perform_one_op(os_hnd, NULL);
01035         done_ptr = NULL;
01036         free(e);
01037         read_nest = 0;
01038     }
01039 
01040     fflush(stdout);
01041 
01042     handling_input = 1;
01043     enable_term_fd(&cmdlang);
01044 
01045     while (!done)
01046         os_hnd->perform_one_op(os_hnd, NULL);
01047 
01048     cleanup_term();
01049 
01050     /* Shut down all existing domains. */
01051     
01052     done = 0;
01053     ipmi_domain_iterate_domains(shutdown_domain_handler, &done);
01054     while (done)
01055         os_hnd->perform_one_op(os_hnd, NULL);
01056 
01057     ipmi_cmdlang_cleanup();
01058     ipmi_shutdown();
01059 
01060     ipmi_debug_malloc_cleanup();
01061 
01062     os_hnd->free_os_handler(os_hnd);
01063 
01064     /* remove the prompt which editline printed */
01065     printf("\b\b  \b\b");
01066     if (evcount)
01067         printf("\n");
01068     fflush(stdout);
01069 
01070     if (rv)
01071         return 1;
01072     return 0;
01073 }

© sourcejam.com 2005-2008