2 * IRC - Internet Relay Chat, ircd/ircd_string.c
3 * Copyright (C) 1999 Thomas Helvey
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 1, or (at your option)
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "ircd_string.h"
24 #include "ircd_defs.h"
25 #include "ircd_chattr.h"
31 * include the character attribute tables here
33 #include "chattr.tab.c"
37 * Disallow a hostname label to contain anything but a [-a-zA-Z0-9].
38 * It may not start or end on a '.'.
39 * A label may not end on a '-', the maximum length of a label is
41 * On top of that (which seems to be the RFC) we demand that the
42 * top domain does not contain any digits.
44 static const char* hostExpr = "^([-0-9A-Za-z]*[0-9A-Za-z]\\.)+[A-Za-z]+$";
45 static regex_t hostRegex;
47 static const char* addrExpr =
48 "^((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\\.){1,3}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])$";
49 static regex_t addrRegex;
54 * initialize matching expressions
55 * XXX - expressions MUST be correct, don't change expressions
56 * without testing them. Might be a good idea to exit if these fail,
57 * important code depends on them.
58 * TODO: use regerror for an error message
60 if (regcomp(&hostRegex, hostExpr, REG_EXTENDED | REG_NOSUB))
63 if (regcomp(&addrRegex, addrExpr, REG_EXTENDED | REG_NOSUB))
68 int string_is_hostname(const char* str)
71 return (strlen(str) <= HOSTLEN && 0 == regexec(&hostRegex, str, 0, 0, 0));
74 int string_is_address(const char* str)
77 return (0 == regexec(&addrRegex, str, 0, 0, 0));
80 int string_has_wildcards(const char* str)
83 for ( ; *str; ++str) {
88 else if ('*' == *str || '?' == *str)
97 * Walk through a string of tokens, using a set of separators.
100 char* ircd_strtok(char **save, char *str, char *fs)
102 char *pos = *save; /* keep last position across calls */
106 pos = str; /* new string scan */
108 while (pos && *pos && strchr(fs, *pos) != NULL)
109 pos++; /* skip leading separators */
112 return (pos = *save = NULL); /* string contains only sep's */
114 tmp = pos; /* now, keep position of the token */
116 while (*pos && strchr(fs, *pos) == NULL)
117 pos++; /* skip content of the token */
120 *pos++ = '\0'; /* remove first sep after the token */
122 pos = NULL; /* end of string */
131 * reduce a string of duplicate list entries to contain only the unique
132 * items. Unavoidably O(n^2).
134 char* canonize(char* buffer)
136 static char cbuf[BUFSIZE];
146 for (s = ircd_strtok(&p, buffer, ","); s; s = ircd_strtok(&p, NULL, ","))
151 for (t = ircd_strtok(&p2, cbuf, ","); t; t = ircd_strtok(&p2, NULL, ","))
152 if (0 == ircd_strcmp(s, t))
176 * ircd_strncpy - optimized strncpy
177 * This may not look like it would be the fastest possible way to do it,
178 * but it generally outperforms everything else on many platforms,
179 * including asm library versions and memcpy, if compiled with the
180 * optimizer on. (-O2 for gcc) --Bleep
182 char* ircd_strncpy(char* s1, const char* s2, size_t n)
190 while (s < endp && (*s++ = *s2++))
197 NTL_HDR_strChattr { NTL_SRC_strChattr }
198 NTL_HDR_strCasediff { NTL_SRC_strCasediff }
199 #endif /* !FORCEINLINE */
202 * Other functions visible externally
205 int strnChattr(const char *s, size_t n)
211 x &= IRCD_CharAttrTab[*rs++ - CHAR_MIN];
216 * ircd_strcmp - case insensitive comparison of 2 strings
217 * NOTE: see ircd_chattr.h for notes on case mapping.
219 int ircd_strcmp(const char *a, const char *b)
223 while (ToLower(*ra) == ToLower(*rb)) {
233 * ircd_strncmp - counted case insensitive comparison of 2 strings
234 * NOTE: see ircd_chattr.h for notes on case mapping.
236 int ircd_strncmp(const char *a, const char *b, size_t n)
243 while (ToLower(*ra) == ToLower(*rb)) {
244 if (!*ra++ || !left--)
253 * unique_name_vector - create a unique vector of names from
254 * a token separated list
255 * list - [in] a token delimited null terminated character array
256 * token - [in] the token to replace
257 * vector - [out] vector of strings to be returned
258 * size - [in] maximum number of elements to place in vector
259 * Returns count of elements placed into the vector, if the list
260 * is an empty string { '\0' } 0 is returned.
261 * list, and vector must be non-null and size must be > 0
262 * Empty strings <token><token> are not placed in the vector or counted.
263 * This function ignores all subsequent tokens when count == size
265 * NOTE: this function destroys it's input, do not use list after it
266 * is passed to this function
268 int unique_name_vector(char* list, char token, char** vector, int size)
280 * ignore spurious tokens
282 while (token == *start)
285 for (end = strchr(start, token); end; end = strchr(start, token)) {
288 * ignore spurious tokens
290 while (token == *end)
292 for (i = 0; i < count; ++i) {
293 if (0 == ircd_strcmp(vector[i], start))
297 vector[count++] = start;
304 for (i = 0; i < count; ++i)
305 if (0 == ircd_strcmp(vector[i], start))
307 vector[count++] = start;
313 * token_vector - create a vector of tokens from
314 * a token separated list
315 * list - [in] a token delimited null terminated character array
316 * token - [in] the token to replace
317 * vector - [out] vector of strings to be returned
318 * size - [in] maximum number of elements to place in vector
319 * returns count of elements placed into the vector, if the list
320 * is an empty string { '\0' } 0 is returned.
321 * list, and vector must be non-null and size must be > 1
322 * Empty tokens are counted and placed in the list
324 * NOTE: this function destroys it's input, do not use list after it
325 * is passed to this function
327 int token_vector(char* list, char token, char** vector, int size)
337 vector[count++] = start;
338 for (end = strchr(start, token); end; end = strchr(start, token)) {
342 vector[count++] = start;
352 * host_from_uh - get the host.domain part of a user@host.domain string
353 * ripped from get_sockhost
355 char* host_from_uh(char* host, const char* userhost, size_t n)
360 assert(0 != userhost);
362 if ((s = strchr(userhost, '@')))
366 ircd_strncpy(host, s, n);
372 * this new faster inet_ntoa was ripped from:
373 * From: Thomas Helvey <tomh@inxpress.net>
375 static const char* IpQuadTab[] =
377 "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
378 "10", "11", "12", "13", "14", "15", "16", "17", "18", "19",
379 "20", "21", "22", "23", "24", "25", "26", "27", "28", "29",
380 "30", "31", "32", "33", "34", "35", "36", "37", "38", "39",
381 "40", "41", "42", "43", "44", "45", "46", "47", "48", "49",
382 "50", "51", "52", "53", "54", "55", "56", "57", "58", "59",
383 "60", "61", "62", "63", "64", "65", "66", "67", "68", "69",
384 "70", "71", "72", "73", "74", "75", "76", "77", "78", "79",
385 "80", "81", "82", "83", "84", "85", "86", "87", "88", "89",
386 "90", "91", "92", "93", "94", "95", "96", "97", "98", "99",
387 "100", "101", "102", "103", "104", "105", "106", "107", "108", "109",
388 "110", "111", "112", "113", "114", "115", "116", "117", "118", "119",
389 "120", "121", "122", "123", "124", "125", "126", "127", "128", "129",
390 "130", "131", "132", "133", "134", "135", "136", "137", "138", "139",
391 "140", "141", "142", "143", "144", "145", "146", "147", "148", "149",
392 "150", "151", "152", "153", "154", "155", "156", "157", "158", "159",
393 "160", "161", "162", "163", "164", "165", "166", "167", "168", "169",
394 "170", "171", "172", "173", "174", "175", "176", "177", "178", "179",
395 "180", "181", "182", "183", "184", "185", "186", "187", "188", "189",
396 "190", "191", "192", "193", "194", "195", "196", "197", "198", "199",
397 "200", "201", "202", "203", "204", "205", "206", "207", "208", "209",
398 "210", "211", "212", "213", "214", "215", "216", "217", "218", "219",
399 "220", "221", "222", "223", "224", "225", "226", "227", "228", "229",
400 "230", "231", "232", "233", "234", "235", "236", "237", "238", "239",
401 "240", "241", "242", "243", "244", "245", "246", "247", "248", "249",
402 "250", "251", "252", "253", "254", "255"
406 * ircd_ntoa - rewrote and renamed yet again :) --Bleep
407 * inetntoa - in_addr to string
408 * changed name to remove collision possibility and
409 * so behaviour is guaranteed to take a pointer arg.
411 * inet_ntoa -- returned the dotted notation of a given
414 * inet_ntoa -- its broken on some Ultrix/Dynix too. -avalon
416 const char* ircd_ntoa(const char* in)
419 return ircd_ntoa_r(buf, in);
423 * reentrant version of above
425 const char* ircd_ntoa_r(char* buf, const char* in)
428 const unsigned char* a = (const unsigned char*)in;