]>
Commit | Line | Data |
---|---|---|
30a4f2a8 | 1 | /* |
67508012 | 2 | * $Id: util.c,v 1.19 1996/09/20 06:28:22 wessels Exp $ |
30a4f2a8 | 3 | * |
4 | * DEBUG: | |
5 | * AUTHOR: Harvest Derived | |
6 | * | |
7 | * SQUID Internet Object Cache http://www.nlanr.net/Squid/ | |
8 | * -------------------------------------------------------- | |
9 | * | |
10 | * Squid is the result of efforts by numerous individuals from the | |
11 | * Internet community. Development is led by Duane Wessels of the | |
12 | * National Laboratory for Applied Network Research and funded by | |
13 | * the National Science Foundation. | |
14 | * | |
15 | * This program is free software; you can redistribute it and/or modify | |
16 | * it under the terms of the GNU General Public License as published by | |
17 | * the Free Software Foundation; either version 2 of the License, or | |
18 | * (at your option) any later version. | |
19 | * | |
20 | * This program is distributed in the hope that it will be useful, | |
21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
23 | * GNU General Public License for more details. | |
24 | * | |
25 | * You should have received a copy of the GNU General Public License | |
26 | * along with this program; if not, write to the Free Software | |
27 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
28 | * | |
29 | */ | |
7fc9f088 | 30 | |
30a4f2a8 | 31 | /* |
32 | * Copyright (c) 1994, 1995. All rights reserved. | |
33 | * | |
34 | * The Harvest software was developed by the Internet Research Task | |
35 | * Force Research Group on Resource Discovery (IRTF-RD): | |
36 | * | |
37 | * Mic Bowman of Transarc Corporation. | |
38 | * Peter Danzig of the University of Southern California. | |
39 | * Darren R. Hardy of the University of Colorado at Boulder. | |
40 | * Udi Manber of the University of Arizona. | |
41 | * Michael F. Schwartz of the University of Colorado at Boulder. | |
42 | * Duane Wessels of the University of Colorado at Boulder. | |
43 | * | |
44 | * This copyright notice applies to software in the Harvest | |
45 | * ``src/'' directory only. Users should consult the individual | |
46 | * copyright notices in the ``components/'' subdirectories for | |
47 | * copyright information about other software bundled with the | |
48 | * Harvest source code distribution. | |
49 | * | |
50 | * TERMS OF USE | |
51 | * | |
52 | * The Harvest software may be used and re-distributed without | |
53 | * charge, provided that the software origin and research team are | |
54 | * cited in any use of the system. Most commonly this is | |
55 | * accomplished by including a link to the Harvest Home Page | |
56 | * (http://harvest.cs.colorado.edu/) from the query page of any | |
57 | * Broker you deploy, as well as in the query result pages. These | |
58 | * links are generated automatically by the standard Broker | |
59 | * software distribution. | |
60 | * | |
61 | * The Harvest software is provided ``as is'', without express or | |
62 | * implied warranty, and with no support nor obligation to assist | |
63 | * in its use, correction, modification or enhancement. We assume | |
64 | * no liability with respect to the infringement of copyrights, | |
65 | * trade secrets, or any patents, and are not responsible for | |
66 | * consequential damages. Proper use of the Harvest software is | |
67 | * entirely the responsibility of the user. | |
68 | * | |
69 | * DERIVATIVE WORKS | |
70 | * | |
71 | * Users may make derivative works from the Harvest software, subject | |
72 | * to the following constraints: | |
73 | * | |
74 | * - You must include the above copyright notice and these | |
75 | * accompanying paragraphs in all forms of derivative works, | |
76 | * and any documentation and other materials related to such | |
77 | * distribution and use acknowledge that the software was | |
78 | * developed at the above institutions. | |
79 | * | |
80 | * - You must notify IRTF-RD regarding your distribution of | |
81 | * the derivative work. | |
82 | * | |
83 | * - You must clearly notify users that your are distributing | |
84 | * a modified version and not the original Harvest software. | |
85 | * | |
86 | * - Any derivative product is also subject to these copyright | |
87 | * and use restrictions. | |
88 | * | |
89 | * Note that the Harvest software is NOT in the public domain. We | |
90 | * retain copyright, as specified above. | |
91 | * | |
92 | * HISTORY OF FREE SOFTWARE STATUS | |
93 | * | |
94 | * Originally we required sites to license the software in cases | |
95 | * where they were going to build commercial products/services | |
96 | * around Harvest. In June 1995 we changed this policy. We now | |
97 | * allow people to use the core Harvest software (the code found in | |
98 | * the Harvest ``src/'' directory) for free. We made this change | |
99 | * in the interest of encouraging the widest possible deployment of | |
100 | * the technology. The Harvest software is really a reference | |
101 | * implementation of a set of protocols and formats, some of which | |
102 | * we intend to standardize. We encourage commercial | |
103 | * re-implementations of code complying to this set of standards. | |
104 | */ | |
0d94e9fe | 105 | |
30a4f2a8 | 106 | #include "config.h" |
107 | ||
108 | #if HAVE_STDIO_H | |
090089c4 | 109 | #include <stdio.h> |
30a4f2a8 | 110 | #endif |
111 | #if HAVE_STDLIB_H | |
090089c4 | 112 | #include <stdlib.h> |
30a4f2a8 | 113 | #endif |
114 | #if HAVE_STRING_H | |
090089c4 | 115 | #include <string.h> |
30a4f2a8 | 116 | #endif |
673d7a4d | 117 | #if HAVE_CTYPE_H |
118 | #include <ctype.h> | |
119 | #endif | |
30a4f2a8 | 120 | #if HAVE_UNISTD_H |
090089c4 | 121 | #include <unistd.h> |
30a4f2a8 | 122 | #endif |
123 | #if HAVE_MALLOC_H && !defined(_SQUID_FREEBSD_) && !defined(_SQUID_NEXT_) | |
090089c4 | 124 | #include <malloc.h> |
983061ed | 125 | #endif |
30a4f2a8 | 126 | #if HAVE_ERRNO_H |
090089c4 | 127 | #include <errno.h> |
30a4f2a8 | 128 | #endif |
090089c4 | 129 | |
f606f345 | 130 | #include "ansiproto.h" |
473471f2 | 131 | #include "util.h" |
30a4f2a8 | 132 | |
67508012 | 133 | void (*failure_notify) _PARAMS((char *)) = NULL; |
090089c4 | 134 | static char msg[128]; |
135 | ||
35570558 | 136 | extern int sys_nerr; |
30a4f2a8 | 137 | #if NEED_SYS_ERRLIST && !defined(_SQUID_NETBSD_) |
35570558 | 138 | extern char *sys_errlist[]; |
139 | #endif | |
140 | ||
30a4f2a8 | 141 | #if XMALLOC_STATISTICS |
142 | #define DBG_MAXSIZE (1024*1024) | |
143 | #define DBG_GRAIN (16) | |
144 | #define DBG_MAXINDEX (DBG_MAXSIZE/DBG_GRAIN) | |
145 | #define DBG_INDEX(sz) (sz<DBG_MAXSIZE?(sz+DBG_GRAIN-1)/DBG_GRAIN:DBG_MAXINDEX) | |
146 | static int malloc_sizes[DBG_MAXINDEX + 1]; | |
147 | static int dbg_stat_init = 0; | |
148 | ||
b8d8561b | 149 | static void |
0673c0ba | 150 | stat_init(void) |
30a4f2a8 | 151 | { |
152 | int i; | |
153 | for (i = 0; i <= DBG_MAXINDEX; i++) | |
154 | malloc_sizes[i] = 0; | |
155 | dbg_stat_init = 1; | |
156 | } | |
157 | ||
b8d8561b | 158 | static int |
159 | malloc_stat(int sz) | |
30a4f2a8 | 160 | { |
161 | if (!dbg_stat_init) | |
162 | stat_init(); | |
163 | return malloc_sizes[DBG_INDEX(sz)] += 1; | |
164 | } | |
165 | ||
b8d8561b | 166 | void |
5d3ec1a4 | 167 | malloc_statistics(void (*func) (int, int, void *), void *data) |
30a4f2a8 | 168 | { |
169 | int i; | |
170 | for (i = 0; i <= DBG_MAXSIZE; i += DBG_GRAIN) | |
171 | func(i, malloc_sizes[DBG_INDEX(i)], data); | |
172 | } | |
173 | #endif /* XMALLOC_STATISTICS */ | |
174 | ||
090089c4 | 175 | |
45e93040 | 176 | |
1d012b4c | 177 | #if XMALLOC_DEBUG |
68b468e5 | 178 | #define DBG_ARRY_SZ (1<<10) |
179 | #define DBG_ARRY_BKTS (1<<8) | |
8c6551ac | 180 | static void *malloc_ptrs[DBG_ARRY_BKTS][DBG_ARRY_SZ]; |
181 | static int malloc_size[DBG_ARRY_BKTS][DBG_ARRY_SZ]; | |
45e93040 | 182 | static int dbg_initd = 0; |
8c6551ac | 183 | static int B = 0; |
45e93040 | 184 | static int I = 0; |
185 | static void *P; | |
186 | static void *Q; | |
187 | ||
b8d8561b | 188 | static void |
0673c0ba | 189 | check_init(void) |
45e93040 | 190 | { |
68b468e5 | 191 | for (B = 0; B < DBG_ARRY_BKTS; B++) { |
30a4f2a8 | 192 | for (I = 0; I < DBG_ARRY_SZ; I++) { |
193 | malloc_ptrs[B][I] = NULL; | |
194 | malloc_size[B][I] = 0; | |
195 | } | |
45e93040 | 196 | } |
197 | dbg_initd = 1; | |
198 | } | |
199 | ||
b8d8561b | 200 | static void |
201 | check_free(void *s) | |
45e93040 | 202 | { |
8c6551ac | 203 | B = (((int) s) >> 4) & 0xFF; |
45e93040 | 204 | for (I = 0; I < DBG_ARRY_SZ; I++) { |
8c6551ac | 205 | if (malloc_ptrs[B][I] != s) |
45e93040 | 206 | continue; |
8c6551ac | 207 | malloc_ptrs[B][I] = NULL; |
208 | malloc_size[B][I] = 0; | |
45e93040 | 209 | break; |
210 | } | |
211 | if (I == DBG_ARRY_SZ) { | |
212 | sprintf(msg, "xfree: ERROR: s=%p not found!", s); | |
213 | (*failure_notify) (msg); | |
214 | } | |
215 | } | |
216 | ||
b8d8561b | 217 | static void |
218 | check_malloc(void *p, size_t sz) | |
45e93040 | 219 | { |
220 | if (!dbg_initd) | |
221 | check_init(); | |
7fc9f088 | 222 | B = (((int) p) >> 4) & 0xFF; |
45e93040 | 223 | for (I = 0; I < DBG_ARRY_SZ; I++) { |
8c6551ac | 224 | if ((P = malloc_ptrs[B][I]) == NULL) |
45e93040 | 225 | continue; |
8c6551ac | 226 | Q = P + malloc_size[B][I]; |
45e93040 | 227 | if (P <= p && p < Q) { |
228 | sprintf(msg, "xmalloc: ERROR: p=%p falls in P=%p+%d", | |
8c6551ac | 229 | p, P, malloc_size[B][I]); |
45e93040 | 230 | (*failure_notify) (msg); |
231 | } | |
232 | } | |
233 | for (I = 0; I < DBG_ARRY_SZ; I++) { | |
8c6551ac | 234 | if ((P = malloc_ptrs[B][I])) |
45e93040 | 235 | continue; |
8c6551ac | 236 | malloc_ptrs[B][I] = p; |
237 | malloc_size[B][I] = (int) sz; | |
45e93040 | 238 | break; |
239 | } | |
240 | if (I == DBG_ARRY_SZ) | |
241 | (*failure_notify) ("xmalloc: debug out of array space!"); | |
242 | } | |
243 | #endif | |
244 | ||
7fc9f088 | 245 | #if XMALLOC_COUNT && !HAVE_MALLOCBLKSIZE |
b8d8561b | 246 | int |
247 | mallocblksize(void *p) | |
7fc9f088 | 248 | { |
249 | B = (((int) p) >> 4) & 0xFF; | |
250 | for (I = 0; I < DBG_ARRY_SZ; I++) { | |
251 | if (malloc_ptrs[B][I] == p) | |
252 | return malloc_size[B][I]; | |
253 | } | |
254 | return 0; | |
255 | } | |
256 | #endif | |
257 | ||
68b468e5 | 258 | #ifdef XMALLOC_COUNT |
b8d8561b | 259 | static void |
260 | xmalloc_count(void *p, int sign) | |
68b468e5 | 261 | { |
7fc9f088 | 262 | size_t sz; |
263 | static size_t total = 0; | |
264 | int memoryAccounted(); | |
265 | int mallinfoTotal(); | |
266 | sz = mallocblksize(p) * sign; | |
267 | total += sz; | |
268 | fprintf(stderr, "xmalloc_count=%9d accounted=%9d mallinfo=%9d\n", | |
269 | (int) total, | |
270 | memoryAccounted(), | |
271 | mallinfoTotal()); | |
68b468e5 | 272 | } |
b8d8561b | 273 | |
68b468e5 | 274 | #endif /* XMALLOC_COUNT */ |
275 | ||
090089c4 | 276 | /* |
277 | * xmalloc() - same as malloc(3). Used for portability. | |
278 | * Never returns NULL; fatal on error. | |
279 | */ | |
b8d8561b | 280 | void * |
281 | xmalloc(size_t sz) | |
090089c4 | 282 | { |
283 | static void *p; | |
284 | ||
285 | if (sz < 1) | |
286 | sz = 1; | |
287 | if ((p = malloc(sz)) == NULL) { | |
288 | if (failure_notify) { | |
289 | sprintf(msg, "xmalloc: Unable to allocate %d bytes!\n", | |
290 | (int) sz); | |
291 | (*failure_notify) (msg); | |
292 | } else { | |
293 | perror("malloc"); | |
294 | } | |
295 | exit(1); | |
296 | } | |
1d012b4c | 297 | #if XMALLOC_DEBUG |
45e93040 | 298 | check_malloc(p, sz); |
30a4f2a8 | 299 | #endif |
300 | #if XMALLOC_STATISTICS | |
301 | malloc_stat(sz); | |
68b468e5 | 302 | #endif |
303 | #if XMALLOC_COUNT | |
304 | xmalloc_count(p, 1); | |
45e93040 | 305 | #endif |
090089c4 | 306 | return (p); |
307 | } | |
308 | ||
309 | /* | |
310 | * xfree() - same as free(3). Will not call free(3) if s == NULL. | |
311 | */ | |
b8d8561b | 312 | void |
313 | xfree(void *s) | |
090089c4 | 314 | { |
68b468e5 | 315 | #if XMALLOC_COUNT |
316 | xmalloc_count(s, -1); | |
7fc9f088 | 317 | #endif |
318 | #if XMALLOC_DEBUG | |
319 | check_free(s); | |
45e93040 | 320 | #endif |
321 | if (s != NULL) | |
090089c4 | 322 | free(s); |
45e93040 | 323 | } |
324 | ||
325 | /* xxfree() - like xfree(), but we already know s != NULL */ | |
b8d8561b | 326 | void |
327 | xxfree(void *s) | |
45e93040 | 328 | { |
68b468e5 | 329 | #if XMALLOC_COUNT |
330 | xmalloc_count(s, -1); | |
7fc9f088 | 331 | #endif |
332 | #if XMALLOC_DEBUG | |
333 | check_free(s); | |
45e93040 | 334 | #endif |
335 | free(s); | |
090089c4 | 336 | } |
337 | ||
338 | /* | |
339 | * xrealloc() - same as realloc(3). Used for portability. | |
340 | * Never returns NULL; fatal on error. | |
341 | */ | |
b8d8561b | 342 | void * |
343 | xrealloc(void *s, size_t sz) | |
090089c4 | 344 | { |
345 | static void *p; | |
346 | ||
68b468e5 | 347 | #if XMALLOC_COUNT |
348 | xmalloc_count(s, -1); | |
349 | #endif | |
350 | ||
090089c4 | 351 | if (sz < 1) |
352 | sz = 1; | |
353 | if ((p = realloc(s, sz)) == NULL) { | |
354 | if (failure_notify) { | |
355 | sprintf(msg, "xrealloc: Unable to reallocate %d bytes!\n", | |
356 | (int) sz); | |
357 | (*failure_notify) (msg); | |
358 | } else { | |
359 | perror("realloc"); | |
360 | } | |
361 | exit(1); | |
362 | } | |
1d012b4c | 363 | #if XMALLOC_DEBUG |
45e93040 | 364 | check_malloc(p, sz); |
30a4f2a8 | 365 | #endif |
366 | #if XMALLOC_STATISTICS | |
367 | malloc_stat(sz); | |
68b468e5 | 368 | #endif |
369 | #if XMALLOC_COUNT | |
370 | xmalloc_count(p, 1); | |
45e93040 | 371 | #endif |
090089c4 | 372 | return (p); |
373 | } | |
374 | ||
375 | /* | |
376 | * xcalloc() - same as calloc(3). Used for portability. | |
377 | * Never returns NULL; fatal on error. | |
378 | */ | |
b8d8561b | 379 | void * |
380 | xcalloc(int n, size_t sz) | |
090089c4 | 381 | { |
382 | static void *p; | |
383 | ||
384 | if (n < 1) | |
385 | n = 1; | |
386 | if (sz < 1) | |
387 | sz = 1; | |
388 | if ((p = calloc(n, sz)) == NULL) { | |
389 | if (failure_notify) { | |
390 | sprintf(msg, "xcalloc: Unable to allocate %d blocks of %d bytes!\n", | |
391 | (int) n, (int) sz); | |
392 | (*failure_notify) (msg); | |
393 | } else { | |
394 | perror("xcalloc"); | |
395 | } | |
396 | exit(1); | |
397 | } | |
1d012b4c | 398 | #if XMALLOC_DEBUG |
45e93040 | 399 | check_malloc(p, sz * n); |
30a4f2a8 | 400 | #endif |
401 | #if XMALLOC_STATISTICS | |
402 | malloc_stat(sz); | |
68b468e5 | 403 | #endif |
404 | #if XMALLOC_COUNT | |
405 | xmalloc_count(p, 1); | |
45e93040 | 406 | #endif |
090089c4 | 407 | return (p); |
408 | } | |
409 | ||
410 | /* | |
411 | * xstrdup() - same as strdup(3). Used for portability. | |
412 | * Never returns NULL; fatal on error. | |
413 | */ | |
b8d8561b | 414 | char * |
415 | xstrdup(char *s) | |
090089c4 | 416 | { |
417 | static char *p = NULL; | |
30a4f2a8 | 418 | size_t sz; |
090089c4 | 419 | |
420 | if (s == NULL) { | |
421 | if (failure_notify) { | |
422 | (*failure_notify) ("xstrdup: tried to dup a NULL pointer!\n"); | |
423 | } else { | |
424 | fprintf(stderr, "xstrdup: tried to dup a NULL pointer!\n"); | |
425 | } | |
426 | exit(1); | |
427 | } | |
428 | sz = strlen(s); | |
30a4f2a8 | 429 | p = xmalloc((size_t) sz + 1); |
090089c4 | 430 | memcpy(p, s, sz); /* copy string */ |
431 | p[sz] = '\0'; /* terminate string */ | |
432 | return (p); | |
433 | } | |
434 | ||
090089c4 | 435 | /* |
436 | * xstrerror() - return sys_errlist[errno]; | |
437 | */ | |
b8d8561b | 438 | char * |
0673c0ba | 439 | xstrerror(void) |
090089c4 | 440 | { |
35570558 | 441 | static char xstrerror_buf[BUFSIZ]; |
35570558 | 442 | if (errno < 0 || errno >= sys_nerr) |
090089c4 | 443 | return ("Unknown"); |
0f5efab0 | 444 | #if HAVE_STRERROR |
445 | sprintf(xstrerror_buf, "(%d) %s", errno, strerror(errno)); | |
446 | #else | |
35570558 | 447 | sprintf(xstrerror_buf, "(%d) %s", errno, sys_errlist[errno]); |
0f5efab0 | 448 | #endif /* HAVE_STRERROR */ |
35570558 | 449 | return xstrerror_buf; |
090089c4 | 450 | } |
451 | ||
45e93040 | 452 | #if !HAVE_STRDUP |
453 | /* define for systems that don't have strdup */ | |
b8d8561b | 454 | char * |
455 | strdup(char *s) | |
45e93040 | 456 | { |
457 | return (xstrdup(s)); | |
458 | } | |
459 | #endif | |
460 | ||
b8d8561b | 461 | void |
462 | xmemcpy(void *from, void *to, int len) | |
090089c4 | 463 | { |
30a4f2a8 | 464 | #if HAVE_MEMMOVE |
465 | (void) memmove(from, to, len); | |
466 | #elif HAVE_BCOPY | |
467 | bcopy(to, from, len); | |
468 | #else | |
469 | (void) memcpy(from, to, len); | |
090089c4 | 470 | #endif |
30a4f2a8 | 471 | } |
673d7a4d | 472 | |
b8d8561b | 473 | void |
474 | Tolower(char *q) | |
673d7a4d | 475 | { |
476 | char *s = q; | |
477 | while (*s) { | |
b8d8561b | 478 | *s = tolower((unsigned char) *s); |
479 | s++; | |
673d7a4d | 480 | } |
481 | } |