summaryrefslogtreecommitdiff
path: root/lib/helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/helper.c')
-rw-r--r--lib/helper.c221
1 files changed, 176 insertions, 45 deletions
diff --git a/lib/helper.c b/lib/helper.c
index de91438..b547123 100644
--- a/lib/helper.c
+++ b/lib/helper.c
@@ -29,12 +29,6 @@
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*/
-#define _POSIX_SOURCE
-#define /* glibc 2.19 and earlier */ _BSD_SOURCE || \
- /* Since glibc 2.20 */_DEFAULT_SOURCE || \
- _XOPEN_SOURCE >= 500 || \
- _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED || \
- /* Since glibc 2.10: */ _POSIX_C_SOURCE >= 200112L \
#include <sys/types.h>
#include <sys/stat.h>
@@ -60,7 +54,7 @@
#ifdef HAVE_PATHS_H
# include <paths.h>
#else
-# define _PATH_VARRUN "/var/run/"
+# define _PATH_RUN "/run/"
#endif
#include <ipmitool/ipmi.h>
@@ -100,7 +94,7 @@ buf2str_extended(const uint8_t *buf, int len, const char *sep)
int left;
int sep_len;
- if (buf == NULL) {
+ if (!buf) {
snprintf(str, sizeof(str), "<NULL>");
return (const char *)str;
}
@@ -180,7 +174,7 @@ ipmi_parse_hex(const char *str, uint8_t *out, int size)
}
len /= 2; /* out bytes */
- if (out == NULL) {
+ if (!out) {
return -2;
}
@@ -234,6 +228,50 @@ void printbuf(const uint8_t * buf, int len, const char * desc)
fprintf(stderr, "\n");
}
+/*
+ * Unconditionally reverse the order of arbitrarily long strings of bytes
+ */
+uint8_t *array_byteswap(uint8_t *buffer, size_t length)
+{
+ size_t i;
+ uint8_t temp;
+ size_t max = length - 1;
+
+ for (i = 0; i < length / 2; ++i) {
+ temp = buffer[i];
+ buffer[i] = buffer[max - i];
+ buffer[max - i] = temp;
+ }
+
+ return buffer;
+}
+
+/* Convert data array from network (big-endian) to host byte order */
+uint8_t *array_ntoh(uint8_t *buffer, size_t length)
+{
+#if WORDS_BIGENDIAN
+ /* Big-endian host doesn't need conversion from big-endian network */
+ (void)length; /* Silence the compiler */
+ return buffer;
+#else
+ /* Little-endian host needs conversion from big-endian network */
+ return array_byteswap(buffer, length);
+#endif
+}
+
+/* Convert data array from little-endian to host byte order */
+uint8_t *array_letoh(uint8_t *buffer, size_t length)
+{
+#if WORDS_BIGENDIAN
+ /* Big-endian host needs conversion from little-endian IPMI */
+ return array_byteswap(buffer, length);
+#else
+ /* Little-endian host doesn't need conversion from little-endian IPMI */
+ (void)length; /* Silence the compiler */
+ return buffer;
+#endif
+}
+
/* str2mac - parse-out MAC address from given string and store it
* into buffer.
*
@@ -281,29 +319,77 @@ mac2str(const uint8_t *buf)
return buf2str_extended(buf, 6, ":");
}
-const char * val2str(uint16_t val, const struct valstr *vs)
+/**
+ * Find the index of value in a valstr array
+ *
+ * @param[in] val The value to search for
+ * @param[in] vs The valstr array to search in
+ * @return >=0 The index into \p vs
+ * @return -1 Error: value \p val was not found in \p vs
+ */
+static
+inline
+off_t find_val_idx(uint32_t val, const struct valstr *vs)
{
- static char un_str[32];
- int i;
-
- for (i = 0; vs[i].str != NULL; i++) {
- if (vs[i].val == val)
- return vs[i].str;
+ if (vs) {
+ for (off_t i = 0; vs[i].str; ++i) {
+ if (vs[i].val == val) {
+ return i;
+ }
+ }
}
+ return -1;
+}
+
+/**
+ * Generate a statically allocated 'Unknown' string for the provided value.
+ * The function is not thread-safe (as most of ipmitool).
+ *
+ * @param[in] val The value to put into the string
+ * @returns A pointer to a statically allocated string
+ */
+static
+inline
+const char *unknown_val_str(uint32_t val)
+{
+ static char un_str[32];
memset(un_str, 0, 32);
snprintf(un_str, 32, "Unknown (0x%02X)", val);
return un_str;
}
-const char * oemval2str(uint32_t oem, uint16_t val,
- const struct oemvalstr *vs)
+const char *
+specific_val2str(uint32_t val,
+ const struct valstr *specific,
+ const struct valstr *generic)
+{
+ int i;
+
+ if (0 <= (i = find_val_idx(val, specific))) {
+ return specific[i].str;
+ }
+
+ if (0 <= (i = find_val_idx(val, generic))) {
+ return generic[i].str;
+ }
+
+ return unknown_val_str(val);
+}
+
+const char *val2str(uint32_t val, const struct valstr *vs)
+{
+ return specific_val2str(val, NULL, vs);
+}
+
+
+const char *oemval2str(uint32_t oem, uint32_t val,
+ const struct oemvalstr *vs)
{
- static char un_str[32];
int i;
- for (i = 0; vs[i].oem != 0xffffff && vs[i].str != NULL; i++) {
+ for (i = 0; vs[i].oem != 0xffffff && vs[i].str; i++) {
/* FIXME: for now on we assume PICMG capability on all IANAs */
if ( (vs[i].oem == oem || vs[i].oem == IPMI_OEM_PICMG) &&
vs[i].val == val ) {
@@ -311,10 +397,7 @@ const char * oemval2str(uint32_t oem, uint16_t val,
}
}
- memset(un_str, 0, 32);
- snprintf(un_str, 32, "Unknown (0x%X)", val);
-
- return un_str;
+ return unknown_val_str(val);
}
/* str2double - safely convert string to double
@@ -559,12 +642,12 @@ int str2uchar(const char * str, uint8_t * uchr_ptr)
return 0;
} /* str2uchar(...) */
-uint16_t str2val(const char *str, const struct valstr *vs)
+uint32_t str2val32(const char *str, const struct valstr *vs)
{
int i;
- for (i = 0; vs[i].str != NULL; i++) {
- if (strncasecmp(vs[i].str, str, __maxlen(str, vs[i].str)) == 0)
+ for (i = 0; vs[i].str; i++) {
+ if (strcasecmp(vs[i].str, str) == 0)
return vs[i].val;
}
@@ -582,10 +665,10 @@ print_valstr(const struct valstr * vs, const char * title, int loglevel)
{
int i;
- if (vs == NULL)
+ if (!vs)
return;
- if (title != NULL) {
+ if (title) {
if (loglevel < 0)
printf("\n%s:\n\n", title);
else
@@ -600,7 +683,7 @@ print_valstr(const struct valstr * vs, const char * title, int loglevel)
lprintf(loglevel, "==============================================");
}
- for (i = 0; vs[i].str != NULL; i++) {
+ for (i = 0; vs[i].str; i++) {
if (loglevel < 0) {
if (vs[i].val < 256)
printf(" %d\t0x%02x\t%s\n", vs[i].val, vs[i].val, vs[i].str);
@@ -631,18 +714,18 @@ print_valstr_2col(const struct valstr * vs, const char * title, int loglevel)
{
int i;
- if (vs == NULL)
+ if (!vs)
return;
- if (title != NULL) {
+ if (title) {
if (loglevel < 0)
printf("\n%s:\n\n", title);
else
lprintf(loglevel, "\n%s:\n", title);
}
- for (i = 0; vs[i].str != NULL; i++) {
- if (vs[i+1].str == NULL) {
+ for (i = 0; vs[i].str; i++) {
+ if (!vs[i+1].str) {
/* last one */
if (loglevel < 0) {
printf(" %4d %-32s\n", vs[i].val, vs[i].str);
@@ -696,12 +779,12 @@ ipmi_open_file(const char * file, int rw)
struct stat st1, st2;
FILE * fp;
- /* verify existance */
+ /* verify existence */
if (lstat(file, &st1) < 0) {
if (rw) {
/* does not exist, ok to create */
fp = fopen(file, "w");
- if (fp == NULL) {
+ if (!fp) {
lperror(LOG_ERR, "Unable to open file %s "
"for write", file);
return NULL;
@@ -718,7 +801,7 @@ ipmi_open_file(const char * file, int rw)
if (!rw) {
/* on read skip the extra checks */
fp = fopen(file, "r");
- if (fp == NULL) {
+ if (!fp) {
lperror(LOG_ERR, "Unable to open file %s", file);
return NULL;
}
@@ -741,7 +824,7 @@ ipmi_open_file(const char * file, int rw)
}
fp = fopen(file, rw ? "w+" : "r");
- if (fp == NULL) {
+ if (!fp) {
lperror(LOG_ERR, "Unable to open file %s", file);
return NULL;
}
@@ -785,6 +868,7 @@ ipmi_start_daemon(struct ipmi_intf *intf)
{
pid_t pid;
int fd;
+ int ret;
#ifdef SIGHUP
sigset_t sighup;
#endif
@@ -828,7 +912,11 @@ ipmi_start_daemon(struct ipmi_intf *intf)
exit(0);
#endif
- chdir("/");
+ ret = chdir("/");
+ if (ret) {
+ lprintf(LOG_ERR, "chdir failed: %s (%d)", strerror(errno), errno);
+ exit(1);
+ }
umask(0);
for (fd=0; fd<64; fd++) {
@@ -837,9 +925,20 @@ ipmi_start_daemon(struct ipmi_intf *intf)
}
fd = open("/dev/null", O_RDWR);
- assert(0 == fd);
- dup(fd);
- dup(fd);
+ if (fd != STDIN_FILENO) {
+ lprintf(LOG_ERR, "failed to reset stdin: %s (%d)", strerror(errno), errno);
+ exit(1);
+ }
+ ret = dup(fd);
+ if (ret != STDOUT_FILENO) {
+ lprintf(LOG_ERR, "failed to reset stdout: %s (%d)", strerror(errno), errno);
+ exit(1);
+ }
+ ret = dup(fd);
+ if (ret != STDERR_FILENO) {
+ lprintf(LOG_ERR, "failed to reset stderr: %s (%d)", strerror(errno), errno);
+ exit(1);
+ }
}
/* eval_ccode - evaluate return value of _ipmi_* functions and print error error
@@ -852,7 +951,7 @@ ipmi_start_daemon(struct ipmi_intf *intf)
int
eval_ccode(const int ccode)
{
- if (ccode == 0) {
+ if (!ccode) {
return 0;
} else if (ccode < 0) {
switch (ccode) {
@@ -1012,11 +1111,11 @@ ipmi_get_oem_id(struct ipmi_intf *intf)
req.msg.data_len = 0;
rsp = intf->sendrecv(intf, &req);
- if (rsp == NULL) {
+ if (!rsp) {
lprintf(LOG_ERR, "Get Board ID command failed");
return 0;
}
- if (rsp->ccode > 0) {
+ if (rsp->ccode) {
lprintf(LOG_ERR, "Get Board ID command failed: %#x %s",
rsp->ccode, val2str(rsp->ccode, completion_code_vals));
return 0;
@@ -1026,3 +1125,35 @@ ipmi_get_oem_id(struct ipmi_intf *intf)
return oem_id;
}
+
+/** Parse command line arguments as numeric byte values (dec or hex)
+ * and store them in a \p len sized buffer \p out.
+ *
+ * @param[in] argc Number of arguments
+ * @param[in] argv Array of arguments
+ * @param[out] out The output buffer
+ * @param[in] len Length of the output buffer in bytes (no null-termination
+ * is assumed, the input data is treated as raw byte values,
+ * not as a string.
+ *
+ * @returns A success status indicator
+ * @return false Error
+ * @return true Success
+ */
+bool
+args2buf(int argc, char *argv[], uint8_t *out, size_t len)
+{
+ size_t i;
+
+ for (i = 0; i < len && i < (size_t)argc; ++i) {
+ uint8_t byte;
+
+ if (str2uchar(argv[i], &byte)) {
+ lprintf(LOG_ERR, "Bad byte value: %s", argv[i]);
+ return false;
+ }
+
+ out[i] = byte;
+ }
+ return true;
+}