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