Restore stats_spy hook that was removed in commit 401f2454671ca233e35b0e6e4f3fa4c43cd...
[seven-1.x.git] / src / irc_string.c
blobcdc8506402822cf476b4312815df30fee2ef7c03
1 /*
2 * ircd-ratbox: A slightly useful ircd.
3 * irc_string.c: IRC string functions.
5 * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
6 * Copyright (C) 1996-2002 Hybrid Development Team
7 * Copyright (C) 2002-2005 ircd-ratbox development team
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22 * USA
25 #include "stdinc.h"
26 #include "sprintf_irc.h"
27 #include "tools.h"
28 #include "irc_string.h"
29 #include "client.h"
30 #include "memory.h"
31 #include "setup.h"
33 #ifndef INADDRSZ
34 #define INADDRSZ 4
35 #endif
37 #ifdef IPV6
38 #ifndef IN6ADDRSZ
39 #define IN6ADDRSZ 16
40 #endif
41 #endif
43 #ifndef INT16SZ
44 #define INT16SZ 2
45 #endif
47 * myctime - This is like standard ctime()-function, but it zaps away
48 * the newline from the end of that string. Also, it takes
49 * the time value as parameter, instead of pointer to it.
50 * Note that it is necessary to copy the string to alternate
51 * buffer (who knows how ctime() implements it, maybe it statically
52 * has newline there and never 'refreshes' it -- zapping that
53 * might break things in other places...)
56 * Thu Nov 24 18:22:48 1986
58 const char *
59 myctime(time_t value)
61 static char buf[32];
62 char *p;
64 strcpy(buf, ctime(&value));
65 if((p = strchr(buf, '\n')) != NULL)
66 *p = '\0';
67 return buf;
72 * clean_string - clean up a string possibly containing garbage
74 * *sigh* Before the kiddies find this new and exciting way of
75 * annoying opers, lets clean up what is sent to local opers
76 * -Dianora
78 char *
79 clean_string(char *dest, const unsigned char *src, size_t len)
81 char *d = dest;
82 s_assert(0 != dest);
83 s_assert(0 != src);
85 if(dest == NULL || src == NULL)
86 return NULL;
88 len -= 3; /* allow for worst case, '^A\0' */
90 while(*src && (len > 0))
92 if(*src & 0x80) /* if high bit is set */
94 *d++ = '.';
95 --len;
97 else if(!IsPrint(*src)) /* if NOT printable */
99 *d++ = '^';
100 --len;
101 *d++ = 0x40 + *src; /* turn it into a printable */
103 else
104 *d++ = *src;
105 ++src;
106 --len;
108 *d = '\0';
109 return dest;
113 * strip_tabs(dst, src, length)
115 * Copies src to dst, while converting all \t (tabs) into spaces.
117 * NOTE: jdc: I have a gut feeling there's a faster way to do this.
119 char *
120 strip_tabs(char *dest, const unsigned char *src, size_t len)
122 char *d = dest;
123 /* Sanity check; we don't want anything nasty... */
124 s_assert(0 != dest);
125 s_assert(0 != src);
127 if(dest == NULL || src == NULL)
128 return NULL;
130 while(*src && (len > 0))
132 if(*src == '\t')
134 *d++ = ' '; /* Translate the tab into a space */
136 else
138 *d++ = *src; /* Copy src to dst */
140 ++src;
141 --len;
143 *d = '\0'; /* Null terminate, thanks and goodbye */
144 return dest;
148 * strtoken - walk through a string of tokens, using a set of separators
149 * argv 9/90
152 char *
153 strtoken(char **save, char *str, const char *fs)
155 char *pos = *save; /* keep last position across calls */
156 char *tmp;
158 if(str)
159 pos = str; /* new string scan */
161 while(pos && *pos && strchr(fs, *pos) != NULL)
162 ++pos; /* skip leading separators */
164 if(!pos || !*pos)
165 return (pos = *save = NULL); /* string contains only sep's */
167 tmp = pos; /* now, keep position of the token */
169 while(*pos && strchr(fs, *pos) == NULL)
170 ++pos; /* skip content of the token */
172 if(*pos)
173 *pos++ = '\0'; /* remove first sep after the token */
174 else
175 pos = NULL; /* end of string */
177 *save = pos;
178 return tmp;
181 static const char base64_table[] =
182 { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
183 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
184 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
185 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
186 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '\0'
189 static const char base64_pad = '=';
191 static const short base64_reverse_table[256] = {
192 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
193 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
194 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
195 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
196 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
197 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
198 -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
199 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
200 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
201 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
202 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
203 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
204 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
205 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
206 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
207 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
210 unsigned char *
211 ircd_base64_encode(const unsigned char *str, int length)
213 const unsigned char *current = str;
214 unsigned char *p;
215 unsigned char *result;
217 if ((length + 2) < 0 || ((length + 2) / 3) >= (1 << (sizeof(int) * 8 - 2))) {
218 return NULL;
221 result = MyMalloc(((length + 2) / 3) * 5);
222 p = result;
224 while (length > 2)
226 *p++ = base64_table[current[0] >> 2];
227 *p++ = base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)];
228 *p++ = base64_table[((current[1] & 0x0f) << 2) + (current[2] >> 6)];
229 *p++ = base64_table[current[2] & 0x3f];
231 current += 3;
232 length -= 3;
235 if (length != 0) {
236 *p++ = base64_table[current[0] >> 2];
237 if (length > 1) {
238 *p++ = base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)];
239 *p++ = base64_table[(current[1] & 0x0f) << 2];
240 *p++ = base64_pad;
241 } else {
242 *p++ = base64_table[(current[0] & 0x03) << 4];
243 *p++ = base64_pad;
244 *p++ = base64_pad;
247 *p = '\0';
248 return result;
251 unsigned char *
252 ircd_base64_decode(const unsigned char *str, int length, int *ret)
254 const unsigned char *current = str;
255 int ch, i = 0, j = 0, k;
256 unsigned char *result;
258 result = MyMalloc(length + 1);
260 while ((ch = *current++) != '\0' && length-- > 0) {
261 if (ch == base64_pad) break;
263 ch = base64_reverse_table[ch];
264 if (ch < 0) continue;
266 switch(i % 4) {
267 case 0:
268 result[j] = ch << 2;
269 break;
270 case 1:
271 result[j++] |= ch >> 4;
272 result[j] = (ch & 0x0f) << 4;
273 break;
274 case 2:
275 result[j++] |= ch >>2;
276 result[j] = (ch & 0x03) << 6;
277 break;
278 case 3:
279 result[j++] |= ch;
280 break;
282 i++;
285 k = j;
287 if (ch == base64_pad) {
288 switch(i % 4) {
289 case 1:
290 free(result);
291 return NULL;
292 case 2:
293 k++;
294 case 3:
295 result[k++] = 0;
298 result[j] = '\0';
300 if(ret)
301 *ret = j;
303 return result;
307 * From: Thomas Helvey <tomh@inxpress.net>
309 static const char *IpQuadTab[] = {
310 "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
311 "10", "11", "12", "13", "14", "15", "16", "17", "18", "19",
312 "20", "21", "22", "23", "24", "25", "26", "27", "28", "29",
313 "30", "31", "32", "33", "34", "35", "36", "37", "38", "39",
314 "40", "41", "42", "43", "44", "45", "46", "47", "48", "49",
315 "50", "51", "52", "53", "54", "55", "56", "57", "58", "59",
316 "60", "61", "62", "63", "64", "65", "66", "67", "68", "69",
317 "70", "71", "72", "73", "74", "75", "76", "77", "78", "79",
318 "80", "81", "82", "83", "84", "85", "86", "87", "88", "89",
319 "90", "91", "92", "93", "94", "95", "96", "97", "98", "99",
320 "100", "101", "102", "103", "104", "105", "106", "107", "108", "109",
321 "110", "111", "112", "113", "114", "115", "116", "117", "118", "119",
322 "120", "121", "122", "123", "124", "125", "126", "127", "128", "129",
323 "130", "131", "132", "133", "134", "135", "136", "137", "138", "139",
324 "140", "141", "142", "143", "144", "145", "146", "147", "148", "149",
325 "150", "151", "152", "153", "154", "155", "156", "157", "158", "159",
326 "160", "161", "162", "163", "164", "165", "166", "167", "168", "169",
327 "170", "171", "172", "173", "174", "175", "176", "177", "178", "179",
328 "180", "181", "182", "183", "184", "185", "186", "187", "188", "189",
329 "190", "191", "192", "193", "194", "195", "196", "197", "198", "199",
330 "200", "201", "202", "203", "204", "205", "206", "207", "208", "209",
331 "210", "211", "212", "213", "214", "215", "216", "217", "218", "219",
332 "220", "221", "222", "223", "224", "225", "226", "227", "228", "229",
333 "230", "231", "232", "233", "234", "235", "236", "237", "238", "239",
334 "240", "241", "242", "243", "244", "245", "246", "247", "248", "249",
335 "250", "251", "252", "253", "254", "255"
339 * inetntoa - in_addr to string
340 * changed name to remove collision possibility and
341 * so behaviour is guaranteed to take a pointer arg.
342 * -avalon 23/11/92
343 * inet_ntoa -- returned the dotted notation of a given
344 * internet number
345 * argv 11/90).
346 * inet_ntoa -- its broken on some Ultrix/Dynix too. -avalon
349 const char *
350 inetntoa(const char *in)
352 static char buf[16];
353 char *bufptr = buf;
354 const unsigned char *a = (const unsigned char *) in;
355 const char *n;
357 n = IpQuadTab[*a++];
358 while(*n)
359 *bufptr++ = *n++;
360 *bufptr++ = '.';
361 n = IpQuadTab[*a++];
362 while(*n)
363 *bufptr++ = *n++;
364 *bufptr++ = '.';
365 n = IpQuadTab[*a++];
366 while(*n)
367 *bufptr++ = *n++;
368 *bufptr++ = '.';
369 n = IpQuadTab[*a];
370 while(*n)
371 *bufptr++ = *n++;
372 *bufptr = '\0';
373 return buf;
377 * Copyright (c) 1996-1999 by Internet Software Consortium.
379 * Permission to use, copy, modify, and distribute this software for any
380 * purpose with or without fee is hereby granted, provided that the above
381 * copyright notice and this permission notice appear in all copies.
383 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
384 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
385 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
386 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
387 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
388 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
389 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
390 * SOFTWARE.
393 #define SPRINTF(x) ((size_t)ircsprintf x)
396 * WARNING: Don't even consider trying to compile this on a system where
397 * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
400 static const char *inet_ntop4(const u_char * src, char *dst, unsigned int size);
401 #ifdef IPV6
402 static const char *inet_ntop6(const u_char * src, char *dst, unsigned int size);
403 #endif
405 /* const char *
406 * inet_ntop4(src, dst, size)
407 * format an IPv4 address
408 * return:
409 * `dst' (as a const)
410 * notes:
411 * (1) uses no statics
412 * (2) takes a u_char* not an in_addr as input
413 * author:
414 * Paul Vixie, 1996.
416 static const char *
417 inet_ntop4(const unsigned char *src, char *dst, unsigned int size)
419 if(size < 16)
420 return NULL;
421 return strcpy(dst, inetntoa((const char *) src));
424 /* const char *
425 * inet_ntop6(src, dst, size)
426 * convert IPv6 binary address into presentation (printable) format
427 * author:
428 * Paul Vixie, 1996.
430 #ifdef IPV6
431 static const char *
432 inet_ntop6(const unsigned char *src, char *dst, unsigned int size)
435 * Note that int32_t and int16_t need only be "at least" large enough
436 * to contain a value of the specified size. On some systems, like
437 * Crays, there is no such thing as an integer variable with 16 bits.
438 * Keep this in mind if you think this function should have been coded
439 * to use pointer overlays. All the world's not a VAX.
441 char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
442 struct
444 int base, len;
446 best, cur;
447 u_int words[IN6ADDRSZ / INT16SZ];
448 int i;
451 * Preprocess:
452 * Copy the input (bytewise) array into a wordwise array.
453 * Find the longest run of 0x00's in src[] for :: shorthanding.
455 memset(words, '\0', sizeof words);
456 for(i = 0; i < IN6ADDRSZ; i += 2)
457 words[i / 2] = (src[i] << 8) | src[i + 1];
458 best.base = -1;
459 cur.base = -1;
460 for(i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
462 if(words[i] == 0)
464 if(cur.base == -1)
465 cur.base = i, cur.len = 1;
466 else
467 cur.len++;
469 else
471 if(cur.base != -1)
473 if(best.base == -1 || cur.len > best.len)
474 best = cur;
475 cur.base = -1;
479 if(cur.base != -1)
481 if(best.base == -1 || cur.len > best.len)
482 best = cur;
484 if(best.base != -1 && best.len < 2)
485 best.base = -1;
488 * Format the result.
490 tp = tmp;
491 for(i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
493 /* Are we inside the best run of 0x00's? */
494 if(best.base != -1 && i >= best.base && i < (best.base + best.len))
496 if(i == best.base)
498 if(i == 0)
499 *tp++ = '0';
500 *tp++ = ':';
502 continue;
504 /* Are we following an initial run of 0x00s or any real hex? */
505 if(i != 0)
506 *tp++ = ':';
507 /* Is this address an encapsulated IPv4? */
508 if(i == 6 && best.base == 0 &&
509 (best.len == 6 || (best.len == 5 && words[5] == 0xffff)))
511 if(!inet_ntop4(src + 12, tp, sizeof tmp - (tp - tmp)))
512 return (NULL);
513 tp += strlen(tp);
514 break;
516 tp += SPRINTF((tp, "%x", words[i]));
518 /* Was it a trailing run of 0x00's? */
519 if(best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ))
520 *tp++ = ':';
521 *tp++ = '\0';
524 * Check for overflow, copy, and we're done.
527 if((unsigned int) (tp - tmp) > size)
529 return (NULL);
531 return strcpy(dst, tmp);
533 #endif
536 inetpton_sock(const char *src, struct sockaddr *dst)
538 if(inetpton(AF_INET, src, &((struct sockaddr_in *) dst)->sin_addr))
540 ((struct sockaddr_in *) dst)->sin_port = 0;
541 ((struct sockaddr_in *) dst)->sin_family = AF_INET;
542 SET_SS_LEN(*((struct irc_sockaddr_storage *) dst), sizeof(struct sockaddr_in));
543 return 1;
545 #ifdef IPV6
546 else if(inetpton(AF_INET6, src, &((struct sockaddr_in6 *) dst)->sin6_addr))
548 ((struct sockaddr_in6 *) dst)->sin6_port = 0;
549 ((struct sockaddr_in6 *) dst)->sin6_family = AF_INET6;
550 SET_SS_LEN(*((struct irc_sockaddr_storage *) dst), sizeof(struct sockaddr_in6));
551 return 1;
553 #endif
554 return 0;
557 const char *
558 inetntop_sock(struct sockaddr *src, char *dst, unsigned int size)
560 switch (src->sa_family)
562 case AF_INET:
563 return (inetntop(AF_INET, &((struct sockaddr_in *) src)->sin_addr, dst, size));
564 break;
565 #ifdef IPV6
566 case AF_INET6:
567 return (inetntop(AF_INET6, &((struct sockaddr_in6 *) src)->sin6_addr, dst, size));
568 break;
569 #endif
570 default:
571 return NULL;
572 break;
576 /* char *
577 * inetntop(af, src, dst, size)
578 * convert a network format address to presentation format.
579 * return:
580 * pointer to presentation format address (`dst'), or NULL (see errno).
581 * author:
582 * Paul Vixie, 1996.
584 const char *
585 inetntop(int af, const void *src, char *dst, unsigned int size)
587 switch (af)
589 case AF_INET:
590 return (inet_ntop4(src, dst, size));
591 #ifdef IPV6
592 case AF_INET6:
593 if(IN6_IS_ADDR_V4MAPPED((const struct in6_addr *) src) ||
594 IN6_IS_ADDR_V4COMPAT((const struct in6_addr *) src))
595 return (inet_ntop4
596 ((const unsigned char *)
597 &((const struct in6_addr *) src)->s6_addr[12], dst, size));
598 else
599 return (inet_ntop6(src, dst, size));
602 #endif
603 default:
604 return (NULL);
606 /* NOTREACHED */
610 * WARNING: Don't even consider trying to compile this on a system where
611 * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
614 /* int
615 * inetpton(af, src, dst)
616 * convert from presentation format (which usually means ASCII printable)
617 * to network format (which is usually some kind of binary format).
618 * return:
619 * 1 if the address was valid for the specified address family
620 * 0 if the address wasn't valid (`dst' is untouched in this case)
621 * -1 if some other error occurred (`dst' is untouched in this case, too)
622 * author:
623 * Paul Vixie, 1996.
626 /* int
627 * inet_pton4(src, dst)
628 * like inet_aton() but without all the hexadecimal and shorthand.
629 * return:
630 * 1 if `src' is a valid dotted quad, else 0.
631 * notice:
632 * does not touch `dst' unless it's returning 1.
633 * author:
634 * Paul Vixie, 1996.
636 static int
637 inet_pton4(src, dst)
638 const char *src;
639 u_char *dst;
641 int saw_digit, octets, ch;
642 u_char tmp[INADDRSZ], *tp;
644 saw_digit = 0;
645 octets = 0;
646 *(tp = tmp) = 0;
647 while((ch = *src++) != '\0')
650 if(ch >= '0' && ch <= '9')
652 u_int new = *tp * 10 + (ch - '0');
654 if(new > 255)
655 return (0);
656 *tp = new;
657 if(!saw_digit)
659 if(++octets > 4)
660 return (0);
661 saw_digit = 1;
664 else if(ch == '.' && saw_digit)
666 if(octets == 4)
667 return (0);
668 *++tp = 0;
669 saw_digit = 0;
671 else
672 return (0);
674 if(octets < 4)
675 return (0);
676 memcpy(dst, tmp, INADDRSZ);
677 return (1);
680 #ifdef IPV6
681 /* int
682 * inet_pton6(src, dst)
683 * convert presentation level address to network order binary form.
684 * return:
685 * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
686 * notice:
687 * (1) does not touch `dst' unless it's returning 1.
688 * (2) :: in a full address is silently ignored.
689 * credit:
690 * inspired by Mark Andrews.
691 * author:
692 * Paul Vixie, 1996.
695 static int
696 inet_pton6(src, dst)
697 const char *src;
698 u_char *dst;
700 static const char xdigits[] = "0123456789abcdef";
701 u_char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
702 const char *curtok;
703 int ch, saw_xdigit;
704 u_int val;
706 tp = memset(tmp, '\0', IN6ADDRSZ);
707 endp = tp + IN6ADDRSZ;
708 colonp = NULL;
709 /* Leading :: requires some special handling. */
710 if(*src == ':')
711 if(*++src != ':')
712 return (0);
713 curtok = src;
714 saw_xdigit = 0;
715 val = 0;
716 while((ch = tolower(*src++)) != '\0')
718 const char *pch;
720 pch = strchr(xdigits, ch);
721 if(pch != NULL)
723 val <<= 4;
724 val |= (pch - xdigits);
725 if(val > 0xffff)
726 return (0);
727 saw_xdigit = 1;
728 continue;
730 if(ch == ':')
732 curtok = src;
733 if(!saw_xdigit)
735 if(colonp)
736 return (0);
737 colonp = tp;
738 continue;
740 else if(*src == '\0')
742 return (0);
744 if(tp + INT16SZ > endp)
745 return (0);
746 *tp++ = (u_char) (val >> 8) & 0xff;
747 *tp++ = (u_char) val & 0xff;
748 saw_xdigit = 0;
749 val = 0;
750 continue;
752 if(*src != '\0' && ch == '.')
754 if(((tp + INADDRSZ) <= endp) && inet_pton4(curtok, tp) > 0)
756 tp += INADDRSZ;
757 saw_xdigit = 0;
758 break; /* '\0' was seen by inet_pton4(). */
761 else
762 continue;
763 return (0);
765 if(saw_xdigit)
767 if(tp + INT16SZ > endp)
768 return (0);
769 *tp++ = (u_char) (val >> 8) & 0xff;
770 *tp++ = (u_char) val & 0xff;
772 if(colonp != NULL)
775 * Since some memmove()'s erroneously fail to handle
776 * overlapping regions, we'll do the shift by hand.
778 const int n = tp - colonp;
779 int i;
781 if(tp == endp)
782 return (0);
783 for(i = 1; i <= n; i++)
785 endp[-i] = colonp[n - i];
786 colonp[n - i] = 0;
788 tp = endp;
790 if(tp != endp)
791 return (0);
792 memcpy(dst, tmp, IN6ADDRSZ);
793 return (1);
795 #endif
797 inetpton(af, src, dst)
798 int af;
799 const char *src;
800 void *dst;
802 switch (af)
804 case AF_INET:
805 return (inet_pton4(src, dst));
806 #ifdef IPV6
807 case AF_INET6:
808 /* Somebody might have passed as an IPv4 address this is sick but it works */
809 if(inet_pton4(src, dst))
811 char tmp[HOSTIPLEN];
812 ircsprintf(tmp, "::ffff:%s", src);
813 return (inet_pton6(tmp, dst));
815 else
816 return (inet_pton6(src, dst));
817 #endif
818 default:
819 return (-1);
821 /* NOTREACHED */
825 * strlcat and strlcpy were ripped from openssh 2.5.1p2
826 * They had the following Copyright info:
829 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
830 * All rights reserved.
832 * Redistribution and use in source and binary forms, with or without
833 * modification, are permitted provided that the following conditions
834 * are met:
835 * 1. Redistributions of source code must retain the above copyright
836 * notice, this list of conditions and the following disclaimer.
837 * 2. Redistributions in binary form must reproduce the above copyright
838 * notice, this list of conditions and the following disclaimer in the
839 * documentation and/or other materials provided with the distribution.
840 * 3. The name of the author may not be used to endorse or promote products
841 * derived from this software without specific prior written permission.
843 * THIS SOFTWARE IS PROVIDED `AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
844 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
845 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
846 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
847 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
848 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
849 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
850 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
851 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
852 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
857 #ifndef HAVE_STRLCAT
858 size_t
859 strlcat(char *dst, const char *src, size_t siz)
861 char *d = dst;
862 const char *s = src;
863 size_t n = siz, dlen;
865 while(n-- != 0 && *d != '\0')
866 d++;
867 dlen = d - dst;
868 n = siz - dlen;
870 if(n == 0)
871 return (dlen + strlen(s));
872 while(*s != '\0')
874 if(n != 1)
876 *d++ = *s;
877 n--;
879 s++;
881 *d = '\0';
882 return (dlen + (s - src)); /* count does not include NUL */
884 #endif
886 #ifndef HAVE_STRLCPY
887 size_t
888 strlcpy(char *dst, const char *src, size_t siz)
890 char *d = dst;
891 const char *s = src;
892 size_t n = siz;
893 /* Copy as many bytes as will fit */
894 if(n != 0 && --n != 0)
898 if((*d++ = *s++) == 0)
899 break;
901 while(--n != 0);
903 /* Not enough room in dst, add NUL and traverse rest of src */
904 if(n == 0)
906 if(siz != 0)
907 *d = '\0'; /* NUL-terminate dst */
908 while(*s++)
912 return (s - src - 1); /* count does not include NUL */
914 #endif
916 char *
917 strip_colour(char *string)
919 char *c = string;
920 char *c2 = string;
921 char *last_non_space = NULL;
922 /* c is source, c2 is target */
923 for(; c && *c; c++)
924 switch (*c)
926 case 3:
927 if(isdigit(c[1]))
929 c++;
930 if(isdigit(c[1]))
931 c++;
932 if(c[1] == ',' && isdigit(c[2]))
934 c += 2;
935 if(isdigit(c[1]))
936 c++;
939 break;
940 case 2:
941 case 6:
942 case 7:
943 case 22:
944 case 23:
945 case 27:
946 case 31:
947 break;
948 case 32:
949 *c2++ = *c;
950 break;
951 default:
952 *c2++ = *c;
953 last_non_space = c2;
954 break;
956 *c2 = '\0';
957 if(last_non_space)
958 *last_non_space = '\0';
959 return string;