diff options
Diffstat (limited to 'lib/helper.c')
-rw-r--r-- | lib/helper.c | 221 |
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; +} |