/* * Copyright (c) 2005 Mark Fullmer * Copyright (c) 2009 Mark Fullmer and the Ohio State University * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. * * $Id: str.c 164 2011-05-11 03:57:41Z maf $ */ #include #if HAVE_STRINGS_H #include #endif #if HAVE_STRING_H #include #endif #include #include "str.h" #include "xerr.h" /* * function: chr_hex_l() * * convert ASCII hex left digit to binary * * arguments: * h - 8 bit value to convert * * example, i = 15: * i = chr_hex_r(0xF0) * * returns binary representation of left ASCII hex character h * */ char chr_hex_l(u_char h) { u_char t; t = ((h&0xF0)>>4); if (t > 9) return (t-10) + 'A'; return t + '0'; } /* chr_hex_l */ /* * function: chr_hex_r() * * convert ASCII hex right digit to binary * * example, i = 0: * i = chr_hex_r(0xF0) * * arguments: * h - 8 bit value to convert * * returns binary representation of right ASCII hex character h * */ char chr_hex_r(u_char h) { u_char t; t = (h&0x0F); if (t > 9) return (t-10) + 'A'; return t + '0'; } /* chr_hex_r */ /* * function: chr_hex_decode() * * convert 4 bit ASCII hex to binary * * example, i = 15 * i = chr_hex_decode('F'); * * returns binary representation of ASCII hex character h (0..15) * or 0xFF on error * */ u_char chr_hex_decode(char h) { if ((h >= '0') && (h <= '9')) return h - '0'; if ((h >= 'A') && (h <= 'F')) return h - 'A' + 10; if ((h >= 'a') && (h <= 'f')) return h - 'a' + 10; /* fatal */ return 0xFF; } /* chr_hex_decode */ /* * function: chr_ishex() * * example, i = 0 * i = ishex('F') * example, i = -1 * i = ishex('g') * * returns: * 0 d is ASCII hex character * -1 d is not ASCII hex character * */ int chr_ishex(char d) { if ((d >= '0') && (d <= '9')) return 0; if ((d >= 'A') && (d <= 'F')) return 0; if ((d >= 'a') && (d <= 'f')) return 0; return -1; } /* chr_ishex */ /* * function: str_hex_dump() * * dumps n bytes of b into buf as hex digits * caller is responsible for allocating buf * each input byte translates to two bytes in output buffer + 1 null terminator * * arguments: * buf - output buffer (allocated by caller) * b - bit stream to decode * n - length of b in bytes * */ int str_hex_dump(char *buf, u_char *b, size_t n) { int i, j; for (i = 0, j = 0; i < n; ++i) { buf[j++] = chr_hex_l(*b); buf[j++] = chr_hex_r(*b++); } buf[j] = 0; return j; } /* * function: str_hex_decode() * * decode max of in_len bytes from in as hex, store result in out. * out is out_len bytes * * arguments: * in - null terminated character string to decode. * in_len - max hex digits to decode (may be > strlen(in) * out - decoded bits * out_len - length of out buffer * * returns: <0 error (non hex digit encountered) * 0 successful decode * */ int str_hex_decode(char *in, size_t in_len, u_char *out, size_t out_len) { int i, l; unsigned char v, odd; bzero(out, out_len); l = strlen(in); odd = 0; out += out_len-1; if (l > in_len) return -1; in += l-1; for (i = 0; i < l; ++i) { if (*in >= '0' && *in <= '9') v = *in - '0'; else if (*in >= 'a' && *in <= 'f') v = *in - 'a' + 10; else if (*in >= 'A' && *in <= 'F') v = *in - 'A' + 10; else return -1; if (!odd) { *out |= v; } else { *out |= v<<4; --out; } --in; odd = odd ? 0 : 1; } return 0; } /* str_hex_decode */ /* * function: str_ftoc() * * convert fixed length string to null terminated C string. * a fixed length string may not have terminating null if it * is the max length * * arguments: * buf - null terminated output buffer (allocated by caller, min n+1 bytes) * f - fixed length string * n - max length of f in bytes * */ void str_ftoc(char *buf, char *f, size_t n) { int i; for (i = 0; i < n; ++i) if (!(buf[i] = f[i])) break; buf[i] = 0; } /* str_ftoc */ /* * function: str_input() * * input a string of maximum length buf_size-1 characters from stdin, * null terminate unless input has overflowed. * * * arguments: * prompt - user prompt * buf - input buffer (allocated by caller) * buf_size - size in bytes of input buffer * flags - STR_FLAGS_* * STR_ECHO_OFF - disable echo * * returns: < 0 fatal error * 0 success * -2 not all input read, buffer too short * */ int str_input(const char *prompt, char *buf, size_t buf_size, int flags) { struct termios t; int i, r, ret; char c; ret = -1; /* fail */ /* sanity check */ if (buf_size <= 1) return -1; /* change tty mode? */ if (flags & STR_FLAGS_ECHO_OFF) { if (tcgetattr(STDIN_FILENO, &t) < 0) return -1; t.c_lflag &= ~ECHO; if (tcsetattr(STDIN_FILENO, TCSANOW, &t) < 0) return -1; } printf("%s", prompt); fflush(stdout); i = 0; while (1) { /* get 1 char */ if ((r = read(STDIN_FILENO, &c, 1)) < 0) goto str_input_out; /* EOF? */ if (r == 0) { buf[i] = 0; break; } /* \n */ if (c == '\n') { buf[i] = 0; break; } /* copy input to buf, check overflow */ if ((i+1) == buf_size) { ret = -2; buf[i] = 0; goto str_input_out; } else { buf[i++] = c; } } /* forever */ ret = 0; /* success */ str_input_out: /* restore tty? */ if (flags & STR_FLAGS_ECHO_OFF) { if (tcgetattr(STDIN_FILENO, &t) < 0) return -1; t.c_lflag |= ECHO; if (tcsetattr(STDIN_FILENO, TCSANOW, &t) < 0) return -1; } return ret; } /* str_input */ /* * function: str_safe * * see STR_SAFE_* * */ int str_safe(char *input, size_t input_len_max, char *ok_set, int flags) { size_t n, input_len, ok_len, s; int ret, null_flag, ok_flag; ret = 0; /* success */ null_flag = 0; for (input_len = 0; input_len <= input_len_max; ++input_len) { if (input[input_len] == 0) { null_flag = 1; break; } } if (flags & STR_SAFE_CHECK_LEN) { if (!null_flag) { if (flags & STR_SAFE_WARN) xerr_warnx("%s: size overrun", __func__); if (flags & STR_SAFE_FIX) { input[input_len_max] = 0; input_len = input_len_max; } ret |= STR_SAFE_FAIL_LEN; } } /* STR_SAFE_CHECK_LEN */ if (flags & (STR_SAFE_CHECK_ALPHA|STR_SAFE_CHECK_NUM|STR_SAFE_CHECK_SET)) { for (n = 0; n < input_len; ++n) { if (flags & STR_SAFE_CHECK_ALPHA) { /* a-z */ if ((input[n] >= 'a') && (input[n] <= 'z')) continue; /* A-Z */ if ((input[n] >= 'A') && (input[n] <= 'Z')) continue; } /* STR_SAFE_CHECK_ALPHA */ if (flags & STR_SAFE_CHECK_NUM) { /* 0-9 */ if ((input[n] >= '0') && (input[n] <= '9')) continue; } /* STR_SAFE_CHECK_NUM */ if (flags & STR_SAFE_CHECK_SET) { ok_len = strlen(ok_set); ok_flag = 0; /* bad */ for (s = 0; s < ok_len; ++s) { if (input[n] == ok_set[s]) { ok_flag = 1; /* good */ break; } } /* test char in ok_set */ if (ok_flag) continue; } /* STR_SAFE_CHECK_SET */ ret |= STR_SAFE_FAIL_CHAR; /* unsafe */ if (flags & STR_SAFE_WARN) xerr_warnx("%s: illegal char @ index=%d", __func__, n); if (flags & STR_SAFE_FIX) input[input_len] = '_'; } /* for each byte in input */ } /* STR_SAFE_CHECK_FNAME */ return ret; } /* str_safe */ /* * function: str_uint32toa() * * convert unsigned 32 bit integer to ascii. Left align. * * arguments: * s - pointer to output buffer. Must be at least 11 bytes. * u - uint32_t to convert * * returns: length of string * */ int str_uint32toa(char *s, uint32_t u) { int len; char *s1; len = 0; s1 = s; /* 2^32-1 = 4294967295 = max 10 digits + NULL */ s[10] = 0; do { ++len; *--s = '0' + (u % 10); u /= 10; } while (u); bcopy(s, s1, len); s1[len] = 0; return len; } /* str_fmt_uint32 */ char *str_lookup8(char *list[], uint8_t id, uint8_t min, uint8_t max) { if (id > max) { xerr_warnx("str_lookup8(): id=%d, max=%d", (int)id, (int)max); return "err"; } if (id < min) { xerr_warnx("str_lookup8(): id=%d, min=%d", (int)id, (int)min); return "err"; } return list[id]; } /* str_lookup8 */ char *str_flag8(char *list[], uint8_t flags, uint8_t bits, char *tmpbuf, size_t tmpbuf_size) { int i, l, u; char *t; u = 0; t = tmpbuf; for (i = 0; i < bits; ++i) { if (flags & (1< #include "str.h" main() { char buf[1024]; unsigned char b[4]; int i; i = str_input("prompt: ", buf, 2, STR_FLAGS_ECHO_OFF); printf("i=%d\n", i); printf("buf=%s\n", buf); b[0] = 0x1A; b[1] = 0x2B; b[2] = 0x3C; b[3] = 0x4D; str_hex_dump(buf, b, 4); printf("%s\n", buf); b[0] = 'A'; b[1] = 'B'; b[2] = 0; str_ftoc(buf, b, 4); printf("%s\n", buf); b[0] = 'A'; b[1] = 'B'; b[2] = 'C'; b[3] = 'D'; str_ftoc(buf, b, 4); printf("%s\n", buf); } #endif /* STR_EXAMPLE */