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