File OpenIPMI_2.0.21_to_HEAD.patch of Package OpenIPMI.8463

diff --git a/doc/IPMI.ltx b/doc/IPMI.ltx
index 35774ac..9d741c9 100644
--- a/doc/IPMI.ltx
+++ b/doc/IPMI.ltx
@@ -5896,7 +5896,7 @@ iterator function with a callback function:
 
 \begin{verbatim}
 static void
-handle_entity(ipmi_domain_t *domain, ipmi_entity_t *entity, void *cb_data)
+handle_entity(ipmi_entity_t *entity, void *cb_data)
 {
   my_data_t *my_data = cb_data;
   /* Process the entity here */
diff --git a/glib/glib_os_hnd.c b/glib/glib_os_hnd.c
index cf21c27..868e96c 100644
--- a/glib/glib_os_hnd.c
+++ b/glib/glib_os_hnd.c
@@ -772,6 +772,31 @@ static void sset_log_handler(os_handler_t *handler,
     info->log_handler = log_handler;
 }
 
+static int get_glib_monotonic_time(os_handler_t *handler,
+				   struct timeval *tv)
+{
+    gint64 now;
+    
+    now = g_get_monotonic_time();
+    tv->tv_sec = now / G_TIME_SPAN_SECOND;
+    tv->tv_usec = now % G_TIME_SPAN_SECOND;
+    return 0;
+}
+
+static int get_glib_time(os_handler_t *handler,
+			 struct timeval *tv)
+{
+    GDateTime *now;
+    GTimeVal gtv;
+    
+    now = g_date_time_new_now_utc();
+    g_date_time_to_timeval(now, &gtv);
+    g_date_time_unref(now);
+    tv->tv_sec = gtv.tv_sec;
+    tv->tv_usec = gtv.tv_usec;
+    return 0;
+}
+
 static os_handler_t ipmi_glib_os_handler =
 {
     .mem_alloc = glib_malloc,
@@ -818,6 +843,8 @@ static os_handler_t ipmi_glib_os_handler =
     .database_set_filename = set_gdbm_filename,
 #endif
     .set_log_handler = sset_log_handler,
+    .get_monotonic_time = get_glib_monotonic_time,
+    .get_real_time = get_glib_time
 };
 
 
diff --git a/include/OpenIPMI/ipmiif.h.in b/include/OpenIPMI/ipmiif.h.in
index 22b2e22..9cdbf34 100644
--- a/include/OpenIPMI/ipmiif.h.in
+++ b/include/OpenIPMI/ipmiif.h.in
@@ -480,6 +480,11 @@ int ipmi_domain_store_entities(ipmi_domain_t  *domain,
 /* Returns if the domain thinks it has a connection up. */
 int ipmi_domain_con_up(ipmi_domain_t *domain);
 
+/*
+ * Returns true if the domain has finished coming up, false if not.
+ */
+int ipmi_domain_is_fully_up(ipmi_domain_t *domain);
+
 /* Iterate through the connections on a domain. */
 typedef void (*ipmi_connection_ptr_cb)(ipmi_domain_t *domain, int conn,
 				       void *cb_data);
diff --git a/ipmi_sim_lancontrol b/ipmi_sim_lancontrol
new file mode 100755
index 0000000..be79f7a
--- /dev/null
+++ b/ipmi_sim_lancontrol
@@ -0,0 +1,72 @@
+#! /bin/sh
+# ipmi_sim_lancontrol - provide link addresses to ipmi_sim for device $1
+# See lan_config_program in ipmi_lan(5)
+#
+# 2015-05-06  Noel Burton-Krahn <noel@pistoncloud.com>
+
+set -eu
+
+# arguments: dev op var
+# network interface
+dev=$1
+# get or set.  This script just supports get
+op=$2
+# var name
+var=$3
+
+# my default gateway device
+gw_dev=$(ip route | sed -ne 's/default via [.0-9]* dev \([^ ]*\) .*/\1/p')
+
+link_ip() {
+    ip -o -4 addr list $1 | sed -ne 's/.* inet \([.0-9]*\)\/.*/\1/p'
+}
+
+link_mac() {
+    ip -o link list $1 | sed -ne 's/.* link\/ether \([:0-9a-f]*\) .*/\1/p'
+}
+
+link_subnet() {
+    ifconfig $1 | sed -n -e 's/.*Mask:\([.0-9]*\).*/\1/p'
+}
+
+get_val() {
+    case $var in
+	ip_addr_src)
+	    echo "dhcp"
+	    ;;
+
+	ip_addr)
+	    link_ip $dev
+	    ;;
+	
+	mac_addr)
+	    link_mac $dev
+	    ;;
+
+	subnet_mask)
+	    link_subnet $dev
+	    ;;
+
+	default_gw_ip_addr)
+	    link_ip $gw_dev
+	    ;;
+	
+	default_gw_mac_addr)
+	    link_mac $gw_dev
+	    ;;
+	    
+	backup_gw_ip_addr)
+	    link_ip $gw_dev
+	    ;;
+	
+	backup_gw_mac_addr)
+	    link_mac $gw_dev
+	    ;;
+    esac
+}
+
+if [ $op = "get" ]; then
+    val=$(get_val $var)
+    echo "$var: $val"
+fi
+
diff --git a/lanserv/OpenIPMI/extcmd.h b/lanserv/OpenIPMI/extcmd.h
index 167090a..382aca2 100644
--- a/lanserv/OpenIPMI/extcmd.h
+++ b/lanserv/OpenIPMI/extcmd.h
@@ -64,6 +64,7 @@ enum extcmd_info_type_e {
     extcmd_mac,
     extcmd_uchar,
     extcmd_int,
+    extcmd_ident,
 };
 
 typedef struct extcmd_map_s {
diff --git a/lanserv/OpenIPMI/mcserv.h b/lanserv/OpenIPMI/mcserv.h
index 032ac28..e0ca58a 100644
--- a/lanserv/OpenIPMI/mcserv.h
+++ b/lanserv/OpenIPMI/mcserv.h
@@ -266,7 +266,8 @@ int ipmi_mc_add_sensor(lmc_data_t    *mc,
 		       unsigned char lun,
 		       unsigned char sens_num,
 		       unsigned char type,
-		       unsigned char event_reading_code);
+		       unsigned char event_reading_code,
+		       int           event_only);
 
 int ipmi_mc_add_polled_sensor(lmc_data_t    *mc,
 			      unsigned char lun,
@@ -368,6 +369,7 @@ int ipmi_mc_set_frudata_handler(lmc_data_t *mc, unsigned int fru,
 #define CHASSIS_CONTROL_BOOT  2
 #define CHASSIS_CONTROL_BOOT_INFO_ACK  3
 #define CHASSIS_CONTROL_GRACEFUL_SHUTDOWN  4
+#define CHASSIS_CONTROL_IDENTIFY 5
 void ipmi_mc_set_chassis_control_func(lmc_data_t *mc,
 				      int (*set)(lmc_data_t *mc, int op,
 						 unsigned char *val,
diff --git a/lanserv/OpenIPMI/serv.h b/lanserv/OpenIPMI/serv.h
index b954af3..c439a0e 100644
--- a/lanserv/OpenIPMI/serv.h
+++ b/lanserv/OpenIPMI/serv.h
@@ -179,7 +179,9 @@ struct channel_s
 #define HW_OP_SEND_NMI		3
 #define HW_OP_IRQ_ENABLE	4
 #define HW_OP_IRQ_DISABLE	5
-#define HW_OP_GRACEFUL_SHUTDOWN	5
+#define HW_OP_GRACEFUL_SHUTDOWN	6
+#define HW_OP_CHECK_POWER	7
+#define HW_OP_FORCEOFF		8
     unsigned int hw_capabilities; /* Bitmask of above bits for capabilities. */
 #define HW_OP_CAN_RESET(chan) ((chan)->hw_capabilities & (1 << HW_OP_RESET))
 #define HW_OP_CAN_POWER(chan) ((chan)->hw_capabilities & (1 << HW_OP_POWERON))
@@ -187,7 +189,7 @@ struct channel_s
 #define HW_OP_CAN_IRQ(chan) ((chan)->hw_capabilities & (1 << HW_OP_IRQ_ENABLE))
 #define HW_OP_CAN_GRACEFUL_SHUTDOWN(chan) ((chan)->hw_capabilities & \
 					   (1 << HW_OP_GRACEFUL_SHUTDOWN))
-    void (*hw_op)(channel_t *chan, unsigned int op);
+    int (*hw_op)(channel_t *chan, unsigned int op);
 
     /* Special command handlers. */
     void (*set_lan_parms)(channel_t *chan, msg_t *msg, unsigned char *rdata,
diff --git a/lanserv/bmc.c b/lanserv/bmc.c
index 8af103c..32eed36 100644
--- a/lanserv/bmc.c
+++ b/lanserv/bmc.c
@@ -625,9 +625,14 @@ ipmi_mc_start_cmd(lmc_data_t *mc)
 	return;
     }
 
-    if (mc->startcmd.vmpid)
+    if (mc->startcmd.vmpid) {
 	/* Already running */
+
+	/* If we are waiting for a poweroff, disable that. */
+	if (mc->startcmd.wait_poweroff)
+	    mc->startcmd.wait_poweroff = 0;
 	return;
+    }
 
     ipmi_do_start_cmd(&mc->startcmd);
 }
@@ -641,8 +646,8 @@ chan_start_cmd(channel_t *chan)
 static void
 ipmi_mc_stop_cmd(lmc_data_t *mc, int do_it_now)
 {
-    if (mc->startcmd.wait_poweroff)
-	/* Already powering off. */
+    if (mc->startcmd.wait_poweroff || !mc->startcmd.vmpid)
+	/* Already powering/powered off. */
 	return;
     if (!do_it_now)
 	mc->startcmd.wait_poweroff = mc->startcmd.poweroff_wait_time;
@@ -780,18 +785,19 @@ handle_tick(void *info, unsigned int seconds)
     lmc_data_t *mc = info;
 
     if (mc->startcmd.wait_poweroff) {
-	if (mc->startcmd.vmpid == 0) {
-	    mc->startcmd.wait_poweroff = 0;
-	} else if (mc->startcmd.wait_poweroff > 0) {
+	if (mc->startcmd.wait_poweroff > 0) {
 	    /* Waiting for the first kill */
 	    mc->startcmd.wait_poweroff--;
 	    if (mc->startcmd.wait_poweroff == 0) {
-		ipmi_do_kill(&mc->startcmd, 0);
+		if (HW_OP_CAN_POWER(mc->channels[15]))
+		    mc->channels[15]->hw_op(mc->channels[15], HW_OP_FORCEOFF);
+		else if (mc->startcmd.vmpid)
+		    ipmi_do_kill(&mc->startcmd, 0);
 		mc->startcmd.wait_poweroff = -mc->startcmd.kill_wait_time;
 	    }
 	} else {
 	    mc->startcmd.wait_poweroff++;
-	    if (mc->startcmd.wait_poweroff == 0)
+	    if (mc->startcmd.wait_poweroff == 0 && mc->startcmd.vmpid)
 		ipmi_do_kill(&mc->startcmd, 1);
 	}
     }
diff --git a/lanserv/bmc.h b/lanserv/bmc.h
index cea8c1a..10cc773 100644
--- a/lanserv/bmc.h
+++ b/lanserv/bmc.h
@@ -135,6 +135,8 @@ struct sensor_s
     uint16_t threshold_supported; /* Bitmask */
     unsigned char thresholds[6];
 
+    int event_only;
+
     unsigned char event_support;
 
     /* 0 for assertion, 1 for deassertion. */
diff --git a/lanserv/bmc_app.c b/lanserv/bmc_app.c
index 38fd619..9a0d482 100644
--- a/lanserv/bmc_app.c
+++ b/lanserv/bmc_app.c
@@ -171,6 +171,12 @@ watchdog_timeout(void *cb_data)
     if (!mc->watchdog_running)
 	goto out;
 
+    if( !sens ) {
+	// NOTE(noelbk): The watchdog sensor should have been defined
+	// earlier, but don't SEGFAULT if it isn't
+	goto out;
+    }
+
     if (! mc->watchdog_preaction_ran) {
 	struct timeval tv, now;
 
@@ -224,7 +230,7 @@ watchdog_timeout(void *cb_data)
 	break;
 
     case IPMI_MC_WATCHDOG_ACTION_POWER_CYCLE:
-	set_sensor_bit(mc, sens, 2, 1, 0xc3, mc->watchdog_use & 0xf, 0xff, 1);
+	set_sensor_bit(mc, sens, 3, 1, 0xc3, mc->watchdog_use & 0xf, 0xff, 1);
 	bchan->hw_op(bchan, HW_OP_POWEROFF);
 	start_poweron_timer(mc);
 	break;
@@ -368,6 +374,8 @@ handle_reset_watchdog_timer(lmc_data_t    *mc,
     }
 
     do_watchdog_reset(mc);
+    rdata[0] = 0x00;
+    *rdata_len = 1;
 }
 
 static void
@@ -928,7 +936,7 @@ handle_get_msg(lmc_data_t    *mc,
     qmsg = mc->recv_q_head;
     if (!qmsg) {
 	rdata[0] = 0x80;
-	*rdata_len = 0;
+	*rdata_len = 1;
 	return;
     }
 
diff --git a/lanserv/bmc_chassis.c b/lanserv/bmc_chassis.c
index 6ca028e..e7231e3 100644
--- a/lanserv/bmc_chassis.c
+++ b/lanserv/bmc_chassis.c
@@ -43,6 +43,8 @@ static extcmd_map_t boot_map[] = {
     { 0, "none" },
     { 1, "pxe" },
     { 2, "default" },
+    { 5, "cdrom" },
+    { 6, "bios" },
     { 0, NULL }
 };
 
@@ -51,7 +53,9 @@ static extcmd_info_t chassis_prog[] = {
     { "power", extcmd_int, NULL, 0 },
     { "reset", extcmd_int, NULL, 0 },
     { "boot", extcmd_uchar, boot_map, 0 },
+    { "boot", extcmd_uchar, boot_map, 0 }, // dup'd for boot info ack
     { "shutdown", extcmd_int, NULL, 0 },
+    { "identify", extcmd_ident, NULL, 0 },
 };
 
 static int
@@ -149,8 +153,11 @@ handle_get_chassis_status(lmc_data_t    *mc,
 	    return;
 	}
 	rdata[1] = val;
-    } else {
-	rdata[1] = mc->startcmd.vmpid != 0;
+    } else if (mc->startcmd.vmpid) {
+	rdata[1] = 1;
+    } else if (HW_OP_CAN_POWER(mc->channels[15])) {
+	int rv = mc->channels[15]->hw_op(mc->channels[15], HW_OP_CHECK_POWER);
+	rdata[1] = rv > 0;
     }
     rdata[2] = 0;
     rdata[3] = 0;
@@ -277,6 +284,48 @@ handle_chassis_control(lmc_data_t    *mc,
 }
 
 static void
+handle_chassis_identify(lmc_data_t    *mc,
+			  msg_t         *msg,
+			  unsigned char *rdata,
+			  unsigned int  *rdata_len,
+			  void          *cb_data)
+{
+    unsigned char val[2];
+
+    rdata[0] = 0;
+    memset(val, 0, sizeof(val));
+
+    if (msg->len == 0)
+        val[0] = 0xf; /* default 15 seconds */
+    else
+        val[0] = msg->data[0]; /* interval */
+
+    if (msg->len > 1) /* force flag is set */
+        val[1] = msg->data[1] & 0x1;
+
+    if (mc->chassis_control_set_func) {
+	int rv;
+	rv = mc->chassis_control_set_func(mc, CHASSIS_CONTROL_IDENTIFY,
+					  val, mc->chassis_control_cb_data);
+	if (rv) {
+	    rdata[0] = IPMI_UNKNOWN_ERR_CC;
+	    *rdata_len = 1;
+	    return;
+	}
+    } else if (mc->chassis_control_prog) {
+	if (extcmd_setvals(mc->sysinfo, val, mc->chassis_control_prog,
+			   &chassis_prog[CHASSIS_CONTROL_IDENTIFY], NULL, 1)) {
+	    rdata[0] = IPMI_UNKNOWN_ERR_CC;
+	    *rdata_len = 1;
+	    return;
+	}
+    } else {
+	rdata[0] = IPMI_INVALID_DATA_FIELD_CC;
+	*rdata_len = 1;
+    }
+}
+
+static void
 set_system_boot_options(lmc_data_t    *mc,
 			msg_t         *msg,
 			unsigned char *rdata,
@@ -326,11 +375,19 @@ set_system_boot_options(lmc_data_t    *mc,
 	    rv = mc->chassis_control_set_func(mc, CHASSIS_CONTROL_BOOT_INFO_ACK,
 					      msg->data + 1,
 					      mc->chassis_control_cb_data);
+
 	    if (rv) {
 		rdata[0] = IPMI_UNKNOWN_ERR_CC;
 		*rdata_len = 1;
 		return;
 	    }
+	} else if (mc->chassis_control_prog) {
+	    if (extcmd_getvals(mc->sysinfo, &val, mc->chassis_control_prog,
+			    &chassis_prog[CHASSIS_CONTROL_BOOT_INFO_ACK], 1)) {
+		rdata[0] = IPMI_UNKNOWN_ERR_CC;
+		*rdata_len = 1;
+		return;
+	    }
 	} else {
 	    rdata[0] = IPMI_INVALID_DATA_FIELD_CC;
 	    *rdata_len = 1;
@@ -459,6 +516,7 @@ cmd_handler_f chassis_netfn_handlers[256] = {
     [IPMI_GET_CHASSIS_STATUS_CMD] = handle_get_chassis_status,
     [IPMI_CHASSIS_CONTROL_CMD] = handle_chassis_control,
     [IPMI_SET_SYSTEM_BOOT_OPTIONS_CMD] = set_system_boot_options,
-    [IPMI_GET_SYSTEM_BOOT_OPTIONS_CMD] = get_system_boot_options
+    [IPMI_GET_SYSTEM_BOOT_OPTIONS_CMD] = get_system_boot_options,
+    [IPMI_CHASSIS_IDENTIFY_CMD] = handle_chassis_identify
 };
 
diff --git a/lanserv/bmc_sensor.c b/lanserv/bmc_sensor.c
index bbc00a3..2166dee 100644
--- a/lanserv/bmc_sensor.c
+++ b/lanserv/bmc_sensor.c
@@ -342,7 +342,14 @@ set_sensor_bit(lmc_data_t *mc, sensor_t *sensor, unsigned char bit,
 	       unsigned char evd1, unsigned char evd2, unsigned char evd3,
 	       int gen_event)
 {
-    if (value != bit_set(sensor->event_status, bit)) {
+    if (sensor->event_only) {
+	if (value)
+	    do_event(mc, sensor, gen_event, IPMI_ASSERTION,
+		     evd1 | bit, evd2, evd3);
+	else
+	    do_event(mc, sensor, gen_event, IPMI_DEASSERTION,
+		     evd1 | bit, evd2, evd3);
+    } else if (value != bit_set(sensor->event_status, bit)) {
 	/* The bit value has changed. */
 	set_bit(sensor->event_status, bit, value);
 	if (value && bit_set(sensor->event_enabled[0], bit)) {
@@ -710,6 +717,12 @@ handle_get_sensor_reading(lmc_data_t    *mc,
 
     sensor = mc->sensors[msg->rs_lun][sens_num];
 
+    if (sensor->event_only) {
+	rdata[0] = IPMI_INVALID_DATA_FIELD_CC;
+	*rdata_len = 1;
+	return;
+    }
+
     rdata[0] = 0;
     rdata[1] = sensor->value;
     rdata[2] = ((sensor->events_enabled << 7)
@@ -1109,7 +1122,8 @@ ipmi_mc_add_sensor(lmc_data_t    *mc,
 		   unsigned char lun,
 		   unsigned char sens_num,
 		   unsigned char type,
-		   unsigned char event_reading_code)
+		   unsigned char event_reading_code,
+		   int           event_only)
 {
     sensor_t *sensor;
     lmc_data_t *bmc;
@@ -1127,6 +1141,7 @@ ipmi_mc_add_sensor(lmc_data_t    *mc,
     sensor->num = sens_num;
     sensor->sensor_type = type;
     sensor->event_reading_code = event_reading_code;
+    sensor->event_only = event_only;
     mc->sensors[lun][sens_num] = sensor;
 
     if (mc->emu->atca_mode && (type == 0xf0)) {
@@ -1531,7 +1546,7 @@ ipmi_mc_add_polled_sensor(lmc_data_t    *mc,
     sensor_t *sensor;
     int err;
 
-    err = ipmi_mc_add_sensor(mc, lun, sens_num, type, event_reading_code);
+    err = ipmi_mc_add_sensor(mc, lun, sens_num, type, event_reading_code, 0);
     if (err)
 	return err;
 
diff --git a/lanserv/config.c b/lanserv/config.c
index 65b169d..f066396 100644
--- a/lanserv/config.c
+++ b/lanserv/config.c
@@ -831,14 +831,18 @@ read_config(sys_data_t *sys,
 	} else if (strcmp(tok, "name") == 0) {
 	    err = get_delim_str(&tokptr, &sys->name, &errstr);
 	} else if (strcmp(tok, "startcmd") == 0) {
-	    err = get_delim_str(&tokptr, &sys->startcmd->startcmd, &errstr);
+	    if (sys->startcmd)
+		err = get_delim_str(&tokptr, &sys->startcmd->startcmd, &errstr);
 	} else if (strcmp(tok, "startnow") == 0) {
-	    err = get_bool(&tokptr, &sys->startcmd->startnow, &errstr);
+	    if (sys->startcmd)
+		err = get_bool(&tokptr, &sys->startcmd->startnow, &errstr);
 	} else if (strcmp(tok, "poweroff_wait") == 0) {
-	    err = get_uint(&tokptr, &sys->startcmd->poweroff_wait_time,
+	    if (sys->startcmd)
+		err = get_uint(&tokptr, &sys->startcmd->poweroff_wait_time,
 			   &errstr);
 	} else if (strcmp(tok, "kill_wait") == 0) {
-	    err = get_uint(&tokptr, &sys->startcmd->kill_wait_time, &errstr);
+	    if (sys->startcmd)
+		err = get_uint(&tokptr, &sys->startcmd->kill_wait_time, &errstr);
 	} else if (strcmp(tok, "set_working_mc") == 0) {
 	    unsigned char ipmb;
 	    err = get_uchar(&tokptr, &ipmb, &errstr);
diff --git a/lanserv/emu_cmd.c b/lanserv/emu_cmd.c
index 1ec99a1..48fb1dc 100644
--- a/lanserv/emu_cmd.c
+++ b/lanserv/emu_cmd.c
@@ -354,7 +354,12 @@ sensor_add(emu_out_t *out, emu_data_t *emu, lmc_data_t *mc, char **toks)
     unsigned char num;
     unsigned char type;
     unsigned char code;
+    int           event_only = 0;
     const char *tok;
+    ipmi_sensor_handler_t *handler = NULL;
+    unsigned int poll_rate = 0;
+    void *rcb_data = NULL;
+    const char *errstr;
 
     rv = emu_get_uchar(out, toks, &lun, "LUN", 0);
     if (rv)
@@ -377,41 +382,52 @@ sensor_add(emu_out_t *out, emu_data_t *emu, lmc_data_t *mc, char **toks)
      * really be part of the main sensor structure.
      */
     tok = mystrtok(NULL, " \t\n", toks);
-    if (tok) {
-	ipmi_sensor_handler_t *handler;
-	unsigned int poll_rate;
-	void *rcb_data;
-	const char *errstr;
-
-	if (strcmp(tok, "poll") != 0) {
-	    out->printf(out, "**Only polled sensors supported\n", tok);
-	    return -1;
-	}
+    while (tok) {
+	if (strcmp(tok, "poll") == 0) {
+	    if (handler) {
+		out->printf(out, "**poll given twice in sensor\n", tok);
+		return -1;
+	    }
 
-	rv = emu_get_uint(out, toks, &poll_rate, "poll rate");
-	if (rv)
-	    return rv;
+	    rv = emu_get_uint(out, toks, &poll_rate, "poll rate");
+	    if (rv)
+		return rv;
 
-	tok = mystrtok(NULL, " \t\n", toks);
-	if (!tok) {
-	    out->printf(out, "**No polled sensor handler given\n", tok);
-	    return -1;
-	}
+	    tok = mystrtok(NULL, " \t\n", toks);
+	    if (!tok) {
+		out->printf(out, "**No polled sensor handler given\n", tok);
+		return -1;
+	    }
+
+	    handler = ipmi_sensor_find_handler(tok);
+	    if (!handler) {
+		out->printf(out, "**Invalid sensor handler: %s\n", tok);
+		return -1;
+	    }
 
-	handler = ipmi_sensor_find_handler(tok);
-	if (!handler) {
-	    out->printf(out, "**Invalid sensor handler: %s\n", tok);
+	    rv = handler->init(mc, lun, num, toks, handler->cb_data, &rcb_data,
+			       &errstr);
+	    if (rv) {
+		out->printf(out, "**Error initializing sensor handler: %s\n", 
+			    errstr);
+		return rv;
+	    }
+	} else if (strcmp(tok, "event-only") == 0) {
+	    event_only = 1;
+	} else {
+	    out->printf(out, "**Unknown sensor option: %s\n", tok);
 	    return -1;
 	}
 
-	rv = handler->init(mc, lun, num, toks, handler->cb_data, &rcb_data,
-			   &errstr);
-	if (rv) {
-	    out->printf(out, "**Error initializing sensor handler: %s\n", 
-			errstr);
-	    return rv;
-	}
+	tok = mystrtok(NULL, " \t\n", toks);
+    }
+
+    if (handler && event_only) {
+	out->printf(out, "**An event-only sensor cannot be polled\n");
+	return -1;
+    }
 
+    if (handler) {
 	rv = ipmi_mc_add_polled_sensor(mc, lun, num, type, code,
 				       poll_rate, handler->poll, rcb_data);
 	
@@ -423,7 +439,7 @@ sensor_add(emu_out_t *out, emu_data_t *emu, lmc_data_t *mc, char **toks)
 	    }
 	}
     } else {
-	rv = ipmi_mc_add_sensor(mc, lun, num, type, code);
+	rv = ipmi_mc_add_sensor(mc, lun, num, type, code, event_only);
     }
     if (rv)
 	out->printf(out, "**Unable to add to sensor, error 0x%x\n", rv);
diff --git a/lanserv/extcmd.c b/lanserv/extcmd.c
index fed693d..1cd902f 100644
--- a/lanserv/extcmd.c
+++ b/lanserv/extcmd.c
@@ -167,6 +167,10 @@ extcmd_setval(void *baseloc, extcmd_info_t *t)
 	    return NULL;
 	break;
 
+    case extcmd_ident:
+	sprintf(buf, "%u %u", (unsigned char)loc[0], (unsigned char)loc[1]);
+	break;
+
     case extcmd_mac:
 	if (!ether_ntoa_r((struct ether_addr *) loc, buf))
 	    return NULL;
@@ -364,7 +368,8 @@ extcmd_setvals(sys_data_t *sys,
 	rv = add_cmd(&cmd, ts[i].name, extcmd_setval(baseloc, ts + i), 1);
 	if (rv) {
 	    sys->log(sys, OS_ERROR, NULL,
-		     "Out of memory in extcmd write command\n");
+		     "Out of memory in extcmd write command (%d) %s\n",
+		     rv, strerror(rv));
 	    goto out;
 	}
     }
diff --git a/lanserv/ipmi_sim.c b/lanserv/ipmi_sim.c
index c634e26..ed0b9f9 100644
--- a/lanserv/ipmi_sim.c
+++ b/lanserv/ipmi_sim.c
@@ -104,6 +104,40 @@ static char *command_file = NULL;
 static int debug = 0;
 static int nostdio = 0;
 
+/*
+ * Keep track of open sockets so we can close them on exec().
+ */
+typedef struct isim_fd {
+    int fd;
+    struct isim_fd *next;
+} isim_fd_t;
+
+static isim_fd_t *isim_fds = NULL;
+
+static void isim_add_fd(int fd)
+{
+    isim_fd_t *n = malloc(sizeof(*n));
+
+    if (!n) {
+	fprintf(stderr, "Unable to add fd to list, out of memory\n");
+	exit(1);
+    }
+
+    n->fd = fd;
+    n->next = isim_fds;
+    isim_fds = n;
+}
+
+static void isim_close_fds(void)
+{
+    isim_fd_t *n = isim_fds;
+
+    while(n) {
+	close(n->fd);
+	n = n->next;
+    }
+}
+
 static void shutdown_handler(int sig);
 
 typedef struct misc_data misc_data_t;
@@ -302,6 +336,8 @@ open_lan_fd(struct sockaddr *addr, socklen_t addr_len)
 	exit(1);
     }
 
+    isim_add_fd(fd);
+
     return fd;
 }
 
@@ -443,7 +479,6 @@ ser_channel_init(void *info, channel_t *chan)
     serserv_data_t *ser = chan->chan_info;
     int err;
     int fd;
-    int opt;
     struct sockaddr *addr = &ser->addr.addr.s_ipsock.s_addr;
     os_hnd_fd_id_t *fd_id;
     int val;
@@ -526,6 +561,9 @@ ser_channel_init(void *info, channel_t *chan)
 	}
     }
 
+    if (!err)
+	isim_add_fd(fd);
+
     return err;
 }
 
@@ -692,7 +730,6 @@ emu_printf(emu_out_t *out, char *format, ...)
 {
     console_info_t *info = out->data;
     va_list ap;
-    int rv;
     char buffer[500];
     int start = 0;
     int pos;
@@ -702,13 +739,13 @@ emu_printf(emu_out_t *out, char *format, ...)
     va_end(ap);
     for (pos = 0; buffer[pos]; pos++) {
 	if (buffer[pos] == '\n') {
-	    rv = write(info->outfd, buffer + start, pos - start + 1);
-	    rv = write(info->outfd, "\r", 1);
+	    (void) write(info->outfd, buffer + start, pos - start + 1);
+	    (void) write(info->outfd, "\r", 1);
 	    start = pos + 1;
 	}
     }
     if (pos != start)
-	rv = write(info->outfd, buffer + start, pos - start);
+	(void) write(info->outfd, buffer + start, pos - start);
 }
 
 static void
@@ -727,8 +764,6 @@ dummy_printf(emu_out_t *out, char *format, ...)
 static unsigned char
 handle_telnet(console_info_t *info, unsigned char c)
 {
-    int err;
-
     info->tn_buf[info->tn_pos++] = c;
     if ((info->tn_pos == 2) && (info->tn_buf[1] == TN_IAC))
 	/* Double IAC, just send it on. */
@@ -767,12 +802,12 @@ handle_telnet(console_info_t *info, unsigned char c)
 
  send_wont:
     info->tn_buf[1] = TN_WONT;
-    err = write(info->outfd, info->tn_buf, 3);
+    (void) write(info->outfd, info->tn_buf, 3);
     goto cmd_done;
 
  send_dont:
     info->tn_buf[1] = TN_DONT;
-    err = write(info->outfd, info->tn_buf, 3);
+    (void) write(info->outfd, info->tn_buf, 3);
     goto cmd_done;
 
  cmd_done:
@@ -783,8 +818,6 @@ handle_telnet(console_info_t *info, unsigned char c)
 static int
 handle_user_char(console_info_t *info, unsigned char c)
 {
-    int rv;
-
     if (info->tn_pos)
 	c = handle_telnet(info, c);
 
@@ -805,14 +838,14 @@ handle_user_char(console_info_t *info, unsigned char c)
 	if (info->pos > 0) {
 	    info->pos--;
 	    if (info->echo)
-		rv = write(info->outfd, "\b \b", 3);
+		(void) write(info->outfd, "\b \b", 3);
 	}
 	break;
 
     case 4:
 	if (info->pos == 0) {
 	    if (info->echo)
-		rv = write(info->outfd, "\n", 1);
+		(void) write(info->outfd, "\n", 1);
 	    return 1;
 	}
 	break;
@@ -820,9 +853,9 @@ handle_user_char(console_info_t *info, unsigned char c)
     case 10:
     case 13:
 	if (info->echo) {
-	    rv = write(info->outfd, "\n", 1);
+	    (void) write(info->outfd, "\n", 1);
 	    if (info->telnet)
-		rv = write(info->outfd, "\r", 1);
+		(void) write(info->outfd, "\r", 1);
 	}
 	info->buffer[info->pos] = '\0';
 	if (strcmp(info->buffer, "noecho") == 0) {
@@ -830,7 +863,7 @@ handle_user_char(console_info_t *info, unsigned char c)
 	} else {
 	    ipmi_emu_cmd(&info->out, info->data->emu, info->buffer);
 	}
-	rv = write(info->outfd, "> ", 2);
+	(void) write(info->outfd, "> ", 2);
 	info->pos = 0;
 	break;
 
@@ -838,12 +871,12 @@ handle_user_char(console_info_t *info, unsigned char c)
     default:
 	if (info->pos >= sizeof(info->buffer)-1) {
 	    char *msg = "\nCommand is too long, max of %d characters\n";
-	    rv = write(info->outfd, msg, strlen(msg));
+	    (void) write(info->outfd, msg, strlen(msg));
 	} else {
 	    info->buffer[info->pos] = c;
 	    info->pos++;
 	    if (info->echo)
-		rv = write(info->outfd, &c, 1);
+		(void) write(info->outfd, &c, 1);
 	}
     }
 
@@ -1201,9 +1234,8 @@ static void
 handle_sigchld(int sig)
 {
     unsigned char c = 1;
-    int rv;
 
-    rv = write(sigpipeh[1], &c, 1);
+    (void) write(sigpipeh[1], &c, 1);
 }
 
 static ipmi_child_quit_t *child_quit_handlers;
@@ -1283,6 +1315,7 @@ ipmi_do_start_cmd(startcmd_t *startcmd)
     if (pid == 0) {
 	char *args[4] = { "/bin/sh", "-c", cmd, NULL };
 
+	isim_close_fds();
 	execvp(args[0], args);
 	exit(1);
     }
@@ -1555,6 +1588,8 @@ main(int argc, const char *argv[])
 	if (err) {
 	    fprintf(stderr, "Unable to add console wait: 0x%x\n", err);
 	    goto out;
+	} else {
+	    isim_add_fd(nfd);
 	}
     }
 
diff --git a/lanserv/ipmi_sim_cmd.5 b/lanserv/ipmi_sim_cmd.5
index 216be36..9071951 100644
--- a/lanserv/ipmi_sim_cmd.5
+++ b/lanserv/ipmi_sim_cmd.5
@@ -132,7 +132,7 @@ Add an entry to the device SDR of the MC.
 .SH SENSOR COMMANDS
 
 .TP
-\fBsensor_add\fP \fImc-addr\fP \fILUN\fP \fIsensor-num\fP \fIsensor-type\fP \fIevent-reading-code\fP [\fIpoll\fP \fIpoll_rate\fP \fIpoll_type\fP \fIpoll_type_options\fP]
+\fBsensor_add\fP \fImc-addr\fP \fILUN\fP \fIsensor-num\fP \fIsensor-type\fP \fIevent-reading-code\fP [\fIpoll\fP \fIpoll_rate\fP \fIpoll_type\fP \fIpoll_type_options\fP] [event-only]
 
 Add a sensor to the given MC and LUN.  The type of sensor is set by the
 event reading code.
@@ -183,6 +183,10 @@ to be active.  Generally, you use the presense bit of a sensor to mark
 whether other sensors on the device are actually present.  Each of the
 other sensors would have one of these pointing to the presense bit.
 
+.I event-only
+specifies that the sensor will not be readable, it will only generate
+events (specified with a type 3 SDR).
+
 .TP
 \fBsensor_set_bit\fP \fImc-addr\fP \fILUN\fP \fIsensor-num\fP \fIbit-to-set\fP \fIbit-value\fP \fIgenerate-event\fP
 Set the given bit to bit-value (0 or 1) for the sensor by bit number,
diff --git a/lanserv/ipmisim1.emu b/lanserv/ipmisim1.emu
index df7526e..367715b 100644
--- a/lanserv/ipmisim1.emu
+++ b/lanserv/ipmisim1.emu
@@ -9,15 +9,15 @@ mc_setbmc 0x20
 mc_add 0x20 0 no-device-sdrs 0x23 9 8 0x9f 0x1291 0xf02 persist_sdr
 sel_enable 0x20 1000 0x0a
 
+# Watchdog sensor.  This must be sensor zero.
+sensor_add 0x20 0 0 35 0x6f event-only
+sensor_set_event_support 0x20 0 0 enable scanning per-state \
+	000000000001111 000000000000000 \
+	000000000001111 000000000000000
+
 # Add a temperature sensor and its SDR.  Note that sensor 0 is already
 # taken as the watchdog sensor.
 sensor_add 0x20 0 1 0x01 0x01
-#main_sdr_add 0x20 \
-#	     00 00 51 01 31 \
-#	     20 00 01 03 01 67 88 01 01 c0 0f c0 7f 38 38 00 \
-#	     01 00 00 01 00 00 00 00 00 03 60 b0 00 b0 00 a0 \
-#	     90 70 00 00 00 00 00 00 00 00 c6 'D 'J 't 'e 'm \
-#	     'p
 # Start with the value set to 0x60
 sensor_set_value 0x20 0 1 0x60 0
 # Set just the upper thresholds with the values 0x70, 0x90, and 0xa0
@@ -28,15 +28,10 @@ sensor_set_event_support 0x20 0 1 enable scanning per-state \
 	000111111000000 000111111000000
 
 # Add a satellite MC
-mc_add 0x30 2 no-device-sdrs 0x98 0x10 1 0x80 0x1291 0xf03
+mc_add 0x30 2 no-device-sdrs 0x98 0x10 1 0x20 0x1291 0xf03
 
 sensor_add 0x30 0 1 0x01 0x01 poll 1000 file "/tmp/file1.ipm"
-#main_sdr_add 20 \
-#	     00 00 51 01 31 \
-#	     30 00 01 03 02 67 88 01 01 c0 0f c0 7f 38 38 00 \
-#	     01 00 00 01 00 00 00 00 00 03 60 b0 00 b0 00 a0 \
-#	     90 70 00 00 00 00 00 00 00 00 c6 'D 'J 't 'e 'm \
-#	     'p
+sensor_set_threshold 0x30 0 1 settable 111000 0xa0 0x90 0x70 00 00 00
 sensor_set_event_support 0x30 0 1 enable scanning per-state \
 	000111111000000 000111111000000 \
 	000111111000000 000111111000000
diff --git a/lanserv/ipmisim1.sdrs b/lanserv/ipmisim1.sdrs
new file mode 100644
index 0000000..2f75ffc
--- /dev/null
+++ b/lanserv/ipmisim1.sdrs
@@ -0,0 +1,94 @@
+
+sdr type 18
+	device_slave_address	0x20
+	device_channel_number	0
+	chassis			true
+	ipmb_event_gen		false
+	ipmb_event_recv		false
+	fru_inventory		true
+	sel			true
+	sdr			true
+	sensor			true
+	entity_id		system_board
+	entity_instance		1
+	id_string		"IPMI sim1"
+endsdr
+
+# Watchdog timer
+sdr type 3
+	sensor_owner_id		0x20
+	sensor_owner_lun	0
+	channel_number		0
+	sensor_number		0
+	entity_id		system_board
+	entity_instance		1
+	sensor_type		Watchdog_2
+	event_reading_type_code	0x6f
+	id_string		"watchdog"
+endsdr
+
+# Temperature sensor on the main board
+sdr type 1
+	sensor_owner_id		0x20
+	sensor_owner_lun	0
+	channel_number		0
+	sensor_number		1
+	entity_id		system_board
+	entity_instance		1
+	sensor_type		Temperature
+	init_scanning		true
+	init_sensor_type	true
+	default_sensor_scan_on	true
+	event_reading_type_code	1
+	analog_data_format	unsigned
+	rate_unit		none
+	modifier_unit		none
+	percentage		false
+	base_unit		degrees_C
+	modifier_unit_code	unspecified
+	linearization		linear
+	m			1
+	tolerance		0
+	b			0
+	accuracy		1
+	accuracy_exp		0
+	sensor_direction	input
+	r_exp			0
+	b_exp			0
+	sensor_maximum		255
+	sensor_minimum		0
+	id_string		"MBTemp"
+endsdr
+
+# Temperature sensor on the sub board
+sdr type 1
+	sensor_owner_id		0x30
+	sensor_owner_lun	0
+	channel_number		0
+	sensor_number		1
+	entity_id		system_board
+	entity_instance		1
+	sensor_type		Temperature
+	init_scanning		true
+	init_sensor_type	true
+	default_sensor_scan_on	true
+	event_reading_type_code	1
+	analog_data_format	unsigned
+	rate_unit		none
+	modifier_unit		none
+	percentage		false
+	base_unit		degrees_C
+	modifier_unit_code	unspecified
+	linearization		linear
+	m			1
+	tolerance		0
+	b			0
+	accuracy		1
+	accuracy_exp		0
+	sensor_direction	input
+	r_exp			0
+	b_exp			0
+	sensor_maximum		255
+	sensor_minimum		0
+	id_string		"SubTemp"
+endsdr
\ No newline at end of file
diff --git a/lanserv/lan.conf b/lanserv/lan.conf
index a87cc6c..7a0f58d 100644
--- a/lanserv/lan.conf
+++ b/lanserv/lan.conf
@@ -16,7 +16,7 @@ set_working_mc 0x20
     # Define an IP address and port to listen on.  You can define more
     # than one address/port to listen on multiple addresses.  The ::
     # listens on all addresses.
-    addr :: 9001
+    addr localhost 9001
     #addr 192.168.27.126 9000
     #addr 192.168.27.200 9000
 
@@ -51,7 +51,7 @@ set_working_mc 0x20
   # startcmd is what to execute to start a VM associated with the
   # codec above (localhost 9002).  It also starts a console serial port
   # on port 9003 that is also used as the monitor interface.
-  startcmd "$HOME/git/qemu/O/x86_64-softmmu/qemu-system-x86_64 --enable-kvm -drive file=/work/cge7/build1/tmp/deploy/images/x86_64-image.ext2,format=raw -nographic -net nic,model=e1000,macaddr=52:54:00:12:34:59 -net user,hostfwd=tcp::5555-10.0.2.15:22 -chardev socket,id=ipmi0,host=localhost,port=9002,reconnect=10 -device isa-ipmi,chardev=ipmi0,interface=bt,irq=5 -serial mon:tcp::9003,server,telnet,nowait -kernel /home/cminyard/git/linux-ipmi/O/arch/x86_64/boot/bzImage --append 'root=/dev/hda console=ttyS0,115200'"
+  startcmd "$HOME/git/qemu/O/x86_64-softmmu/qemu-system-x86_64 --enable-kvm -machine q35 -drive file=/work/cge7/build.x86-generic-64/tmp/deploy/images/small-image-x86-generic-64.ext2,format=raw -nographic -net nic,model=e1000,macaddr=52:54:00:12:34:59 -net user,hostfwd=tcp::5555-10.0.2.15:22 -chardev socket,id=ipmi0,host=localhost,port=9002,reconnect=10 -device ipmi-bmc-extern,id=bmc0,chardev=ipmi0 -device isa-ipmi-bt,bmc=bmc0 -serial mon:tcp:localhost:9003,server,telnet,nowait -kernel //work/cge7/build.x86-generic-64/tmp/deploy/images/bzImage --append 'root=/dev/sdb console=ttyS0,115200'"
 
   # Start startcmd at startup?  Default is false.
   startnow false
@@ -77,7 +77,7 @@ set_working_mc 0x20
   user 1 true  ""        "test" user     10       none md2 md5 straight
   user 2 true  "ipmiusr" "test" admin    10       none md2 md5 straight
 
-  sol "/dev/ttyUSB0" 38400 history=4000 historyfru=10
+#  sol "/dev/ttyUSB0" 38400 history=4000 historyfru=10
 
 #
 # Switch to a new MC
diff --git a/lanserv/lanserv_ipmi.c b/lanserv/lanserv_ipmi.c
index 219b2d8..b0a2431 100644
--- a/lanserv/lanserv_ipmi.c
+++ b/lanserv/lanserv_ipmi.c
@@ -3070,7 +3070,7 @@ ipmi_lan_tick(void *info, unsigned int time_since_last)
     for (i=1; i<=MAX_SESSIONS; i++) {
 	if (lan->sessions[i].active) {
 	    if (lan->sessions[i].time_left <= time_since_last) {
-		msg_t msg; /* A fake message to hold the address. */
+		msg_t msg = { 0 }; /* A fake message to hold the address. */
 
 		msg.src_addr = lan->sessions[i].src_addr;
 		msg.src_len = lan->sessions[i].src_len;
diff --git a/lanserv/marvell-bmc/BuildingAndConfiguring.tex b/lanserv/marvell-bmc/BuildingAndConfiguring.tex
new file mode 100644
index 0000000..a4c3545
--- /dev/null
+++ b/lanserv/marvell-bmc/BuildingAndConfiguring.tex
@@ -0,0 +1,38 @@
+
+The build script
+
+build procedure
+  special files (NTP, ast1300...)
+
+How to modify the build config
+How to modify the busybox config
+
+The configuration file
+  LAN channels
+  MCs
+  users
+
+emu files
+MCs
+  sensors
+  FRU data
+
+SDRs
+
+Custom commands
+  Disable network services:
+    raw 2e 01 0f 50 00 [0|1]
+  Enables (1) or disables(0) ssh access to the BMC
+
+  Reload board FRU
+    raw 2e 02 0f 50 00 <board num>
+  Reload the board FRU information for the given board number.
+
+  Set force all fans duty cycle
+    raw 2e 03 0f 50 00 [0|<duty cycle>]
+  Set all fans to the given duty cycle.  Allowed values are 30-100.
+  Setting it to zero will disable this feature
+
+  Get force all fans duty cycle
+    raw 2e 04 0f 50 00
+  Returns the current fan forced duty cycle setting.
diff --git a/lanserv/marvell-bmc/Makefile.am b/lanserv/marvell-bmc/Makefile.am
index afb5b61..6975d38 100644
--- a/lanserv/marvell-bmc/Makefile.am
+++ b/lanserv/marvell-bmc/Makefile.am
@@ -13,4 +13,8 @@ noinst_DATA = sdrs.bin
 
 noinst_HEADERS = wiw.h
 
-EXTRA_DIST = main.sdrs board.sdrs fan.sdrs lan.conf netsrvc
+EXTRA_DIST = main.sdrs board.sdrs fan.sdrs lan.conf netsrvc lancontrol \
+	busybox-1.18.4.config interfaces ntp.conf marvell_bmc.config \
+	S90ast1300 SystemInfo TODO BuildingAndConfiguring.tex \
+	Build_Marvell_BMC.sh Install_Marvell_BMC.sh marvell_node.emu \
+	marvell.emu
diff --git a/lanserv/serial_ipmi.c b/lanserv/serial_ipmi.c
index e794db0..9a1806c 100644
--- a/lanserv/serial_ipmi.c
+++ b/lanserv/serial_ipmi.c
@@ -745,6 +745,7 @@ tm_setup(serserv_data_t *si)
 #define   VM_CAPABILITIES_IRQ	0x04
 #define   VM_CAPABILITIES_NMI	0x08
 #define   VM_CAPABILITIES_ATTN	0x10
+#define VM_CMD_FORCEOFF		0x09
 
 struct vm_data {
     unsigned char recv_msg[IPMI_SIM_MAX_MSG_LENGTH + 4];
@@ -936,7 +937,7 @@ vm_set_attn(channel_t *chan, int val, int irq)
     raw_send(si, c, len);
 }
 
-static void
+static int
 vm_hw_op(channel_t *chan, unsigned int op)
 {
     serserv_data_t *si = chan->chan_info;
@@ -951,7 +952,7 @@ vm_hw_op(channel_t *chan, unsigned int op)
     case HW_OP_POWERON:
 	if (chan->start_cmd)
 	    chan->start_cmd(chan);
-	return;
+	return 0;
 
     case HW_OP_POWEROFF:
 	if (si->connected)
@@ -960,6 +961,11 @@ vm_hw_op(channel_t *chan, unsigned int op)
 	    chan->stop_cmd(chan, !si->connected);
 	break;
 	
+    case HW_OP_FORCEOFF:
+	if (si->connected)
+	    vm_add_char(VM_CMD_FORCEOFF, c, &len);
+	break;
+	
     case HW_OP_SEND_NMI:
 	vm_add_char(VM_CMD_SEND_NMI, c, &len);
 	break;
@@ -972,13 +978,18 @@ vm_hw_op(channel_t *chan, unsigned int op)
 	vm_add_char(VM_CMD_DISABLE_IRQ, c, &len);
 	break;
 
+    case HW_OP_CHECK_POWER:
+	return si->connected;
+	break;
+
     default:
-	return;
+	return 0;
     }	
 
     c[len++] = VM_CMD_CHAR;
 
     raw_send(si, c, len);
+    return 0;
 }
 
 static void
diff --git a/lib/domain.c b/lib/domain.c
index 1a2a1b3..718ffa9 100644
--- a/lib/domain.c
+++ b/lib/domain.c
@@ -474,6 +474,12 @@ _ipmi_put_domain_fully_up(ipmi_domain_t *domain, char *name)
     ipmi_unlock(domain->domain_lock);
 }
 
+int
+ipmi_domain_is_fully_up(ipmi_domain_t *domain)
+{
+    return domain->fully_up_count == 0;
+}
+
 /***********************************************************************
  *
  * Domain data structure creation and destruction
diff --git a/lib/event.c b/lib/event.c
index b69cf24..8230e55 100644
--- a/lib/event.c
+++ b/lib/event.c
@@ -385,9 +385,9 @@ sensor_event_call(ipmi_sensor_t *sensor, void *cb_data)
 	raw_value = data[11];
 	value = 0.0;
 
-	if ((data[10] >> 6) == 2) {
+	if ((data[10] >> 6) == 1) {
 	    rv = ipmi_sensor_convert_from_raw(sensor, raw_value, &value);
-	    if (!rv)
+	    if (rv)
 		value_present = IPMI_RAW_VALUE_PRESENT;
 	    else
 		value_present = IPMI_BOTH_VALUES_PRESENT;
diff --git a/lib/lanparm.c b/lib/lanparm.c
index bb36264..f8b075f 100644
--- a/lib/lanparm.c
+++ b/lib/lanparm.c
@@ -886,6 +886,7 @@ struct ipmi_lan_config_s
     unsigned char  max_priv_for_cipher_suite_supported;
     unsigned char  max_priv_for_cipher_suite[16];
 
+    /* See the note in the gnd function foro weirdness about this field. */
     unsigned char num_alert_destinations;
     unsigned char  vlan_tag_supported;
     alert_dest_type_t *alert_dest_type;
@@ -1095,6 +1096,12 @@ static int gnd(ipmi_lan_config_t *lanc, lanparms_t *lp, int err,
     if (num == 0)
 	return 0;
 
+    /*
+     * This is important!  The number in this field is the number of
+     * non-volatile destinations.  There is a volatile destination
+     * at zero that is always present, and at least on non-volatile
+     * field is required if this paramter is non-zero.
+     */
     num++;
 
     lanc->alert_dest_type = ipmi_mem_alloc(sizeof(alert_dest_type_t) * num);
@@ -1554,7 +1561,7 @@ got_parm(ipmi_lanparm_t    *lanparm,
 	    if (lanc->num_alert_destinations == 0)
 		goto done;
 	    lanc->curr_parm = IPMI_LANPARM_DEST_VLAN_TAG;
-	    lanc->curr_sel = 1;
+	    lanc->curr_sel = 0;
 	}
 	break;
 
diff --git a/lib/normal_fru.c b/lib/normal_fru.c
index 91106cb..e1ac548 100644
--- a/lib/normal_fru.c
+++ b/lib/normal_fru.c
@@ -4801,11 +4801,10 @@ process_fru_info(ipmi_fru_t *fru)
 	        goto check_done;
 	}
 	if (foff[i].offset >= foff[j].offset) {
-	    ipmi_log(IPMI_LOG_ERR_INFO,
+	    ipmi_log(IPMI_LOG_WARNING,
 		     "%snormal_fru.c(process_fru_info):"
 		     " FRU fields did not occur in the correct order",
 		     _ipmi_fru_get_iname(fru));
-	    return EBADF;
 	}
     }
  check_done:
diff --git a/lib/rakp.c b/lib/rakp.c
index d4ffeef..6afd750 100644
--- a/lib/rakp.c
+++ b/lib/rakp.c
@@ -482,7 +482,7 @@ rakp_hmac_c2(rakp_info_t   *info,
 	return EINVAL;
     HMAC(rinfo->evp_md, p, rinfo->key_len, idata, 58+idata[57], integ_data, &ilen);
     if (memcmp(data+40, integ_data, rinfo->key_len) != 0)
-	return EKEYREJECTED;
+	return EINVAL;
 
     /* Now generate the SIK */
     p = ipmi_rmcpp_auth_get_my_rand(info->ainfo, &plen);
diff --git a/lib/sensor.c b/lib/sensor.c
index bb5971e..c6d9546 100644
--- a/lib/sensor.c
+++ b/lib/sensor.c
@@ -3695,9 +3695,9 @@ ipmi_sensor_event(ipmi_sensor_t *sensor, ipmi_event_t *event)
 	raw_value = data[11];
 	value = 0.0;
 
-	if ((data[10] >> 6) == 2) {
+	if ((data[10] >> 6) == 1) {
 	    rv = ipmi_sensor_convert_from_raw(sensor, raw_value, &value);
-	    if (!rv)
+	    if (rv)
 		value_present = IPMI_RAW_VALUE_PRESENT;
 	    else
 		value_present = IPMI_BOTH_VALUES_PRESENT;
diff --git a/man/Makefile.am b/man/Makefile.am
index dc26492..632f55b 100644
--- a/man/Makefile.am
+++ b/man/Makefile.am
@@ -1,5 +1,6 @@
 
 man_MANS = ipmi_ui.1 openipmicmd.1 openipmish.1 ipmi_cmdlang.7 \
-	openipmigui.1 openipmi_conparms.7 solterm.1 rmcp_ping.1
+	openipmigui.1 openipmi_conparms.7 solterm.1 rmcp_ping.1 \
+	openipmi_eventd.1
 
 EXTRA_DIST = $(man_MANS)
diff --git a/man/openipmi_eventd.1 b/man/openipmi_eventd.1
new file mode 100644
index 0000000..9f953a5
--- /dev/null
+++ b/man/openipmi_eventd.1
@@ -0,0 +1,168 @@
+.TH openipmi_eventd 1 03/4/15 OpenIPMI "IPMI event handler"
+
+.SH NAME
+openipmi_eventd \- An IPMI event handler
+
+.SH SYNOPSIS
+.B openipmi_eventd
+.BI "<domain\ name>"
+.BI "<connection\ parms>"
+.BI "<options>"
+.BI "<program> [<parm1> [<parm2> [...]]]"
+.SH DESCRIPTION
+The
+.BR openipmi_eventd
+program listens for IPMI events for the given connection and sends them
+to another program to process, or to a file.
+
+.SH PARAMETERS
+.TP
+.BI <domain\ name>
+The name to use for the OpenIPMI domain.  This will appear in logs and
+some names.
+
+.TP
+.BI <connection\ parms>
+The parameters for the connection depend on the connection type.
+These are all described in openipmi_conparms (7)
+
+.TP
+.BI <options>
+Zero or more of the options defined in OPTIONS below.
+
+.TP
+.BI <program>\ [<parm1>\ [<parm2>\ [...]]]
+The program to run.  This must be the full path to the program.  Any
+given parameters are passed to the program before any IPMI parameters.
+
+.SH OPTIONS
+.TP
+\fB\-f\fR filename, \fB\-\-outfile\fR filename
+Send all events to the given file
+
+.TP
+\fB\-k\fR, \fB\-\-exec\-now\fR
+Immediately spawn the given program and send the event information to that
+program's standard input.  The program should not quit, if it does then
+this program will exit with an error.
+
+.TP
+\fB\-i\fR, \fB\-\-event\-stdin\fR
+Send the event information to the program's standard input instead of
+the commandline.
+
+.TP
+\fB\-e\fR, \fB\-\-delete\-events\fR
+Delete events from the SEL (System Event Log) once they have been
+processed.  Note that the program has to have handled the event
+without error for the event to be deleted.  Otherwise the events are
+not deleted from the SEL.
+
+.TP
+\fB\-b\fR, \fB\-\-dont\-daemonize\fR
+Do not daemonize the program, run it as a foreground process.
+
+.TP
+\fB\-d\fR, \fB\-\-debug\fR
+Debug the program, turn on output, send all logs to stderr, and do not
+run the process as a daemon.
+
+.SH "USAGE"
+When started, this program will connect to the given IPMI domain,
+ignore all existing logs, and set up to listen from logs from all
+sources.  When an event comes in, it will handle the event depending
+on how it is configured.
+
+By default the program will be called on each log and the event information
+passed on the program's command line. The first parameter (after the ones
+given on the
+.BR openipmi_eventd
+command line) will be the event type, the rest are key-value pairs as
+defined below.
+
+If
+.BI \-i
+is given on the commandline, instead of passing in the event information
+on the command line, it will be passed into the program's standard input.
+The first line will be the event type, and each line will have a key-value
+pair up until the last line, which will be
+.BI endevent.
+
+If
+.BI \-k
+is given on the command line, the program will be started immediately and
+expected to take events on its standard input as they come in.  Each
+event will start with an event type, contain key-value pairs, and end
+in 
+.BI endevent.
+
+.SH "EVENT KEY-VALUE PAIRS"
+
+The first line and parameter of an event is always the event type
+(either
+.BI threshold
+,
+.BI discrete
+, or
+.BI unknown
+).  Then the following
+then the following, in no particular order.  When sending to a file,
+or another program via standard input,
+.BI endevent
+will mark the end of an event.
+
+.RS
+.IP assert\ true|false
+If true, the event is being asserted (the alarm
+present).  If false, the alarm was present but has now gone
+away.
+.IP eventtype\ <num>
+The event type, per the IPMI specification.
+.IP eventtime\ <num>
+The time (in seconds) for the IPMI event.  It is 64 bits.
+.IP eventdata\ <vals>
+The raw event data, vals is a list of hex numbers.
+.IP id\ <name>
+The OpenIPMI id of the sensor.  This is in the format:
+.BI <entity_id>.<entity_instance>.<sensor_name>
+where the entity id and instance identify the object being
+monitored and the sensor names comes from the sensor.  Only
+for discrete and threshold events.
+.IP val\ <floatnum>
+The sensor value that cause the event, in floating point format.
+Optional and only present for threshold sensors.
+.IP raw\ <hexnum>
+The sensor value that cause the event, in raw (hex) format.  Optional
+and only present for threshold sensors.
+.IP off\ <num>
+The bit in the sensor that caused the event, only present for discrete sensors.
+.IP severity
+The severity of the event.  For discrete sensors this optional and is a
+number between 0 and 14.  Them meaning depends on the specific sensor type.
+For threshold sensors this is one of:
+.RS
+.IP lower_non_critical
+.IP lower_critical
+.IP lower_non_recoverable
+.IP upper_non_critical
+.IP upper_critical
+.IP upper_non_recoverable
+.RE
+.IP prevseverity - The severity before the event, optional and only present
+for discrete sensors.
+.IP direction going_low|going_high
+The direction of the event, only for threshold sensors.  This can be
+difficult to understand and is not consistent on IPMI systems.  The
+IPMI specifiation does define what this means.  For instance, what
+does an assertion of an upper critcal event going low mean?
+.RE
+
+.SH "SEE ALSO"
+.BR openipmi_conparms (7)
+
+.SH "KNOWN PROBLEMS"
+None
+
+.SH AUTHOR
+.PP
+Corey Minyard <cminyard@mvista.com>
diff --git a/sample/Makefile.am b/sample/Makefile.am
index febba2f..06278bd 100644
--- a/sample/Makefile.am
+++ b/sample/Makefile.am
@@ -2,7 +2,7 @@
 AM_CFLAGS = -Wall -Wsign-compare -I$(top_builddir)/include \
 	-I$(top_srcdir)/include -DIPMI_CHECK_LOCKS
 
-bin_PROGRAMS = openipmicmd solterm rmcp_ping
+bin_PROGRAMS = openipmicmd solterm rmcp_ping openipmi_eventd
 
 noinst_PROGRAMS = ipmisample ipmisample2 ipmisample3 ipmi_serial_bmc_emu \
 		  ipmi_dump_sensors waiter_sample
@@ -31,6 +31,12 @@ waiter_sample_LDADD = $(top_builddir)/utils/libOpenIPMIutils.la \
 		$(top_builddir)/unix/libOpenIPMIposix.la \
 		$(OPENSSLLIBS)
 
+openipmi_eventd_SOURCES = eventd.c
+openipmi_eventd_LDADD = $(top_builddir)/utils/libOpenIPMIutils.la \
+		$(top_builddir)/lib/libOpenIPMI.la \
+		$(top_builddir)/unix/libOpenIPMIposix.la \
+		$(OPENSSLLIBS)
+
 ipmi_dump_sensors_SOURCES = dump_sensors.c
 ipmi_dump_sensors_LDADD = $(top_builddir)/utils/libOpenIPMIutils.la \
 		$(top_builddir)/lib/libOpenIPMI.la \
@@ -65,4 +71,4 @@ install-data-local:
 	$(LN_S) openipmicmd $(DESTDIR)$(bindir)/ipmicmd
 
 uninstall-local:
-	rm -f $(DESTDIR)$(bindir)/ipmicmd
\ No newline at end of file
+	rm -f $(DESTDIR)$(bindir)/ipmicmd
diff --git a/sample/eventd.c b/sample/eventd.c
new file mode 100644
index 0000000..1ae1600
--- /dev/null
+++ b/sample/eventd.c
@@ -0,0 +1,770 @@
+/*
+ * eventd.c
+ *
+ * OpenIPMI event logging daemon
+ *
+ * This program takes IPMI events and calls an external program to
+ * handle them.  See the man page for usage details.
+ *
+ * Author: Corey Minyard <cminyard@mvista.com>
+ *
+ *  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 <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <ctype.h>
+#include <time.h>
+#include <syslog.h>
+
+#include <OpenIPMI/ipmiif.h>
+#include <OpenIPMI/ipmi_err.h>
+#include <OpenIPMI/ipmi_posix.h>
+
+#define STDERR_IPMIERR(err, format, ...) \
+    do {								\
+	char errstr[128];						\
+	ipmi_get_error_string(err, errstr, sizeof(errstr));		\
+	fprintf(stderr, "%s: " format ": %s\n", domainname, ##__VA_ARGS__, \
+		errstr);						\
+    } while(0)
+
+#define SYSLOG_IPMIERR(level, err, format, ...) \
+    do {								\
+	char errstr[128];						\
+	ipmi_get_error_string(err, errstr, sizeof(errstr));		\
+	syslog(level, "%s: " format ": %s", domainname, ##__VA_ARGS__, errstr);\
+    } while(0)
+
+#define debug_printf(format, ...) \
+    do {								\
+	if (debug)							\
+	    printf(format, ##__VA_ARGS__);				\
+    } while(0)
+
+static const char *progname;
+static char **prog;
+static int num_prog;
+static bool progstdio;
+static FILE *outfile;
+static char *domainname;
+static bool domain_up;
+static bool delete_events;
+static int debug;
+static int childpid = -1;
+
+static char *indent_str(const char *instr, const char *indent)
+{
+    int p, o;
+    int ilen = strlen(indent);
+    size_t extra = 0;
+    char *s;
+
+    for (p = 0; instr[p]; p++) {
+	if (instr[p] == '\n')
+	    extra += ilen;
+    }
+    if (extra == 0)
+	return (char *) instr;
+    s = malloc(strlen(instr) + extra + 1);
+    if (!s)
+	return NULL;
+    for (p = 0, o = 0; instr[p]; p++) {
+	s[o++] = instr[p];
+	if (instr[p] == '\n') {
+	    memcpy(s + o, indent, ilen);
+	    o += ilen;
+	}
+    }
+    s[o] = '\0';
+    return s;
+}
+
+static void con_usage(const char *name, const char *help, void *cb_data)
+{
+    char *newhelp = indent_str(help, "     ");
+    printf("\n %s%s", name, newhelp);
+    if (newhelp != help)
+	free(newhelp);
+}
+
+static void
+usage(void)
+{
+    printf("Usage:\n");
+    printf(" %s <domain> <con_parms> [-k] [-i] [-e] [-d] [-b] [-f <filename>] <program> [<parm1> [<parm2> [...]]]\n",
+	   progname);
+    printf("<domain> is a name given to locally identify the connection.\n");
+    printf("Options are:\n");
+    printf(" -k, --exec-now - Execute the program at startup and feed it\n");
+    printf("    events through stdin.\n");
+    printf(" -i, --event-stdin - Execute the program for each event, but\n");
+    printf("    feed it input through stdin.\n");
+    printf(" -e, --delete-events - Delete each event after processing.\n");
+    printf(" -d, --debug - Enable debugging\n");
+    printf(" -b, --dont-daemonize - Run the program in foreground.\n");
+    printf(" -f, --outfile - Send the output to the given file instead of\n");;
+    printf("    spawning another program.\n");
+    printf("<con_parms> is:");
+    ipmi_parse_args_iter_help(con_usage, NULL);
+}
+
+static int
+send_parms_to_file(char *type, char **parms1, int num_parms1,
+		   char **parms2, int num_parms2)
+{
+    int i;
+    fprintf(outfile, "%s\n", type);
+    for (i = 0; i + 1 < num_parms1; i += 2)
+	fprintf(outfile, "%s %s\n", parms1[i], parms1[i + 1]);
+    for (i = 0; i + 1 < num_parms2; i += 2)
+	fprintf(outfile, "%s %s\n", parms2[i], parms2[i + 1]);
+    fprintf(outfile, "endevent\n");
+    if (fflush(outfile) == -1) {
+	syslog(LOG_CRIT, "%s: Destination end of pipe failed: %s\n",
+	       domainname, strerror(errno));
+	return -1;
+    }
+
+    return 0;
+}
+
+static int
+newpipe(FILE **retfile)
+{
+    int fds[2];
+    FILE *f;
+
+    if (pipe(fds) == -1) {
+	syslog(LOG_ERR, "%s: Unable to open pipe to subprogram: %s",
+	       domainname, strerror(errno));
+	return -1;
+    }
+
+    f = fdopen(fds[1], "w");
+    if (!f) {
+	syslog(LOG_ERR, "%s: Unable to fdopen pipe to subprogram: %s",
+	       domainname, strerror(errno));
+	close(fds[0]);
+	close(fds[1]);
+	return -1;
+    }
+
+    *retfile = f;
+    return fds[0];
+}
+
+static void
+send_event_to_prog(char         *type,
+		   ipmi_event_t *event,
+		   char         **parms,
+		   int          num_parms)
+{
+    char typestr[30];
+    char timestr[30];
+    char datastr[128];
+    char *parms2[6];
+    int num_parms2 = 0;
+    pid_t pid;
+    int infd = -1;
+    bool handled = false;
+
+    if (event) {
+	int pos = 0;
+	unsigned int i, len;
+	unsigned char eventdata[16];
+
+	parms2[num_parms2++] = "eventtype";
+	parms2[num_parms2++] = typestr;
+	snprintf(typestr, sizeof(typestr), "0x%x", ipmi_event_get_type(event));
+
+	parms2[num_parms2++] = "eventtime";
+	parms2[num_parms2++] = timestr;
+	snprintf(timestr, sizeof(timestr), "%lld",
+		 (long long) ipmi_event_get_timestamp(event));
+
+	parms2[num_parms2++] = "eventdata";
+	parms2[num_parms2++] = datastr;
+	datastr[0] = '\0';
+	len = ipmi_event_get_data_len(event);
+	if (len > sizeof(eventdata))
+	    len = sizeof(eventdata);
+	ipmi_event_get_data(event, eventdata, 0, len);
+	for (i = 0; i < len; i++) {
+	    pos += snprintf(datastr + pos, sizeof(datastr) - pos, " 0x%2.2x",
+			    eventdata[i]);
+	}
+    }
+
+    if (!domain_up)
+	goto out;
+
+    if (outfile) {
+	if (send_parms_to_file(type, parms, num_parms, parms2, num_parms2))
+	    /* The remote end is broken, give up. */
+	    exit(1);
+	handled = true;
+	goto out;
+    }
+
+    if (progstdio) {
+	infd = newpipe(&outfile);
+	if (infd == -1)
+	    goto out_close;
+    }
+	
+    pid = fork();
+    if (pid < 0) {
+	syslog(LOG_ERR, "%s: Unable to fork: %s\n", domainname,
+	strerror(errno));
+    } else if (pid > 0) {
+	int rv, status;
+
+	if (outfile) {
+	    if (!send_parms_to_file(type, parms, num_parms, parms2, num_parms2))
+		handled = true;
+
+	    /*
+	     * Close the output here, instead of later, to give a hint to
+	     * the program receiving the data that we are done.
+	     */
+	    fclose(outfile);
+	    outfile = NULL;
+	}
+
+	/* Wait here so multiple events don't get out of order. */
+	rv = waitpid(pid, &status, 0);
+
+	/* If the calling program failed, don't delete the event. */
+	if (rv == -1)
+	    handled = false;
+	else if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
+	    handled = false;
+    } else if (outfile) {
+	fclose(outfile);
+	close(0);
+	if (dup(infd) != 0)
+	    exit(1);
+	close(infd);
+	execv(prog[0], prog);
+	syslog(LOG_ERR, "%s: Unable to execute program: %s\n", domainname,
+	       strerror(errno));
+	exit(1);
+    } else {
+	char **execvals;
+	execvals = malloc((num_parms + num_parms2 + num_prog + 2)
+			  * sizeof(char *));
+	if (!execvals) {
+	    syslog(LOG_ERR, "%s: Out of memory allocating execvals",
+		   domainname);
+	    goto out_close;
+	}
+
+	memcpy(execvals, prog, num_prog * sizeof(char *));
+	execvals[num_prog] = type;
+	memcpy(execvals + num_prog + 1, parms, num_parms * sizeof(char *));
+	memcpy(execvals + num_prog + num_parms + 1, parms2,
+	       num_parms2 * sizeof(char *));
+	execvals[num_prog + num_parms + num_parms2 + 1] = NULL;
+
+	execv(execvals[0], execvals);
+	syslog(LOG_ERR, "%s: Unable to execute program: %s\n", domainname,
+	       strerror(errno));
+	exit(1);
+    }
+
+ out_close:
+    if (outfile) {
+	fclose(outfile);
+	outfile = NULL;
+    }
+ out:
+    if (handled && event && delete_events)
+	ipmi_event_delete(event, NULL, NULL);
+    return;
+}
+
+static void
+send_sensor_event_to_prog(ipmi_sensor_t               *sensor,
+			  enum ipmi_event_dir_e       dir,
+			  ipmi_event_t                *event,
+			  char                        *type,
+			  char                        **parms,
+			  int                         num_parms)
+{
+    ipmi_entity_t *ent = ipmi_sensor_get_entity(sensor);
+    int id, instance, pos;
+    char idstr[128];
+
+    
+    parms[num_parms++] = "assert";
+    parms[num_parms++] = (dir == IPMI_ASSERTION) ? "true" : "false";
+
+    parms[num_parms++] = "id";
+    parms[num_parms++] = idstr;
+    id = ipmi_entity_get_entity_id(ent);
+    instance = ipmi_entity_get_entity_instance(ent);
+    pos = snprintf(idstr, sizeof(idstr), "%d.%d.", id, instance);
+    ipmi_sensor_get_id(sensor, idstr + pos, sizeof(idstr) - pos - 1);
+    idstr[127] = '\0';
+
+    send_event_to_prog(type, event, parms, num_parms);
+}
+
+/*
+ * Enough to add the id.
+ */
+#define MAX_EXTRA_PARMS 4
+
+char *thresh_to_severity[6] = {
+    "lower_non_critical",
+    "lower_critical",
+    "lower_non_recoverable",
+    "upper_non_critical",
+    "upper_critical",
+    "upper_non_recoverable"
+};
+
+static int
+sensor_threshold_event_handler(ipmi_sensor_t               *sensor,
+			       enum ipmi_event_dir_e       dir,
+			       enum ipmi_thresh_e          threshold,
+			       enum ipmi_event_value_dir_e high_low,
+			       enum ipmi_value_present_e   value_present,
+			       unsigned int                raw_value,
+			       double                      value,
+			       void                        *cb_data,
+			       ipmi_event_t                *event)
+{
+    char *parms[10 + MAX_EXTRA_PARMS];
+    int num_parms = 0;
+    char valstr[30];
+    char rawstr[30];
+
+    debug_printf("threshold event handler\n");
+
+    parms[num_parms++] = "severity";
+    parms[num_parms++] = thresh_to_severity[threshold];
+
+    parms[num_parms++] = "direction";
+    parms[num_parms++] = high_low == IPMI_GOING_LOW ?
+	"going_low" : "going_high";
+
+    if (value_present == IPMI_BOTH_VALUES_PRESENT) {
+	parms[num_parms++] = "val";
+	parms[num_parms++] = valstr;
+	snprintf(valstr, sizeof(valstr), "%f", value);
+	parms[num_parms++] = "raw";
+	parms[num_parms++] = rawstr;
+	snprintf(rawstr, sizeof(rawstr), "0x%2.2x", raw_value);
+    } else if (value_present == IPMI_RAW_VALUE_PRESENT) {
+	parms[num_parms++] = "raw";
+	parms[num_parms++] = rawstr;
+	snprintf(rawstr, sizeof(rawstr), "0x%2.2x", raw_value);
+    }
+
+    send_sensor_event_to_prog(sensor, dir, event, "threshold",
+			      parms, num_parms);
+
+    /* Don't pass this on. */
+    return IPMI_EVENT_HANDLED;
+}
+
+static int
+sensor_discrete_event_handler(ipmi_sensor_t         *sensor,
+			      enum ipmi_event_dir_e dir,
+			      int                   offset,
+			      int                   severity,
+			      int                   prev_severity,
+			      void                  *cb_data,
+			      ipmi_event_t          *event)
+{
+    char *parms[6 + MAX_EXTRA_PARMS];
+    int num_parms = 0;
+    char sevstr[30];
+    char prevstr[30];
+    char offstr[30];
+
+    debug_printf("discrete event handler\n");
+
+    parms[num_parms++] = "offset";
+    parms[num_parms++] = offstr;
+    snprintf(offstr, sizeof(offstr), "%d", offset);
+
+    if (severity != -1) {
+	parms[num_parms++] = "severity";
+	parms[num_parms++] = sevstr;
+	snprintf(sevstr, sizeof(sevstr), "%d", severity);
+    }
+
+    if (prev_severity != -1) {
+	parms[num_parms++] = "prevseverity";
+	parms[num_parms++] = prevstr;
+	snprintf(prevstr, sizeof(prevstr), "%d", prev_severity);
+    }
+
+    send_sensor_event_to_prog(sensor, dir, event, "discrete",
+			      parms, num_parms);
+
+    /* Don't pass this on. */
+    return IPMI_EVENT_HANDLED;
+}
+
+static void
+default_event_handler(ipmi_domain_t *domain,
+		      ipmi_event_t  *event,
+		      void          *event_data)
+{
+    debug_printf("default event handler\n");
+
+    send_event_to_prog("unknown", event, NULL, 0);
+}
+
+/* Whenever the status of a sensor changes, the function is called
+   We display the information of the sensor if we find a new sensor
+*/
+static void
+sensor_change(enum ipmi_update_e op,
+	      ipmi_entity_t      *ent,
+	      ipmi_sensor_t      *sensor,
+	      void               *cb_data)
+{
+    int id, instance;
+    char name[33];
+    int rv;
+
+    id = ipmi_entity_get_entity_id(ent);
+    instance = ipmi_entity_get_entity_instance(ent);
+    ipmi_sensor_get_id(sensor, name, 32);
+    if (op == IPMI_ADDED) {
+	debug_printf("Sensor added: %d.%d.%s\n", id, instance, name);
+
+	if (ipmi_sensor_get_event_reading_type(sensor)
+	    == IPMI_EVENT_READING_TYPE_THRESHOLD)
+	    rv = ipmi_sensor_add_threshold_event_handler
+		(sensor,
+		 sensor_threshold_event_handler,
+		 NULL);
+	else
+	    rv = ipmi_sensor_add_discrete_event_handler
+		(sensor,
+		 sensor_discrete_event_handler,
+		 NULL);
+	if (rv) {      
+	    SYSLOG_IPMIERR(LOG_CRIT, rv, "Unable to add sensor event handler");
+	    exit(1);
+	}
+    }
+}
+
+/* Whenever the status of an entity changes, the function is called
+   When a new entity is created, we search all sensors that belong 
+   to the entity */
+static void
+entity_change(enum ipmi_update_e op,
+	      ipmi_domain_t      *domain,
+	      ipmi_entity_t      *entity,
+	      void               *cb_data)
+{
+    int rv;
+    int id, instance;
+
+    id = ipmi_entity_get_entity_id(entity);
+    instance = ipmi_entity_get_entity_instance(entity);
+    if (op == IPMI_ADDED) {
+	debug_printf("Entity added: %d.%d\n", id, instance);
+	/* Register callback so that when the status of a
+	   sensor changes, sensor_change is called */
+	rv = ipmi_entity_add_sensor_update_handler(entity,
+						   sensor_change,
+						   entity);
+	if (rv) {
+	    SYSLOG_IPMIERR(LOG_CRIT, rv, "Unable to add sensor update handler");
+	    exit(1);
+	}
+    }
+}
+
+/* After we have established connection to domain, this function get called
+   At this time, we can do whatever things we want to do. Herr we want to
+   search all entities in the system */ 
+void
+setup_done(ipmi_domain_t *domain,
+	   int           err,
+	   unsigned int  conn_num,
+	   unsigned int  port_num,
+	   int           still_connected,
+	   void          *user_data)
+{
+    int rv;
+
+    if (err) {
+	SYSLOG_IPMIERR(LOG_CRIT, err, "Unable to connect to domain");
+	exit(1);
+    }
+
+    rv = ipmi_domain_add_event_handler(domain, default_event_handler, NULL);
+    if (rv) {      
+	SYSLOG_IPMIERR(LOG_CRIT, rv, "Unable to add default event handler");
+	exit(1);
+    }
+
+    /* Register a callback functin entity_change. When a new entities 
+       is created, entity_change is called */
+    rv = ipmi_domain_add_entity_update_handler(domain, entity_change, domain);
+    if (rv) {      
+	SYSLOG_IPMIERR(LOG_CRIT, rv, "Unable to add entity update handler");
+	exit(1);
+    }
+}
+
+static os_handler_t *os_hnd;
+
+static void
+handle_openipmi_vlog(os_handler_t         *handler,
+		     const char           *format,
+		     enum ipmi_log_type_e log_type,
+		     va_list              ap)
+{
+    int level;
+    char *newformat;
+
+    switch(log_type)
+    {
+    case IPMI_LOG_INFO: level = LOG_INFO; break;
+    case IPMI_LOG_WARNING: level = LOG_WARNING; break;
+    case IPMI_LOG_SEVERE: level = LOG_ERR; break;
+    case IPMI_LOG_FATAL: level = LOG_CRIT; break;
+    case IPMI_LOG_ERR_INFO: level = LOG_WARNING; break;
+
+    case IPMI_LOG_DEBUG_START:
+    case IPMI_LOG_DEBUG:
+    case IPMI_LOG_DEBUG_CONT:
+    case IPMI_LOG_DEBUG_END:
+	level = LOG_DEBUG;
+	break;
+    default:
+	level = LOG_NOTICE;
+    }
+
+    newformat = malloc(strlen(format) + strlen(domainname) + 3);
+    if (!newformat) {
+	vsyslog(level, format, ap);
+	return;
+    }
+
+    strcpy(newformat, domainname);
+    strcat(newformat, ": ");
+    strcat(newformat, format);
+    vsyslog(level, newformat, ap);
+    free(newformat);
+}
+
+static void
+fully_up(ipmi_domain_t *domain, void *cb_data)
+{
+    debug_printf("Fully up!\n");
+    domain_up = 1;
+}
+
+static void
+sigchld_handler(int sig)
+{
+    syslog(LOG_CRIT, "%s: Child process failed\n", domainname);
+    exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+    int         rv;
+    int         curr_arg = 2;
+    ipmi_args_t *args;
+    ipmi_con_t  *con;
+    bool        execnow = false;
+    bool        daemonize = true;
+    char        *outfname = NULL;
+    int         syslog_options = 0;
+
+    if (argc < 2) {
+	fprintf(stderr, "No domain name given\n");
+	exit(1);
+    }
+
+    progname = argv[0];
+    domainname = argv[1];
+
+    /* OS handler allocated first. */
+    os_hnd = ipmi_posix_setup_os_handler();
+    if (!os_hnd) {
+	fprintf(stderr, "ipmi_smi_setup_con: Unable to allocate os handler\n");
+	exit(1);
+    }
+
+    /* Override the default log handler. */
+    os_hnd->set_log_handler(os_hnd, handle_openipmi_vlog);
+
+    rv = ipmi_init(os_hnd);
+    if (rv) {
+	STDERR_IPMIERR(rv, "Error in ipmi initialization");
+	exit(1);
+    }
+
+    rv = ipmi_parse_args2(&curr_arg, argc, argv, &args);
+    if (rv) {
+	STDERR_IPMIERR(rv, "Error parsing command arguments, argument %d",
+		       curr_arg);
+	usage();
+	exit(1);
+    }
+
+    while (curr_arg < argc && argv[curr_arg][0] == '-') {
+	int a = curr_arg;
+	curr_arg++;
+	if (strcmp(argv[a], "--") == 0)
+	    break;
+	if ((strcmp(argv[a], "-i") == 0) ||
+	    (strcmp(argv[a], "--event-stdin") == 0))
+	    progstdio = true;
+	else if ((strcmp(argv[a], "-k") == 0) ||
+		 (strcmp(argv[a], "--exec-now") == 0))
+	    execnow = true;
+	else if ((strcmp(argv[a], "-e") == 0) ||
+		 (strcmp(argv[a], "--delete-events") == 0))
+	    delete_events = true;
+	else if ((strcmp(argv[a], "-d") == 0) ||
+		 (strcmp(argv[a], "--debug") == 0)) {
+	    debug++;
+	    daemonize = false;
+	} else if ((strcmp(argv[a], "-b") == 0) ||
+		   (strcmp(argv[a], "--dont-daemonize") == 0))
+	    daemonize = false;
+	else if ((strcmp(argv[a], "-f") == 0) ||
+		 (strcmp(argv[a], "--outfile") == 0)) {
+	    if (curr_arg == argc) {
+		fprintf(stderr, "-f given, but no filename given\n");
+		exit(1);
+	    }
+	    outfname = argv[curr_arg];
+	    curr_arg++;
+	} else {
+	    fprintf(stderr, "Unknown parameter: %s\n", argv[a]);
+	    exit(1);
+	}
+	    
+    }
+
+    prog = argv + curr_arg;
+    num_prog = argc - curr_arg;
+
+    if (debug)
+	syslog_options |= LOG_PERROR;
+
+    openlog("openipmi_syslog", syslog_options, LOG_DAEMON);
+
+    rv = ipmi_args_setup_con(args, os_hnd, NULL, &con);
+    if (rv) {
+        STDERR_IPMIERR(rv, "ipmi_ip_setup_con failed");
+	exit(1);
+    }
+
+    rv = ipmi_open_domain(domainname, &con, 1, setup_done, NULL, fully_up, NULL,
+			  NULL, 0, NULL);
+    if (rv) {
+        STDERR_IPMIERR(rv, "ipmi_open domain failed");
+	exit(1);
+    }
+
+    if (outfname) {
+	if (curr_arg != argc || execnow) {
+	    fprintf(stderr, "You can't specify a program or -k"
+		    " along with -f\n");
+	    exit(1);
+	}
+	outfile = fopen(outfname, "a");
+	if (!outfile) {
+	    fprintf(stderr, "Unable to output output file %s: %s\n", outfname,
+		    strerror(errno));
+	    exit(1);
+	}
+    } else if (curr_arg == argc) {
+	fprintf(stderr, "No program given to execute on an IPMI event\n");
+	exit(1);
+    }
+
+    if (execnow) {
+	/* Only watch for child processes if we keep it around. */
+	if (signal(SIGCHLD, sigchld_handler) == SIG_ERR) {
+	    fprintf(stderr, "Unable to install sigchld handler: %s\n",
+		    strerror(errno));
+	    exit(1);
+	}
+    }
+
+    /*
+     * We have to daemonize before we fork or sigchld won't work.
+     */
+    if (daemonize)
+	daemon(0, 0);
+
+    if (execnow) {
+	int infd = newpipe(&outfile);
+
+	if (infd == -1) {
+	    fprintf(stderr, "Unable to open pipe, see syslog for errors\n");
+	    exit(1);
+	}
+	
+	childpid = fork();
+	if (childpid < 0) {
+	    syslog(LOG_CRIT, "%s: Unable to fork: %s\n", domainname,
+		   strerror(errno));
+	    exit(1);
+	} else if (childpid == 0) {
+	    close(0);
+	    if (dup(infd) != 0) {
+		syslog(LOG_CRIT, "%s: Dup didn't set stdin\n", domainname);
+		exit(1);
+	    }
+	    close(infd);
+	    execv(prog[0], prog);
+	    syslog(LOG_CRIT, "%s: Unable to exec %s: %s\n", domainname, prog[0],
+		    strerror(errno));
+	    exit(1);
+	}
+    }
+
+    /* Let the selector code run the select loop. */
+    os_hnd->operation_loop(os_hnd);
+
+    /* Technically, we can't get here, but just to be sure... */
+    os_hnd->free_os_handler(os_hnd);
+    return 0;
+}
diff --git a/swig/python/openipmigui/gui.py b/swig/python/openipmigui/gui.py
index 39801e6..3226cd1 100644
--- a/swig/python/openipmigui/gui.py
+++ b/swig/python/openipmigui/gui.py
@@ -38,6 +38,7 @@ import gui_errstr
 import gui_cmdwin
 import gui_list
 import gui_popup
+import gui_winsys
 
 init_treenamewidth = 150
 init_sashposition = 400
@@ -49,14 +50,6 @@ init_logevents = False
 init_fullevents = False
 init_impt_objs = [ ]
 
-try:
-    winsys = self.tk.eval("return [ tk windowingsystem ]")
-    pass
-except:
-    # Assume x11
-    winsys = "x11"
-    pass
-
 refresh_timer_time = 10000
 
 class IPMITreeDummyItem:
@@ -218,7 +211,7 @@ class IPMIGUI(Tix.Frame):
         self.tree.hlist.bind("<Button-3>", self.TreeMenu)
         
         self.tree.hlist.bind("<MouseWheel>", self.Wheel)
-        if (winsys == "x11"):
+        if (gui_winsys.winsys == "x11"):
             self.tree.hlist.bind("<Button-4>", self.ButtonUp)
             self.tree.hlist.bind("<Button-5>", self.ButtonDown)
             pass
diff --git a/swig/python/openipmigui/gui_list.py b/swig/python/openipmigui/gui_list.py
index 18677c5..b8c5d72 100644
--- a/swig/python/openipmigui/gui_list.py
+++ b/swig/python/openipmigui/gui_list.py
@@ -32,7 +32,7 @@
 
 import Tix
 import gui_errstr
-import gui
+import gui_winsys
 
 # A list widget that can be embedded in something else
 class SubList(Tix.ScrolledHList):
@@ -55,7 +55,7 @@ class SubList(Tix.ScrolledHList):
         self.bind("<Destroy>", self.OnDestroy)
 
         self.hlist.bind("<MouseWheel>", self.Wheel)
-        if (gui.winsys == "x11"):
+        if (gui_winsys.winsys == "x11"):
             self.hlist.bind("<Button-4>", self.ButtonUp)
             self.hlist.bind("<Button-5>", self.ButtonDown)
             pass
diff --git a/swig/python/openipmigui/gui_treelist.py b/swig/python/openipmigui/gui_treelist.py
index 5d37ae2..7c4a45e 100644
--- a/swig/python/openipmigui/gui_treelist.py
+++ b/swig/python/openipmigui/gui_treelist.py
@@ -32,7 +32,7 @@
 
 import Tix
 import gui_errstr
-import gui
+import gui_winsys
 
 class TreeList(Tix.Toplevel):
     def __init__(self, name, root, columns):
@@ -84,7 +84,7 @@ class TreeList(Tix.Toplevel):
         self.bind("<Destroy>", self.OnDestroy)
         
         self.bind("<MouseWheel>", self.Wheel)
-        if (gui.winsys == "x11"):
+        if (gui_winsys.winsys == "x11"):
             self.bind("<Button-4>", self.ButtonUp)
             self.bind("<Button-5>", self.ButtonDown)
             pass
diff --git a/swig/python/openipmigui/gui_winsys.py b/swig/python/openipmigui/gui_winsys.py
new file mode 100644
index 0000000..a19b837
--- /dev/null
+++ b/swig/python/openipmigui/gui_winsys.py
@@ -0,0 +1,40 @@
+# gui.py
+#
+# main openipmi GUI handling
+#
+# Author: MontaVista Software, Inc.
+#         Corey Minyard <minyard@mvista.com>
+#         source@mvista.com
+#
+# Copyright 2005 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.
+#
+
+try:
+    winsys = self.tk.eval("return [ tk windowingsystem ]")
+    pass
+except:
+    # Assume x11
+    winsys = "x11"
+    pass
+
diff --git a/tcl/Makefile.am b/tcl/Makefile.am
index b702819..e2a98dc 100644
--- a/tcl/Makefile.am
+++ b/tcl/Makefile.am
@@ -17,6 +17,7 @@ libOpenIPMItcl_la_LDFLAGS = -rdynamic -version-info $(LD_VERSION) \
 noinst_PROGRAMS = test_handlers
 
 test_handlers_SOURCES = test_handlers.c
+test_handlers_CFLAGS = $(TCL_CFLAGS) $(AM_CFLAGS)
 test_handlers_LDADD = libOpenIPMItcl.la \
 	$(top_builddir)/utils/libOpenIPMIutils.la $(GDBM_LIB) $(TCL_LIBS)
 
diff --git a/unix/Makefile.am b/unix/Makefile.am
index a792147..ac5b9f4 100644
--- a/unix/Makefile.am
+++ b/unix/Makefile.am
@@ -2,7 +2,7 @@
 LIB_VERSION = 0.0.1
 LD_VERSION = 0:1:0
 
-AM_CFLAGS = -Wall -Wsign-compare -I$(top_builddir)/include \
+AM_CFLAGS = -lrt -Wall -Wsign-compare -I$(top_builddir)/include \
 	-I$(top_srcdir)/include
 
 lib_LTLIBRARIES = libOpenIPMIposix.la libOpenIPMIpthread.la
diff --git a/unix/posix_thread_os_hnd.c b/unix/posix_thread_os_hnd.c
index 1110e01..a26fff8 100644
--- a/unix/posix_thread_os_hnd.c
+++ b/unix/posix_thread_os_hnd.c
@@ -392,11 +392,6 @@ sposix_log(os_handler_t         *handler,
 struct os_hnd_lock_s
 {
     pthread_mutex_t mutex;
-    int             lock_count;
-
-    /* This is volatile and we always set the owner before we set the count.
-       That avoids race conditions checking the count and owner. */
-    volatile pthread_t owner;
 };
 
 static int
@@ -404,19 +399,30 @@ create_lock(os_handler_t  *handler,
 	    os_hnd_lock_t **id)
 {
     os_hnd_lock_t *lock;
+    pthread_mutexattr_t attr;
     int           rv;
 
     lock = malloc(sizeof(*lock));
     if (!lock)
 	return ENOMEM;
-    rv = pthread_mutex_init(&lock->mutex, NULL);
-    if (rv) {
-	free(lock);
-	return rv;
-    }
-    lock->lock_count = 0;
+    rv = pthread_mutexattr_init(&attr);
+    if (rv)
+	goto out_err;
+    rv = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+    if (rv)
+	goto out_err_destroy;
+    rv = pthread_mutex_init(&lock->mutex, &attr);
+    if (rv)
+	goto out_err_destroy;
+    pthread_mutexattr_destroy(&attr);
     *id = lock;
     return 0;
+
+ out_err_destroy:
+    pthread_mutexattr_destroy(&attr);
+ out_err:
+    free(lock);
+    return rv;
 }
 
 static int
@@ -425,9 +431,6 @@ destroy_lock(os_handler_t  *handler,
 {
     int rv;
 
-    if (id->lock_count != 0)
-	handler->log(handler, IPMI_LOG_FATAL,
-		     "Destroy of lock when count is not zero");
     rv = pthread_mutex_destroy(&id->mutex);
     if (rv)
 	return rv;
@@ -441,13 +444,9 @@ lock(os_handler_t  *handler,
 {
     int rv;
 
-    if ((id->lock_count == 0) || (pthread_self() != id->owner)) {
-	rv = pthread_mutex_lock(&id->mutex);
-	if (rv)
-	    return rv;
-    }
-    id->owner = pthread_self();
-    id->lock_count++;
+    rv = pthread_mutex_lock(&id->mutex);
+    if (rv)
+	return rv;
     return 0;
 }
 
@@ -457,18 +456,9 @@ unlock(os_handler_t  *handler,
 {
     int rv;
 
-    if (id->lock_count == 0)
-	handler->log(handler, IPMI_LOG_FATAL, "lock count went negative");
-    if (pthread_self() != id->owner)
-	handler->log(handler, IPMI_LOG_FATAL, "lock release by non-owner");
-    id->lock_count--;
-    if (id->lock_count == 0) {
-	rv = pthread_mutex_unlock(&id->mutex);
-	if (rv) {
-	    id->lock_count++;
-	    return rv;
-	}
-    }
+    rv = pthread_mutex_unlock(&id->mutex);
+    if (rv)
+	return rv;
     return 0;
 }
 
@@ -531,15 +521,8 @@ cond_wait(os_handler_t  *handler,
 	  os_hnd_lock_t *lock)
 {
     int       rv;
-    int       old_lock_count;
-    pthread_t old_owner;
 
-    old_lock_count = lock->lock_count; 
-    old_owner = lock->owner;
-    lock->lock_count = 0;
     rv = pthread_cond_wait(&cond->cond, &lock->mutex);
-    lock->lock_count = old_lock_count;
-    lock->owner = old_owner;
     return rv;
 }
 
@@ -552,8 +535,6 @@ cond_timedwait(os_handler_t   *handler,
     struct timespec spec;
     struct timeval  now;
     int             rv;
-    int             old_lock_count;
-    pthread_t       old_owner;
 
     rv = handler->get_monotonic_time(handler, &now);
     if (rv)
@@ -565,12 +546,7 @@ cond_timedwait(os_handler_t   *handler,
 	spec.tv_sec += 1;
 	spec.tv_nsec -= 1000000000;
     }
-    old_lock_count = lock->lock_count; 
-    old_owner = lock->owner;
-    lock->lock_count = 0;
     rv = pthread_cond_timedwait(&cond->cond, &lock->mutex, &spec);
-    lock->lock_count = old_lock_count;
-    lock->owner = old_owner;
     return rv;
 }
 
openSUSE Build Service is sponsored by