ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/irc_string.c
Revision: 33
Committed: Sun Oct 2 20:50:00 2005 UTC (19 years, 10 months ago) by knight
Content type: text/x-csrc
Original Path: ircd-hybrid/src/irc_string.c
File size: 15071 byte(s)
Log Message:
- svn:keywords

File Contents

# User Rev Content
1 adx 30 /*
2     * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3     * irc_string.c: IRC string functions.
4     *
5     * Copyright (C) 2002 by the past and present ircd coders, and others.
6     *
7     * This program is free software; you can redistribute it and/or modify
8     * it under the terms of the GNU General Public License as published by
9     * the Free Software Foundation; either version 2 of the License, or
10     * (at your option) any later version.
11     *
12     * This program is distributed in the hope that it will be useful,
13     * but WITHOUT ANY WARRANTY; without even the implied warranty of
14     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     * GNU General Public License for more details.
16     *
17     * You should have received a copy of the GNU General Public License
18     * along with this program; if not, write to the Free Software
19     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20     * USA
21     *
22 knight 31 * $Id$
23 adx 30 */
24    
25     #include "stdinc.h"
26     #include "tools.h"
27     #include "pcre.h"
28     #include "irc_string.h"
29     #include "sprintf_irc.h"
30     #include "client.h"
31     #include "list.h"
32     #include "memory.h"
33    
34     #ifndef INADDRSZ
35     #define INADDRSZ 4
36     #endif
37    
38     #ifndef IN6ADDRSZ
39     #define IN6ADDRSZ 16
40     #endif
41    
42     #ifndef INT16SZ
43     #define INT16SZ 2
44     #endif
45    
46    
47     char *
48     xstrldup(const char *s, size_t n)
49     {
50     size_t len = strlen(s) + 1;
51     char *p = NULL;
52    
53     if (len > n)
54     len = n;
55     return strlcpy((p = malloc(len)), s, len), p;
56     }
57    
58     /*
59     * myctime - This is like standard ctime()-function, but it zaps away
60     * the newline from the end of that string. Also, it takes
61     * the time value as parameter, instead of pointer to it.
62     * Note that it is necessary to copy the string to alternate
63     * buffer (who knows how ctime() implements it, maybe it statically
64     * has newline there and never 'refreshes' it -- zapping that
65     * might break things in other places...)
66     *
67     *
68     * Thu Nov 24 18:22:48 1986
69     */
70     const char *
71     myctime(time_t value)
72     {
73     static char buf[32];
74     char *p;
75    
76     strcpy(buf, ctime(&value));
77    
78     if ((p = strchr(buf, '\n')) != NULL)
79     *p = '\0';
80     return buf;
81     }
82    
83     /*
84     * clean_string - clean up a string possibly containing garbage
85     *
86     * *sigh* Before the kiddies find this new and exciting way of
87     * annoying opers, lets clean up what is sent to local opers
88     * -Dianora
89     */
90     char *
91     clean_string(char* dest, const unsigned char* src, size_t len)
92     {
93     char* d = dest;
94     assert(0 != dest);
95     assert(0 != src);
96    
97     if(dest == NULL || src == NULL)
98     return NULL;
99    
100     len -= 3; /* allow for worst case, '^A\0' */
101    
102     while (*src && (len > 0))
103     {
104     if (*src & 0x80) /* if high bit is set */
105     {
106     *d++ = '.';
107     --len;
108     }
109     else if (!IsPrint(*src)) /* if NOT printable */
110     {
111     *d++ = '^';
112     --len;
113     *d++ = 0x40 + *src; /* turn it into a printable */
114     }
115     else
116     *d++ = *src;
117     ++src, --len;
118     }
119     *d = '\0';
120     return dest;
121     }
122    
123     /*
124     * strip_tabs(dst, src, length)
125     *
126     * Copies src to dst, while converting all \t (tabs) into spaces.
127     */
128     void
129     strip_tabs(char *dest, const char *src, size_t len)
130     {
131     char *d = dest;
132    
133     /* Sanity check; we don't want anything nasty... */
134     assert(dest != NULL);
135     assert(src != NULL);
136     assert(len > 0);
137    
138     for (; --len && *src; ++src)
139     *d++ = *src == '\t' ? ' ' : *src;
140    
141     *d = '\0'; /* NUL terminate, thanks and goodbye */
142     }
143    
144     /*
145     * strtoken - walk through a string of tokens, using a set of separators
146     * argv 9/90
147     *
148     */
149     #ifndef HAVE_STRTOK_R
150    
151     char *
152     strtoken(char** save, char* str, const char* fs)
153     {
154     char* pos = *save; /* keep last position across calls */
155     char* tmp;
156    
157     if (str)
158     pos = str; /* new string scan */
159    
160     while (pos && *pos && strchr(fs, *pos) != NULL)
161     ++pos; /* skip leading separators */
162    
163     if (!pos || !*pos)
164     return (pos = *save = NULL); /* string contains only sep's */
165    
166     tmp = pos; /* now, keep position of the token */
167    
168     while (*pos && strchr(fs, *pos) == NULL)
169     ++pos; /* skip content of the token */
170    
171     if (*pos)
172     *pos++ = '\0'; /* remove first sep after the token */
173     else
174     pos = NULL; /* end of string */
175    
176     *save = pos;
177     return tmp;
178     }
179    
180     #endif /* !HAVE_STRTOK_R */
181    
182     /*
183     * From: Thomas Helvey <tomh@inxpress.net>
184     */
185     static const char *IpQuadTab[] =
186     {
187     "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
188     "10", "11", "12", "13", "14", "15", "16", "17", "18", "19",
189     "20", "21", "22", "23", "24", "25", "26", "27", "28", "29",
190     "30", "31", "32", "33", "34", "35", "36", "37", "38", "39",
191     "40", "41", "42", "43", "44", "45", "46", "47", "48", "49",
192     "50", "51", "52", "53", "54", "55", "56", "57", "58", "59",
193     "60", "61", "62", "63", "64", "65", "66", "67", "68", "69",
194     "70", "71", "72", "73", "74", "75", "76", "77", "78", "79",
195     "80", "81", "82", "83", "84", "85", "86", "87", "88", "89",
196     "90", "91", "92", "93", "94", "95", "96", "97", "98", "99",
197     "100", "101", "102", "103", "104", "105", "106", "107", "108", "109",
198     "110", "111", "112", "113", "114", "115", "116", "117", "118", "119",
199     "120", "121", "122", "123", "124", "125", "126", "127", "128", "129",
200     "130", "131", "132", "133", "134", "135", "136", "137", "138", "139",
201     "140", "141", "142", "143", "144", "145", "146", "147", "148", "149",
202     "150", "151", "152", "153", "154", "155", "156", "157", "158", "159",
203     "160", "161", "162", "163", "164", "165", "166", "167", "168", "169",
204     "170", "171", "172", "173", "174", "175", "176", "177", "178", "179",
205     "180", "181", "182", "183", "184", "185", "186", "187", "188", "189",
206     "190", "191", "192", "193", "194", "195", "196", "197", "198", "199",
207     "200", "201", "202", "203", "204", "205", "206", "207", "208", "209",
208     "210", "211", "212", "213", "214", "215", "216", "217", "218", "219",
209     "220", "221", "222", "223", "224", "225", "226", "227", "228", "229",
210     "230", "231", "232", "233", "234", "235", "236", "237", "238", "239",
211     "240", "241", "242", "243", "244", "245", "246", "247", "248", "249",
212     "250", "251", "252", "253", "254", "255"
213     };
214    
215     /*
216     * inetntoa - in_addr to string
217     * changed name to remove collision possibility and
218     * so behaviour is guaranteed to take a pointer arg.
219     * -avalon 23/11/92
220     * inet_ntoa -- returned the dotted notation of a given
221     * internet number
222     * argv 11/90).
223     * inet_ntoa -- its broken on some Ultrix/Dynix too. -avalon
224     */
225     const char *
226     inetntoa(const char *in)
227     {
228     static char buf[16];
229     char *bufptr = buf;
230     const unsigned char *a = (const unsigned char *)in;
231     const char *n;
232    
233     n = IpQuadTab[ *a++ ];
234     while (*n)
235     *bufptr++ = *n++;
236     *bufptr++ = '.';
237     n = IpQuadTab[ *a++ ];
238     while (*n)
239     *bufptr++ = *n++;
240     *bufptr++ = '.';
241     n = IpQuadTab[ *a++ ];
242     while (*n)
243     *bufptr++ = *n++;
244     *bufptr++ = '.';
245     n = IpQuadTab[ *a ];
246     while (*n)
247     *bufptr++ = *n++;
248     *bufptr = '\0';
249     return buf;
250     }
251    
252     #ifndef HAVE_BASENAME
253    
254     /* basename()
255     *
256     * input - i.e. "/usr/local/ircd/modules/m_whois.so"
257     * output - i.e. "m_whois.so"
258     * side effects - this will be overwritten on subsequent calls
259     */
260     char *
261     basename(char *path)
262     {
263     char *s;
264    
265     if ((s = strrchr(path, '/')) == NULL)
266     s = path;
267     else
268     s++;
269    
270     return s;
271     }
272    
273     #endif /* !HAVE_BASENAME */
274    
275     /*
276     * Copyright (c) 1996-1999 by Internet Software Consortium.
277     *
278     * Permission to use, copy, modify, and distribute this software for any
279     * purpose with or without fee is hereby granted, provided that the above
280     * copyright notice and this permission notice appear in all copies.
281     *
282     * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
283     * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
284     * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
285     * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
286     * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
287     * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
288     * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
289     * SOFTWARE.
290     */
291    
292     #define SPRINTF(x) ((size_t)ircsprintf x)
293    
294     /*
295     * WARNING: Don't even consider trying to compile this on a system where
296     * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
297     */
298    
299     static const char *inet_ntop4(const unsigned char *src, char *dst, unsigned int size);
300     #ifdef IPV6
301     static const char *inet_ntop6(const unsigned char *src, char *dst, unsigned int size);
302     #endif
303    
304     /* const char *
305     * inet_ntop4(src, dst, size)
306     * format an IPv4 address
307     * return:
308     * `dst' (as a const)
309     * notes:
310     * (1) uses no statics
311     * (2) takes a unsigned char* not an in_addr as input
312     * author:
313     * Paul Vixie, 1996.
314     */
315     static const char *
316     inet_ntop4(const unsigned char *src, char *dst, unsigned int size)
317     {
318     if (size < 16)
319     return NULL;
320    
321     return strcpy(dst, inetntoa((const char *)src));
322     }
323    
324     /* const char *
325     * inet_ntop6(src, dst, size)
326     * convert IPv6 binary address into presentation (printable) format
327     * author:
328     * Paul Vixie, 1996.
329     */
330     #ifdef IPV6
331     static const char *
332     inet_ntop6(const unsigned char *src, char *dst, unsigned int size)
333     {
334     /*
335     * Note that int32_t and int16_t need only be "at least" large enough
336     * to contain a value of the specified size. On some systems, like
337     * Crays, there is no such thing as an integer variable with 16 bits.
338     * Keep this in mind if you think this function should have been coded
339     * to use pointer overlays. All the world's not a VAX.
340     */
341     char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
342     struct { int base, len; } best, cur;
343     unsigned int words[IN6ADDRSZ / INT16SZ];
344     int i;
345    
346     /*
347     * Preprocess:
348     * Copy the input (bytewise) array into a wordwise array.
349     * Find the longest run of 0x00's in src[] for :: shorthanding.
350     */
351     memset(words, '\0', sizeof words);
352     for (i = 0; i < IN6ADDRSZ; i += 2)
353     words[i / 2] = (src[i] << 8) | src[i + 1];
354     best.base = -1;
355     cur.base = -1;
356     for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
357     if (words[i] == 0) {
358     if (cur.base == -1)
359     cur.base = i, cur.len = 1;
360     else
361     cur.len++;
362     } else {
363     if (cur.base != -1) {
364     if (best.base == -1 || cur.len > best.len)
365     best = cur;
366     cur.base = -1;
367     }
368     }
369     }
370     if (cur.base != -1) {
371     if (best.base == -1 || cur.len > best.len)
372     best = cur;
373     }
374     if (best.base != -1 && best.len < 2)
375     best.base = -1;
376    
377     /*
378     * Format the result.
379     */
380     tp = tmp;
381     for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
382     /* Are we inside the best run of 0x00's? */
383     if (best.base != -1 && i >= best.base &&
384     i < (best.base + best.len)) {
385     if (i == best.base)
386     *tp++ = ':';
387     continue;
388     }
389     /* Are we following an initial run of 0x00s or any real hex? */
390     if (i != 0)
391     *tp++ = ':';
392     /* Is this address an encapsulated IPv4? */
393     if (i == 6 && best.base == 0 &&
394     (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
395     if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp)))
396     return (NULL);
397     tp += strlen(tp);
398     break;
399     }
400     tp += SPRINTF((tp, "%x", words[i]));
401     }
402     /* Was it a trailing run of 0x00's? */
403     if (best.base != -1 && (best.base + best.len) ==
404     (IN6ADDRSZ / INT16SZ))
405     *tp++ = ':';
406     *tp++ = '\0';
407    
408     /*
409     * Check for overflow, copy, and we're done.
410     */
411    
412     assert (tp - tmp >= 0);
413    
414     if ((unsigned int)(tp - tmp) > size) {
415     return (NULL);
416     }
417     return strcpy(dst, tmp);
418     }
419     #endif
420    
421     /* char *
422     * inetntop(af, src, dst, size)
423     * convert a network format address to presentation format.
424     * return:
425     * pointer to presentation format address (`dst'), or NULL (see errno).
426     * author:
427     * Paul Vixie, 1996.
428     */
429     const char *
430     inetntop(int af, const void *src, char *dst, unsigned int size)
431     {
432     switch (af)
433     {
434     case AF_INET:
435     return inet_ntop4(src, dst, size);
436     #ifdef IPV6
437     case AF_INET6:
438     if (IN6_IS_ADDR_V4MAPPED((const struct in6_addr *)src) ||
439     IN6_IS_ADDR_V4COMPAT((const struct in6_addr *)src))
440     return inet_ntop4((unsigned char *)&((const struct in6_addr *)src)->s6_addr[12], dst, size);
441     else
442     return inet_ntop6(src, dst, size);
443     #endif
444     default:
445     return NULL;
446     }
447     /* NOTREACHED */
448     }
449    
450     /*
451     * strlcat and strlcpy were ripped from openssh 2.5.1p2
452     * They had the following Copyright info:
453     *
454     *
455     * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
456     * All rights reserved.
457     *
458     * Redistribution and use in source and binary forms, with or without
459     * modification, are permitted provided that the following conditions
460     * are met:
461     * 1. Redistributions of source code must retain the above copyright
462     * notice, this list of conditions and the following disclaimer.
463     * 2. Redistributions in binary form must reproduce the above copyright
464     * notice, this list of conditions and the following disclaimer in the
465     * documentation and/or other materials provided with the distribution.
466     * 3. The name of the author may not be used to endorse or promote products
467     * derived from this software without specific prior written permission.
468     *
469     * THIS SOFTWARE IS PROVIDED `AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
470     * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
471     * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
472     * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
473     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
474     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
475     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
476     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
477     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
478     * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
479     */
480    
481     #ifndef HAVE_STRLCAT
482     size_t
483     strlcat(char *dst, const char *src, size_t siz)
484     {
485     char *d = dst;
486     const char *s = src;
487     size_t n = siz, dlen;
488    
489     while (n-- != 0 && *d != '\0')
490     d++;
491    
492     dlen = d - dst;
493     n = siz - dlen;
494    
495     if (n == 0)
496     return(dlen + strlen(s));
497    
498     while (*s != '\0')
499     {
500     if (n != 1)
501     {
502     *d++ = *s;
503     n--;
504     }
505    
506     s++;
507     }
508    
509     *d = '\0';
510     return dlen + (s - src); /* count does not include NUL */
511     }
512     #endif
513    
514     #ifndef HAVE_STRLCPY
515     size_t
516     strlcpy(char *dst, const char *src, size_t siz)
517     {
518     char *d = dst;
519     const char *s = src;
520     size_t n = siz;
521    
522     /* Copy as many bytes as will fit */
523     if (n != 0 && --n != 0)
524     {
525     do
526     {
527     if ((*d++ = *s++) == 0)
528     break;
529     } while (--n != 0);
530     }
531    
532     /* Not enough room in dst, add NUL and traverse rest of src */
533     if (n == 0)
534     {
535     if (siz != 0)
536     *d = '\0'; /* NUL-terminate dst */
537     while (*s++)
538     ;
539     }
540    
541     return s - src - 1; /* count does not include NUL */
542     }
543     #endif
544    
545     pcre *
546     ircd_pcre_compile(const char *pattern, const char **errptr)
547     {
548     int erroroffset = 0;
549     int options = PCRE_EXTRA;
550    
551     assert(pattern);
552    
553     return pcre_compile(pattern, options, errptr, &erroroffset, NULL);
554     }
555    
556     int
557     ircd_pcre_exec(const pcre *code, const char *subject)
558     {
559     assert(code && subject);
560    
561     return pcre_exec(code, NULL, subject, strlen(subject), 0, 0, NULL, 0) < 0;
562     }

Properties

Name Value
svn:eol-style native
svn:keywords Id Revision