X-Git-Url: http://git.pk910.de/?a=blobdiff_plain;f=src%2Ftools.c;h=b10bc7be4379b5b573008142c58bb539ffe9c9c3;hb=80d9ed728be4b02ac483f3339cbb184f6602d15b;hp=502668435a1969d5b316c02c0af6c0af9fb7f400;hpb=222e1b0003536cf7b47858961d4b56d45c6d6606;p=srvx.git diff --git a/src/tools.c b/src/tools.c index 5026684..b10bc7b 100644 --- a/src/tools.c +++ b/src/tools.c @@ -1,11 +1,12 @@ /* tools.c - miscellaneous utility functions * Copyright 2000-2004 srvx Development Team * - * This program is free software; you can redistribute it and/or modify + * This file is part of srvx. + * + * srvx is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. Important limitations are - * listed in the COPYING file that accompanies this software. + * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -13,9 +14,11 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, email srvx-maintainers@srvx.net. + * along with srvx; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ +#include "helpfile.h" #include "log.h" #include "nickserv.h" #include "recdb.h" @@ -47,13 +50,23 @@ static const unsigned char convert2n[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 52,53,54,55,56,57,58,59,60,61, 0, 0, 0, 0, 0, 0, + 52,53,54,55,56,57,58,59,60,61, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14, 15,16,17,18,19,20,21,22,23,24,25,62, 0,63, 0, 0, 0,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40, 41,42,43,44,45,46,47,48,49,50,51, 0, 0, 0, 0, 0 }; +static const unsigned char ctype[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, + 0,10,11,12,13,14,15, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0,10,11,12,13,14,15, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + unsigned long int base64toint(const char* s, int count) { @@ -75,6 +88,273 @@ const char* inttobase64(char* buf, unsigned int v, unsigned int count) return buf; } +unsigned int +irc_ntop(char *output, unsigned int out_size, const irc_in_addr_t *addr) +{ + static const char hexdigits[] = "0123456789abcdef"; + unsigned int pos; + + assert(output); + assert(addr); + + if (irc_in_addr_is_ipv4(*addr)) { + unsigned int ip4; + + ip4 = (ntohs(addr->in6[6]) << 16) | ntohs(addr->in6[7]); + pos = snprintf(output, out_size, "%u.%u.%u.%u", (ip4 >> 24), (ip4 >> 16) & 255, (ip4 >> 8) & 255, ip4 & 255); + } else { + unsigned int part, max_start, max_zeros, curr_zeros, ii; + + /* Find longest run of zeros. */ + for (max_start = max_zeros = curr_zeros = ii = 0; ii < 8; ++ii) { + if (!addr->in6[ii]) + curr_zeros++; + else if (curr_zeros > max_zeros) { + max_start = ii - curr_zeros; + max_zeros = curr_zeros; + curr_zeros = 0; + } + } + if (curr_zeros > max_zeros) { + max_start = ii - curr_zeros; + max_zeros = curr_zeros; + } + + /* Print out address. */ +#define APPEND(CH) do { if (pos < out_size) output[pos] = (CH); pos++; } while (0) + for (pos = 0, ii = 0; ii < 8; ++ii) { + if ((max_zeros > 0) && (ii == max_start)) { + if (ii == 0) + APPEND(':'); + APPEND(':'); + ii += max_zeros - 1; + continue; + } + part = ntohs(addr->in6[ii]); + if (part >= 0x1000) + APPEND(hexdigits[part >> 12]); + if (part >= 0x100) + APPEND(hexdigits[(part >> 8) & 15]); + if (part >= 0x10) + APPEND(hexdigits[(part >> 4) & 15]); + APPEND(hexdigits[part & 15]); + if (ii < 7) + APPEND(':'); + } +#undef APPEND + output[pos < out_size ? pos : out_size - 1] = '\0'; + } + + return pos; +} + +unsigned int +irc_ntop_mask(char *output, unsigned int out_size, const irc_in_addr_t *addr, unsigned char bits) +{ + char base_addr[IRC_NTOP_MAX_SIZE]; + int len; + + if (bits >= 128) + return irc_ntop(output, out_size, addr); + if (!irc_ntop(base_addr, sizeof(base_addr), addr)) + return 0; + len = snprintf(output, out_size, "%s/%d", base_addr, bits); + if ((unsigned int)len >= out_size) + return 0; + return len; +} + +static unsigned int +irc_pton_ip4(const char *input, unsigned char *pbits, uint32_t *output) +{ + unsigned int dots = 0, pos = 0, part = 0, ip = 0, bits = 32; + + /* Intentionally no support for bizarre IPv4 formats (plain + * integers, octal or hex components) -- only vanilla dotted + * decimal quads, optionally with trailing /nn. + */ + if (input[0] == '.') + return 0; + while (1) switch (input[pos]) { + default: + if (dots < 3) + return 0; + out: + ip |= part << (24 - 8 * dots++); + *output = htonl(ip); + if (pbits) + *pbits = bits; + return pos; + case '.': + if (input[++pos] == '.') + return 0; + ip |= part << (24 - 8 * dots++); + part = 0; + if (input[pos] == '*') { + while (input[++pos] == '*') ; + if (input[pos] != '\0') + return 0; + if (pbits) + *pbits = dots * 8; + *output = htonl(ip); + return pos; + } + break; + case '/': + if (!pbits || !isdigit(input[pos + 1])) + return 0; + for (bits = 0; isdigit(input[++pos]); ) + bits = bits * 10 + input[pos] - '0'; + if (bits > 32) + return 0; + goto out; + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + part = part * 10 + input[pos++] - '0'; + if (part > 255) + return 0; + break; + } +} + +unsigned int +irc_pton(irc_in_addr_t *addr, unsigned char *bits, const char *input) +{ + const char *part_start = NULL; + char *colon; + char *dot; + unsigned int part = 0, pos = 0, ii = 0, cpos = 8; + + assert(input); + memset(addr, 0, sizeof(*addr)); + colon = strchr(input, ':'); + dot = strchr(input, '.'); + + if (colon && (!dot || (dot > colon))) { + /* Parse IPv6, possibly like ::127.0.0.1. + * This is pretty straightforward; the only trick is borrowed + * from Paul Vixie (BIND): when it sees a "::" continue as if + * it were a single ":", but note where it happened, and fill + * with zeros afterwards. + */ + if (input[pos] == ':') { + if ((input[pos+1] != ':') || (input[pos+2] == ':')) + return 0; + cpos = 0; + pos += 2; + part_start = input + pos; + } + while (ii < 8) switch (input[pos]) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + part = (part << 4) | (ctype[(unsigned char)input[pos++]] & 15); + if (part > 0xffff) + return 0; + break; + case ':': + part_start = input + ++pos; + if (input[pos] == '.') + return 0; + addr->in6[ii++] = htons(part); + part = 0; + if (input[pos] == ':') { + if (cpos < 8) + return 0; + cpos = ii; + } + break; + case '.': { + uint32_t ip4; + unsigned int len; + len = irc_pton_ip4(part_start, bits, &ip4); + if (!len || (ii > 6)) + return 0; + memcpy(addr->in6 + ii, &ip4, sizeof(ip4)); + if (bits) + *bits += 96; + ii += 2; + pos = part_start + len - input; + goto finish; + } + case '/': + if (!bits || !isdigit(input[pos + 1])) + return 0; + addr->in6[ii++] = htons(part); + for (part = 0; isdigit(input[++pos]); ) + part = part * 10 + input[pos] - '0'; + if (part > 128) + return 0; + *bits = part; + goto finish; + case '*': + while (input[++pos] == '*') ; + if (input[pos] != '\0' || cpos < 8) + return 0; + if (bits) + *bits = ii * 16; + return pos; + default: + addr->in6[ii++] = htons(part); + if (cpos == 8 && ii < 8) + return 0; + if (bits) + *bits = 128; + goto finish; + } + finish: + /* Shift stuff after "::" up and fill middle with zeros. */ + if (cpos < 8) { + unsigned int jj; + for (jj = 0; jj < ii - cpos; jj++) + addr->in6[7 - jj] = addr->in6[ii - jj - 1]; + for (jj = 0; jj < 8 - ii; jj++) + addr->in6[cpos + jj] = 0; + } + } else if (dot) { + uint32_t ip4; + pos = irc_pton_ip4(input, bits, &ip4); + if (pos) { +/* glibc's htons() macro is not -Wshadow-safe. */ +#undef htons + addr->in6[5] = htons(65535); + addr->in6[6] = htons(ntohl(ip4) >> 16); + addr->in6[7] = htons(ntohl(ip4) & 65535); + if (bits) + *bits += 96; + } + } else if (input[0] == '*') { + while (input[++pos] == '*') ; + if (input[pos] != '\0') + return 0; + if (bits) + *bits = 0; + } + return pos; +} + +const char *irc_ntoa(const irc_in_addr_t *addr) +{ + static char ntoa[IRC_NTOP_MAX_SIZE]; + irc_ntop(ntoa, sizeof(ntoa), addr); + return ntoa; +} + +unsigned int +irc_check_mask(const irc_in_addr_t *check, const irc_in_addr_t *mask, unsigned char bits) +{ + unsigned int ii; + + for (ii = 0; (ii < 8) && (bits > 16); bits -= 16, ++ii) + if (check->in6[ii] != mask->in6[ii]) + return 0; + if (ii < 8 && bits > 0 + && (ntohs(check->in6[ii] ^ mask->in6[ii]) >> (16 - bits))) + return 0; + return 1; +} + static char irc_tolower[256]; #undef tolower #define tolower(X) irc_tolower[(unsigned char)(X)] @@ -107,31 +387,40 @@ irccasestr(const char *haystack, const char *needle) { return NULL; } +char * +ircstrlower(char *str) { + size_t ii; + for (ii = 0; str[ii] != '\0'; ++ii) + str[ii] = tolower(str[ii]); + return str; +} + int split_line(char *line, int irc_colon, int argv_size, char *argv[]) { int argc = 0; int n; while (*line && (argc < argv_size)) { - while (*line == ' ') *line++ = 0; - if (*line == ':' && irc_colon && argc > 0) { - /* the rest is a single parameter */ - argv[argc++] = line + 1; - break; - } + while (*line == ' ') + *line++ = 0; + if (*line == ':' && irc_colon && argc > 0) { + /* the rest is a single parameter */ + argv[argc++] = line + 1; + break; + } if (!*line) break; - argv[argc++] = line; - if (argc >= argv_size) + argv[argc++] = line; + if (argc >= argv_size) break; - while (*line != ' ' && *line) line++; + while (*line != ' ' && *line) + line++; } #ifdef NDEBUG n = 0; #else - for (n=argc; n old_mask) && (*m == '?'); m--) - ; + ; if ((*m == '*') && (m > old_mask) && (m[-1] != '\\')) - return 0; + return 0; if (!wild) - return 1; + return 1; m = ma; /* Added to `mmatch' : Because '\?' and '\*' now is one character: */ if ((*na == '\\') && ((na[1] == '*') || (na[1] == '?'))) - ++na; + ++na; n = ++na; } else if (!*n) { while (*m == '*') - m++; + m++; return (*m != 0); } if ((*m == '\\') && ((m[1] == '*') || (m[1] == '?'))) @@ -215,23 +504,23 @@ int mmatch(const char *old_mask, const char *new_mask) * cases upfront (which took 2 hours!)). */ if ((*m == '*' && !mq) || - ((!mq || nq) && tolower(*m) == tolower(*n)) || - (*m == '?' && !mq && (*n != '*' || nq))) + ((!mq || nq) && tolower(*m) == tolower(*n)) || + (*m == '?' && !mq && (*n != '*' || nq))) { if (*m) - m++; + m++; if (*n) - n++; + n++; } else { if (!wild) - return 1; + return 1; m = ma; /* Added to `mmatch' : Because '\?' and '\*' now is one character: */ if ((*na == '\\') && ((na[1] == '*') || (na[1] == '?'))) - ++na; + ++na; n = ++na; } @@ -241,68 +530,78 @@ int mmatch(const char *old_mask, const char *new_mask) int match_ircglob(const char *text, const char *glob) { - unsigned int star_p, q_cnt; - while (1) { - switch (*glob) { - case 0: - return !*text; - case '\\': - glob++; - /* intentionally not tolower(...) so people can force - * capitalization, or we can overload \ in the future */ - if (*text++ != *glob++) return 0; - break; - case '*': - case '?': - star_p = q_cnt = 0; - do { - if (*glob == '*') star_p = 1; - else if (*glob == '?') q_cnt++; - else break; - glob++; - } while (1); - while (q_cnt) { if (!*text++) return 0; q_cnt--; } - if (star_p) { - /* if this is the last glob character, it will match any text */ - if (!*glob) return 1; - /* Thanks to the loop above, we know that the next - * character is a normal character. So just look for - * the right character. - */ - for (; *text; text++) { - if ((tolower(*text) == tolower(*glob)) - && match_ircglob(text+1, glob+1)) { - return 1; - } - } - return 0; + const char *m = glob, *n = text; + const char *m_tmp = glob, *n_tmp = text; + int star_p; + + for (;;) switch (*m) { + case '\0': + if (!*n) + return 1; + backtrack: + if (m_tmp == glob) + return 0; + m = m_tmp; + n = ++n_tmp; + if (!*n) + return 0; + break; + case '\\': + m++; + /* allow escaping to force capitalization */ + if (*m++ != *n++) + goto backtrack; + break; + case '*': case '?': + for (star_p = 0; ; m++) { + if (*m == '*') + star_p = 1; + else if (*m == '?') { + if (!*n++) + goto backtrack; + } else break; + } + if (star_p) { + if (!*m) + return 1; + else if (*m == '\\') { + m_tmp = ++m; + if (!*m) + return 0; + for (n_tmp = n; *n && *n != *m; n++) ; + } else { + m_tmp = m; + for (n_tmp = n; *n && tolower(*n) != tolower(*m); n++) ; } - /* if !star_p, fall through to normal character case, - * first checking to see if ?s carried us to the end */ - if (!*glob && !*text) return 1; - default: - if (!*text) return 0; - while (*text && *glob && *glob != '*' && *glob != '?' && *glob != '\\') { - if (tolower(*text++) != tolower(*glob++)) return 0; - } - } + } + /* and fall through */ + default: + if (!*n) + return *m == '\0'; + if (tolower(*m) != tolower(*n)) + goto backtrack; + m++; + n++; + break; } } extern const char *hidden_host_suffix; int -user_matches_glob(struct userNode *user, const char *orig_glob, int include_nick) +user_matches_glob(struct userNode *user, const char *orig_glob, int flags) { + irc_in_addr_t mask; char *glob, *marker; + unsigned char mask_bits; /* Make a writable copy of the glob */ glob = alloca(strlen(orig_glob)+1); strcpy(glob, orig_glob); /* Check the nick, if it's present */ - if (include_nick) { + if (flags & MATCH_USENICK) { if (!(marker = strchr(glob, '!'))) { - log_module(MAIN_LOG, LOG_ERROR, "user_matches_glob(\"%s\", \"%s\", %d) called, and glob doesn't include a '!'", user->nick, orig_glob, include_nick); + log_module(MAIN_LOG, LOG_ERROR, "user_matches_glob(\"%s\", \"%s\", %d) called, and glob doesn't include a '!'", user->nick, orig_glob, flags); return 0; } *marker = 0; @@ -311,48 +610,64 @@ user_matches_glob(struct userNode *user, const char *orig_glob, int include_nick } /* Check the ident */ if (!(marker = strchr(glob, '@'))) { - log_module(MAIN_LOG, LOG_ERROR, "user_matches_glob(\"%s\", \"%s\", %d) called, and glob doesn't include an '@'", user->nick, orig_glob, include_nick); + log_module(MAIN_LOG, LOG_ERROR, "user_matches_glob(\"%s\", \"%s\", %d) called, and glob doesn't include an '@'", user->nick, orig_glob, flags); return 0; } *marker = 0; - if (!match_ircglob(user->ident, glob)) + if (((IsFakeIdent(user) && IsHiddenHost(user) && (flags & MATCH_VISIBLE)) || !match_ircglob(user->ident, glob)) && + !(IsFakeIdent(user) && match_ircglob(user->fakeident, glob))) return 0; glob = marker + 1; - /* Now check the host part */ - if (isdigit(*glob) && !glob[strspn(glob, "0123456789./*?")]) { - /* Looks like an IP-based mask */ - return match_ircglob(inet_ntoa(user->ip), glob); - } else { - /* The host part of the mask isn't IP-based */ - if (hidden_host_suffix && user->handle_info) { - char hidden_host[HOSTLEN+1]; - snprintf(hidden_host, sizeof(hidden_host), "%s.%s", user->handle_info->handle, hidden_host_suffix); - if (match_ircglob(hidden_host, glob)) - return 1; - } - return match_ircglob(user->hostname, glob); + /* Check for a fakehost match. */ + if (IsFakeHost(user) && match_ircglob(user->fakehost, glob)) + return 1; + /* Check for an account match. */ + if (hidden_host_suffix && user->handle_info) { + char hidden_host[HOSTLEN+1]; + snprintf(hidden_host, sizeof(hidden_host), "%s.%s", user->handle_info->handle, hidden_host_suffix); + if (match_ircglob(hidden_host, glob)) + return 1; } + /* If only matching the visible hostnames, bail early. */ + if ((flags & MATCH_VISIBLE) && IsHiddenHost(user) + && (IsFakeHost(user) || (hidden_host_suffix && user->handle_info))) + return 0; + /* If it might be an IP glob, test that. */ + if (irc_pton(&mask, &mask_bits, glob) + && irc_check_mask(&user->ip, &mask, mask_bits)) + return 1; + /* None of the above; could only be a hostname match. */ + return match_ircglob(user->hostname, glob); } int is_ircmask(const char *text) { - while (*text && (isalnum((char)*text) || strchr("-_[]|\\`^{}?*", *text))) text++; - if (*text++ != '!') return 0; - while (*text && *text != '@' && !isspace((char)*text)) text++; - if (*text++ != '@') return 0; - while (*text && !isspace((char)*text)) text++; + while (*text && (isalnum((char)*text) || strchr("-_[]|\\`^{}?*", *text))) + text++; + if (*text++ != '!') + return 0; + while (*text && *text != '@' && !isspace((char)*text)) + text++; + if (*text++ != '@') + return 0; + while (*text && !isspace((char)*text)) + text++; return !*text; } int is_gline(const char *text) { - if (*text == '@') return 0; + if (*text == '@') + return 0; text += strcspn(text, "@!% \t\r\n"); - if (*text++ != '@') return 0; - if (!*text) return 0; - while (*text && (isalnum((char)*text) || strchr(".-?*", *text))) text++; + if (*text++ != '@') + return 0; + if (!*text) + return 0; + while (*text && (isalnum((char)*text) || strchr(".-?*:", *text))) + text++; return !*text; } @@ -362,20 +677,28 @@ split_ircmask(char *text, char **nick, char **ident, char **host) char *start; start = text; - while (isalnum((char)*text) || strchr("=[]\\`^{}?*", *text)) text++; - if (*text != '!' || ((text - start) > NICKLEN)) return 0; + while (isalnum((char)*text) || strchr("=[]\\`^{}?*", *text)) + text++; + if (*text != '!' || ((text - start) > NICKLEN)) + return 0; *text = 0; - if (nick) *nick = start; + if (nick) + *nick = start; start = ++text; - while (*text && *text != '@' && !isspace((char)*text)) text++; - if (*text != '@' || ((text - start) > USERLEN)) return 0; + while (*text && *text != '@' && !isspace((char)*text)) + text++; + if (*text != '@' || ((text - start) > USERLEN)) + return 0; *text = 0; - if (ident) *ident = start; - + if (ident) + *ident = start; + start = ++text; - while (*text && (isalnum((char)*text) || strchr(".-?*", *text))) text++; - if (host) *host = start; + while (*text && (isalnum((char)*text) || strchr(".-?*:", *text))) + text++; + if (host) + *host = start; return !*text && ((text - start) <= HOSTLEN) && nick && ident && host; } @@ -395,20 +718,20 @@ sanitize_ircmask(char *input) mask = input; while(*input++ != '!') { - length++; + length++; } if(length > NICKLEN) { - mask += NICKLEN; - *mask++ = '!'; + mask += NICKLEN; + *mask++ = '!'; - /* This flag is used to indicate following parts should - be shifted. */ - flag = 1; + /* This flag is used to indicate following parts should + be shifted. */ + flag = 1; } else { - mask = input; + mask = input; } /* The ident and host must be truncated at the beginning and @@ -417,46 +740,46 @@ sanitize_ircmask(char *input) start = input; while(*input++ != '@') { - length++; + length++; } if(length > USERLEN || flag) { - if(length > USERLEN) - { - start = input - USERLEN; - *mask++ = '*'; - } - while(*start != '@') - { - *mask++ = *start++; - } - *mask++ = '@'; - - flag = 1; + if(length > USERLEN) + { + start = input - USERLEN; + *mask++ = '*'; + } + while(*start != '@') + { + *mask++ = *start++; + } + *mask++ = '@'; + + flag = 1; } else { - mask = input; + mask = input; } length = 0; start = input; while(*input++) { - length++; + length++; } if(length > HOSTLEN || flag) { - if(length > HOSTLEN) - { - start = input - HOSTLEN; - *mask++ = '*'; - } - while(*start) - { - *mask++ = *start++; - } - *mask = '\0'; + if(length > HOSTLEN) + { + start = input - HOSTLEN; + *mask++ = '*'; + } + while(*start) + { + *mask++ = *start++; + } + *mask = '\0'; } return output; @@ -486,12 +809,14 @@ ParseInterval(const char *interval) /* process the string, resetting the count if we find a unit character */ while ((c = *interval++)) { - if (isdigit((int)c)) { - partial = partial*10 + c - '0'; - } else { - seconds += TypeLength(c) * partial; - partial = 0; - } + if (isdigit((int)c)) { + partial = partial*10 + c - '0'; + } else if (strchr("yMwdhms", c)) { + seconds += TypeLength(c) * partial; + partial = 0; + } else { + return 0; + } } /* assume the last chunk is seconds (the normal case) */ return seconds + partial; @@ -525,79 +850,17 @@ ParseVolume(const char *volume) return accum + partial; } -int -parse_ipmask(const char *str, struct in_addr *addr, unsigned long *mask) -{ - int accum, pos; - unsigned long t_a, t_m; - - t_a = t_m = pos = 0; - if (addr) addr->s_addr = htonl(t_a); - if (mask) *mask = t_m; - while (*str) { - if (!isdigit(*str)) return 0; - accum = 0; - do { - accum = (accum * 10) + *str++ - '0'; - } while (isdigit(*str)); - if (accum > 255) return 0; - t_a = (t_a << 8) | accum; - t_m = (t_m << 8) | 255; - pos += 8; - if (*str == '.') { - str++; - while (*str == '*') { - str++; - if (*str == '.') { - t_a <<= 8; - t_m <<= 8; - pos += 8; - str++; - } else if (*str == 0) { - t_a <<= 32 - pos; - t_m <<= 32 - pos; - pos = 32; - goto out; - } else { - return 0; - } - } - } else if (*str == '/') { - int start = pos; - accum = 0; - do { - accum = (accum * 10) + *str++ - '0'; - } while (isdigit(*str)); - while (pos < start+accum && pos < 32) { - t_a = (t_a << 1) | 0; - t_m = (t_m << 1) | 1; - pos++; - } - if (pos != start+accum) return 0; - } else if (*str == 0) { - break; - } else { - return 0; - } - } -out: - if (pos != 32) return 0; - if (addr) addr->s_addr = htonl(t_a); - if (mask) *mask = t_m; - return 1; -} - char * unsplit_string(char *set[], unsigned int max, char *dest) { static char unsplit_buffer[MAXLEN*2]; unsigned int ii, jj, pos; - if (!dest) dest = unsplit_buffer; + if (!dest) + dest = unsplit_buffer; for (ii=pos=0; iilanguage : lang_C; if(!interval) { - strcpy(output, brief ? "0s" : "0 seconds"); - return output; + msg = language_find_message(lang, "MSG_0_SECONDS"); + return strcpy(output, msg); } for (type = 0, words = pos = 0; interval && (words < 2) && (type < ArrayLength(unit)); type++) { - if (interval < unit[type].length) + if (interval < unit[type].length) continue; count = interval / unit[type].length; interval = interval % unit[type].length; - if (brief) - pos += sprintf(output + pos, "%d%c", count, unit[type].name[0]); - else if (words == 1) - pos += sprintf(output + pos, " and %d %s", count, unit[type].name); + if (words++ == 1) { + msg = language_find_message(lang, "MSG_AND"); + pos += sprintf(output + pos, " %s ", msg); + } + if (count == 1) + msg = language_find_message(lang, unit[type].msg_single); else - pos += sprintf(output + pos, "%d %s", count, unit[type].name); - if (count != 1) - output[pos++] = 's'; - words++; + msg = language_find_message(lang, unit[type].msg_plural); + pos += sprintf(output + pos, "%d %s", count, msg); } output[pos] = 0; @@ -653,14 +920,12 @@ int getipbyname(const char *name, unsigned long *ip) { struct hostent *he = gethostbyname(name); - if (he) { - if (he->h_addrtype != AF_INET) - return 0; - memcpy(ip, he->h_addr_list[0], sizeof(*ip)); - return 1; - } else { - return 0; - } + if (!he) + return 0; + if (he->h_addrtype != AF_INET) + return 0; + memcpy(ip, he->h_addr_list[0], sizeof(*ip)); + return 1; } DEFINE_LIST(string_buffer, char) @@ -703,7 +968,7 @@ string_buffer_append_vprintf(struct string_buffer *buf, const char *fmt, va_list /* pre-C99 behavior; double buffer size until it is big enough */ va_end(working); VA_COPY(working, args); - while ((ret = vsnprintf(buf->list + buf->used, buf->size, fmt, working)) == -1) { + while ((ret = vsnprintf(buf->list + buf->used, buf->size - buf->used, fmt, working)) <= 0) { buf->size += len; buf->list = realloc(buf->list, buf->size); va_end(working); @@ -738,13 +1003,14 @@ void string_buffer_replace(struct string_buffer *buf, unsigned int from, unsigned int len, const char *repl) { unsigned int repl_len = strlen(repl); - if (from > buf->used) return; - if (len + from > buf->used) len = buf->used - from; + if (from > buf->used) + return; + if (len + from > buf->used) + len = buf->used - from; buf->used = buf->used + repl_len - len; if (buf->size <= buf->used) { - while (buf->used >= buf->size) { + while (buf->used >= buf->size) buf->size <<= 1; - } buf->list = realloc(buf->list, buf->size*sizeof(buf->list[0])); } memmove(buf->list+from+repl_len, buf->list+from+len, strlen(buf->list+from+len)); @@ -755,10 +1021,12 @@ struct string_list str_tab; const char * strtab(unsigned int ii) { - if (ii > 65536) return NULL; + if (ii > 65536) + return NULL; if (ii > str_tab.size) { unsigned int old_size = str_tab.size; - while (ii >= str_tab.size) str_tab.size <<= 1; + while (ii >= str_tab.size) + str_tab.size <<= 1; str_tab.list = realloc(str_tab.list, str_tab.size*sizeof(str_tab.list[0])); memset(str_tab.list+old_size, 0, (str_tab.size-old_size)*sizeof(str_tab.list[0])); } @@ -773,12 +1041,17 @@ void tools_init(void) { unsigned int upr, lwr; - for (lwr=0; lwr<256; ++lwr) tolower(lwr) = lwr; - for (upr='A', lwr='a'; lwr <= 'z'; ++upr, ++lwr) tolower(upr) = lwr; + for (lwr=0; lwr<256; ++lwr) + tolower(lwr) = lwr; + for (upr='A', lwr='a'; lwr <= 'z'; ++upr, ++lwr) + tolower(upr) = lwr; #ifdef WITH_PROTOCOL_P10 - for (upr='[', lwr='{'; lwr <= '~'; ++upr, ++lwr) tolower(upr) = lwr; - for (upr=0xc0, lwr=0xe0; lwr <= 0xf6; ++upr, ++lwr) tolower(upr) = lwr; - for (upr=0xd8, lwr=0xf8; lwr <= 0xfe; ++upr, ++lwr) tolower(upr) = lwr; + for (upr='[', lwr='{'; lwr <= '~'; ++upr, ++lwr) + tolower(upr) = lwr; + for (upr=0xc0, lwr=0xe0; lwr <= 0xf6; ++upr, ++lwr) + tolower(upr) = lwr; + for (upr=0xd8, lwr=0xf8; lwr <= 0xfe; ++upr, ++lwr) + tolower(upr) = lwr; #endif str_tab.size = 1001; str_tab.list = calloc(str_tab.size, sizeof(str_tab.list[0])); @@ -788,8 +1061,7 @@ void tools_cleanup(void) { unsigned int ii; - for (ii=0; ii