#include #include "string.h" #include "util.h" bool is_special(char c) { //ctype takes an int that must be representable as unsigned char or EOF. Passing a //plain (signed) char hands it a negative value for every byte above 0x7f, which is //undefined - and these protocols carry binary payloads full of them. unsigned char u = (unsigned char)c; return (isspace(u) || u == '\r' || u == '\n'); } char * strip_whitespace(char * cmd) { for (; strlen(cmd) > 0 && is_special(*cmd); cmd++); //a string that is empty, or entirely whitespace, leaves strlen at 0 here and the old //"strlen - 1" wrapped to SIZE_MAX, so the loop read cmd[SIZE_MAX] on its first test. size_t len = strlen(cmd); if (len == 0) { return cmd; } for (size_t idx = len - 1; idx > 0 && is_special(cmd[idx]) ; idx--) { char c = cmd[idx]; if (!isprint(c)) { cmd[idx] = ' '; } if (isspace(c)) { cmd[idx] = ' '; } if (c == '\r' || c == '\n') { cmd[idx] = 0; } } return cmd; } int parse_int(char * str, size_t count) { if (count >= 32) { return 0; } if (0 == str) { return 0; } for (size_t i = 0; i < count && is_special(*str); i++) { str++; } unsigned char tmp[32]; memset(tmp, 0, 32); memcpy(tmp, str, min(count, strlen(str))); return atoi((const char *)tmp); } float parse_float(char * string) { float num = 0, divisor = 10;; char ch; bool neg = false; if (0 == string) { return num; } size_t count = strlen(string); for (size_t i = 0; i < count && is_special(*string); i++) { string++; } if (*string == '-') { neg = true; string++; } while (isdigit((unsigned char)(ch = *string)) && ch != 0) { num = 10 * num + ch - '0'; string++; } //the integer loop above used to consume the byte that stopped it. When that byte was //the terminator the fractional loop started one past the end of the string and read //whatever followed it in memory. if (*string == '.' || *string == ',') { string++; while (isdigit((unsigned char)(ch = *string)) && ch != 0) { num = num + (ch - '0') / divisor; divisor *= 10; string++; } } return neg ? -num : num; } int idx(char * string, char c) { char * e = strchr(string, c); if (e == NULL) { return 0; } return (int)(e - string); } /* * Where c first appears in the first len bytes of buf, or -1 when it does not. * * The framing code used idx(), which answers 0 both for "not there" and for "at the very * start", and searches with strchr - past read_count, through whatever an earlier message * left in the buffer. A frame that was nothing but its terminator ("#" on its own) therefore * looked like no frame at all, was never consumed, and every message behind it waited for * ever. memchr over the bytes actually received, and a distinct answer for "not found". */ long find_byte(const unsigned char * buf, size_t len, unsigned char c) { const unsigned char * at = buf ? memchr(buf, c, len) : NULL; return at ? (long)(at - buf) : -1; } /* * Six hex octets out of a scan entry, in whichever layout the protocol uses ("%x:%x:..." or * "%2x%2x..."). True only when all six converted, each fits a byte, and the address is not * all zeros or all ones - neither of which is an access point. mac is written only then, so * a field that does not parse can never hand the lookup whatever was on the stack. */ bool parse_mac(const char * text, const char * format, unsigned char mac[6]) { unsigned int v[6] = {0}; if (text == 0 || format == 0 || sscanf(text, format, &v[0], &v[1], &v[2], &v[3], &v[4], &v[5]) != 6) { return false; } bool all_zero = true; bool all_ones = true; for (int b = 0; b < 6; b++) { if (v[b] > 0xff) { return false; } all_zero = all_zero && v[b] == 0; all_ones = all_ones && v[b] == 0xff; } if (all_zero || all_ones) { return false; } for (int b = 0; b < 6; b++) { mac[b] = (unsigned char)v[b]; } return true; } void rep(unsigned char * in, unsigned char from, unsigned char with, size_t len) { for (size_t i = 0; i < len; i++)if (in[i] == from) { in[i] = with; } } size_t split_to(unsigned char delim, unsigned char * src, size_t len, unsigned char ** dest, size_t dest_count) { size_t prev_idx = 0; size_t str_count = 0; len = min(len, strlen(src)); for (size_t i = 0; i <= len && str_count < dest_count; i++) { if (src[i] == delim || src[i] == '\0' || i == len) { size_t cur_len = i - prev_idx; dest[str_count] = src + prev_idx; for (; cur_len > 0 && isspace(dest[str_count][0]) && dest[str_count] < (src + len) ;) { dest[str_count]++; cur_len--; } str_count++; if ( src[i] == '\0' || i == len) { return str_count; } prev_idx = i + 1; src[i] = 0; } } return str_count; }