mirror of
https://github.com/adulau/ootp.git
synced 2024-11-21 17:47:10 +00:00
611 lines
11 KiB
C
611 lines
11 KiB
C
/*
|
|
* 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 <termios.h>
|
|
#if HAVE_STRINGS_H
|
|
#include <strings.h>
|
|
#endif
|
|
#if HAVE_STRING_H
|
|
#include <string.h>
|
|
#endif
|
|
#include <stdio.h>
|
|
#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<<i)) {
|
|
l = strlen(list[i]);
|
|
if ((l + u + 2) < tmpbuf_size) {
|
|
bcopy(list[i], t, l);
|
|
t += l;
|
|
u += l;
|
|
*t++ = ' ';
|
|
} else {
|
|
goto str_flag8_err;
|
|
}
|
|
} /* if */
|
|
} /* for */
|
|
|
|
/* any strings added then back up over trailing space */
|
|
if (u)
|
|
--t;
|
|
|
|
*t = 0;
|
|
return tmpbuf;
|
|
|
|
str_flag8_err:
|
|
xerr_warnx("str_flag8(): tmpbuf too small.");
|
|
return "";
|
|
|
|
} /* str_flag8 */
|
|
|
|
int str_find8(char *list[], uint8_t *id, char *s, uint8_t min, uint8_t max)
|
|
{
|
|
int i;
|
|
*id = 0;
|
|
|
|
for (i = min; i <= max; ++i) {
|
|
if (!strcasecmp(s, list[i])) {
|
|
*id = i;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
xerr_warnx("str_find8(): %s not found.", s);
|
|
return -1;
|
|
|
|
} /* str_find8 */
|
|
|
|
int str_setflag8(char *list[], uint8_t *flags, char *s, uint8_t min,
|
|
uint8_t max)
|
|
{
|
|
int i;
|
|
|
|
for (i = min; i < max; ++i) {
|
|
if (!strcasecmp(s, list[i]))
|
|
*flags |= 1<<i;
|
|
}
|
|
|
|
if (*flags)
|
|
return 0;
|
|
|
|
xerr_warnx("str_setflag8(): %s not found.", s);
|
|
return -1;
|
|
|
|
} /* str_setflag8 */
|
|
|
|
#ifdef STR_EXAMPLE
|
|
|
|
#include <stdio.h>
|
|
#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 */
|