now has an option to daemonize and log SEL events to syslog

This commit is contained in:
Duncan Laurie 2004-08-27 16:40:42 +00:00
parent dd8b1806b5
commit 68be9c40e6

View File

@ -45,10 +45,16 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/poll.h> #include <sys/poll.h>
#include <linux/ipmi.h>
#include <config.h> #include <config.h>
#ifdef HAVE_OPENIPMI_H
# include <linux/ipmi.h>
#else
# include "plugins/open/open.h"
#endif
#include <ipmitool/helper.h> #include <ipmitool/helper.h>
#include <ipmitool/log.h>
#include <ipmitool/ipmi.h> #include <ipmitool/ipmi.h>
#include <ipmitool/ipmi_intf.h> #include <ipmitool/ipmi_intf.h>
#include <ipmitool/ipmi_sel.h> #include <ipmitool/ipmi_sel.h>
@ -57,6 +63,66 @@ extern int errno;
int verbose = 0; int verbose = 0;
int csv_output = 0; int csv_output = 0;
static void daemonize(void)
{
pid_t pid;
int fd;
sigset_t sighup;
/* if we are started from init no need to become daemon */
if (getppid() == 1)
return;
#ifdef SIGHUP
sigemptyset(&sighup);
sigaddset(&sighup, SIGHUP);
if (sigprocmask(SIG_UNBLOCK, &sighup, nil) < 0)
fprintf(stderr, "ERROR: could not unblock SIGHUP signal\n");
SIG_IGNORE(SIGHUP);
#endif
#ifdef SIGTTOU
SIG_IGNORE(SIGTTOU);
#endif
#ifdef SIGTTIN
SIG_IGNORE(SIGTTIN);
#endif
#ifdef SIGQUIT
SIG_IGNORE(SIGQUIT);
#endif
#ifdef SIGTSTP
SIG_IGNORE(SIGTSTP);
#endif
pid = (pid_t) fork();
if (pid < 0 || pid > 0)
exit(0);
#if defined(SIGTSTP) && defined(TIOCNOTTY)
if (setpgid(0, getpid()) == -1)
exit(1);
if ((fd = open(_PATH_TTY, O_RDWR)) >= 0) {
ioctl(fd, TIOCNOTTY, NULL);
close(fd);
}
#else
if (setpgrp() == -1)
exit(1);
pid = (pid_t) fork();
if (pid < 0 || pid > 0)
exit(0);
#endif
chdir("/");
umask(0);
for (fd=0; fd<64; fd++)
close(fd);
open("/dev/null", O_RDWR);
dup(0);
dup(0);
}
static int enable_event_msg_buffer(struct ipmi_intf * intf) static int enable_event_msg_buffer(struct ipmi_intf * intf)
{ {
struct ipmi_rs * rsp; struct ipmi_rs * rsp;
@ -71,7 +137,7 @@ static int enable_event_msg_buffer(struct ipmi_intf * intf)
rsp = intf->sendrecv(intf, &req); rsp = intf->sendrecv(intf, &req);
if (!rsp || rsp->ccode) { if (!rsp || rsp->ccode) {
printf("ERROR:%x Get BMC Global Enables command\n", lprintf(LOG_WARNING, "Get BMC Global Enables command filed [ccode %02x]",
rsp ? rsp->ccode : 0); rsp ? rsp->ccode : 0);
return -1; return -1;
} }
@ -83,17 +149,38 @@ static int enable_event_msg_buffer(struct ipmi_intf * intf)
rsp = intf->sendrecv(intf, &req); rsp = intf->sendrecv(intf, &req);
if (!rsp || rsp->ccode) { if (!rsp || rsp->ccode) {
printf("ERROR:%x Set BMC Global Enables command\n", lprintf(LOG_WARNING, "Set BMC Global Enables command failed [ccode %02x]",
rsp ? rsp->ccode : 0); rsp ? rsp->ccode : 0);
return -1; return -1;
} }
if (verbose) lprintf(LOG_DEBUG, "BMC Event Message Buffer enabled");
printf("BMC Event Message Buffer enabled.\n");
return 0; return 0;
} }
static void log_event(struct sel_event_record * evt)
{
char *desc;
if (!evt)
return;
if (evt->record_type == 0xf0)
lprintf(LOG_ALERT, "Linux kernel panic: %.11s", (char *) evt + 5);
else if (evt->record_type >= 0xc0)
lprintf(LOG_NOTICE, "IPMI Event OEM Record %02x", evt->record_type);
else {
ipmi_get_event_desc(evt, &desc);
if (desc) {
lprintf(LOG_NOTICE, "%s Sensor %02x - %s",
ipmi_sel_get_sensor_type(evt->sensor_type),
evt->sensor_num, desc);
free(desc);
}
}
}
static void read_event(struct ipmi_intf * intf) static void read_event(struct ipmi_intf * intf)
{ {
struct ipmi_addr addr; struct ipmi_addr addr;
@ -108,125 +195,121 @@ static void read_event(struct ipmi_intf * intf)
rv = ioctl(intf->fd, IPMICTL_RECEIVE_MSG_TRUNC, &recv); rv = ioctl(intf->fd, IPMICTL_RECEIVE_MSG_TRUNC, &recv);
if (rv < 0) { if (rv < 0) {
if (errno == EINTR) switch (errno) {
/* abort */ case EINTR:
return; return; /* abort */
if (errno == EMSGSIZE) { case EMSGSIZE:
/* message truncated */ recv.msg.data_len = sizeof(data); /* truncated */
recv.msg.data_len = sizeof(data); break;
} else { default:
printf("ERROR: receiving IPMI message: %s\n", lperror(LOG_ERR, "Unable to receive IPMI message");
strerror(errno));
return; return;
} }
} }
if (!recv.msg.data || recv.msg.data_len == 0) { if (!recv.msg.data || recv.msg.data_len == 0) {
printf("ERROR: No data in event!\n"); lprintf(LOG_ERR, "No data in event");
return; return;
} }
if (verbose > 1) {
printf(" type = %d\n", recv.recv_type);
printf(" channel = 0x%x\n", addr.channel);
printf(" msgid = %ld\n", recv.msgid);
printf(" netfn = 0x%x\n", recv.msg.netfn);
printf(" cmd = 0x%x\n", recv.msg.cmd);
printf(" data_len = %d\n", recv.msg.data_len);
printbuf(recv.msg.data, recv.msg.data_len, "data");
}
if (recv.recv_type != IPMI_ASYNC_EVENT_RECV_TYPE) { if (recv.recv_type != IPMI_ASYNC_EVENT_RECV_TYPE) {
printf("ERROR: Not an event!\n"); lprintf(LOG_ERR, "Type %x is not an event", recv.recv_type);
return; return;
} }
if (verbose) lprintf(LOG_DEBUG, "netfn:%x cmd:%x ccode:%d",
ipmi_sel_print_std_entry_verbose((struct sel_event_record *)recv.msg.data); recv.msg.netfn, recv.msg.cmd, recv.msg.data[0]);
else
ipmi_sel_print_std_entry((struct sel_event_record *)recv.msg.data); log_event((struct sel_event_record *)recv.msg.data);
} }
static int do_exit(struct ipmi_intf * intf, int rv) static int do_exit(struct ipmi_intf * intf, int rv)
{ {
if (intf) if (intf)
intf->close(intf); intf->close(intf);
ipmi_intf_exit(); log_halt();
exit(rv); exit(rv);
} }
static void usage(void) static void usage(void)
{ {
printf("usage: ipmievd [-hv]\n"); fprintf(stderr, "usage: ipmievd [-hvd]\n");
printf("\n"); fprintf(stderr, "\n");
printf(" -h This help\n"); fprintf(stderr, " -h This help\n");
printf(" -v Verbose (can use multiple times)\n"); fprintf(stderr, " -v Verbose (can use multiple times)\n");
printf("\n"); fprintf(stderr, " -s Do NOT daemonize\n");
fprintf(stderr, "\n");
} }
int main(int argc, char ** argv) int main(int argc, char ** argv)
{ {
struct ipmi_intf * intf; struct ipmi_intf * intf;
int r, i=1, a; int r, a;
int i = 1;
int daemon = 1;
struct pollfd pfd; struct pollfd pfd;
while ((a = getopt(argc, (char **)argv, "hv")) != -1) { /* make sure we have UID 0 */
if (geteuid() || getuid()) {
fprintf(stderr, "Inadequate privledges\n");
do_exit(NULL, EXIT_FAILURE);
}
while ((a = getopt(argc, (char **)argv, "hvs")) != -1) {
switch (a) { switch (a) {
case 'h': case 'h':
usage(); usage();
do_exit(NULL, EXIT_SUCCESS);
break; break;
case 'v': case 'v':
verbose++; verbose++;
break; break;
case 's':
daemon = 0;
break;
default: default:
usage(); usage();
do_exit(NULL, EXIT_FAILURE);
} }
} }
if (verbose) if (daemon)
printf("Loading OpenIPMI interface plugin.\n"); daemonize();
/* init interface plugin support */ log_init("ipmievd", daemon, verbose);
r = ipmi_intf_init();
if (r < 0) {
printf("ERROR: Unable to initialize plugin interface\n");
exit(EXIT_FAILURE);
}
/* load interface plugin */ /* load interface */
intf = ipmi_intf_load("intf_open"); lprintf(LOG_DEBUG, "Loading OpenIPMI interface");
intf = ipmi_intf_load("open");
if (!intf) { if (!intf) {
printf("ERROR: unable to load OpenIPMI interface plugin\n"); lprintf(LOG_ERR, "Unable to load OpenIPMI interface");
exit(EXIT_FAILURE); do_exit(NULL, EXIT_FAILURE);
} }
if (verbose)
printf("Connecting to OpenIPMI device.\n");
/* open connection to openipmi device */ /* open connection to openipmi device */
lprintf(LOG_DEBUG, "Connecting to OpenIPMI device");
r = intf->open(intf); r = intf->open(intf);
if (r < 0) { if (r < 0) {
printf("ERROR: Unable to open OpenIPMI device\n"); lprintf(LOG_ERR, "Unable to open OpenIPMI device");
exit(EXIT_FAILURE); do_exit(NULL, EXIT_FAILURE);
} }
/* enable event message buffer */ /* enable event message buffer */
lprintf(LOG_DEBUG, "Enabling event message buffer");
r = enable_event_msg_buffer(intf); r = enable_event_msg_buffer(intf);
if (r < 0) { if (r < 0) {
printf("ERROR: Unable to enable event message buffer.\n"); lprintf(LOG_ERR, "Could not enable event message buffer");
do_exit(intf, EXIT_FAILURE); do_exit(intf, EXIT_FAILURE);
} }
if (verbose)
printf("Enabling event receiver.\n");
/* enable OpenIPMI event receiver */ /* enable OpenIPMI event receiver */
if (ioctl(intf->fd, IPMICTL_SET_GETS_EVENTS_CMD, &i)) { lprintf(LOG_DEBUG, "Enabling event receiver");
perror("ERROR: Could not enable event receiver"); r = ioctl(intf->fd, IPMICTL_SET_GETS_EVENTS_CMD, &i);
if (r != 0) {
lperror(LOG_ERR, "Could not enable event receiver");
do_exit(intf, EXIT_FAILURE); do_exit(intf, EXIT_FAILURE);
} }
printf("ipmievd loaded, waiting for events...\n"); lprintf(LOG_NOTICE, "Waiting for events...");
for (;;) { for (;;) {
pfd.fd = intf->fd; /* wait on openipmi device */ pfd.fd = intf->fd; /* wait on openipmi device */
@ -238,7 +321,7 @@ int main(int argc, char ** argv)
/* timeout is disabled */ /* timeout is disabled */
break; break;
case -1: case -1:
perror("ERROR: poll operation failed"); lperror(LOG_CRIT, "Unable to read from IPMI device");
do_exit(intf, EXIT_FAILURE); do_exit(intf, EXIT_FAILURE);
break; break;
default: default:
@ -247,8 +330,6 @@ int main(int argc, char ** argv)
} }
} }
if (verbose) lprintf(LOG_DEBUG, "Shutting down...");
printf("Exiting.\n");
do_exit(intf, EXIT_SUCCESS); do_exit(intf, EXIT_SUCCESS);
} }