]>
Commit | Line | Data |
---|---|---|
30a4f2a8 | 1 | /* |
6a54c60e | 2 | * $Id: util.c,v 1.33 1997/10/20 22:59:42 wessels Exp $ |
30a4f2a8 | 3 | * |
4 | * DEBUG: | |
5 | * AUTHOR: Harvest Derived | |
6 | * | |
42c04c16 | 7 | * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ |
30a4f2a8 | 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 |
88738790 | 123 | #if HAVE_GNUMALLLOC_H |
124 | #include <gnumalloc.h> | |
125 | #elif HAVE_MALLOC_H && !defined(_SQUID_FREEBSD_) && !defined(_SQUID_NEXT_) | |
090089c4 | 126 | #include <malloc.h> |
983061ed | 127 | #endif |
30a4f2a8 | 128 | #if HAVE_ERRNO_H |
090089c4 | 129 | #include <errno.h> |
30a4f2a8 | 130 | #endif |
090089c4 | 131 | |
f606f345 | 132 | #include "ansiproto.h" |
473471f2 | 133 | #include "util.h" |
30a4f2a8 | 134 | |
0ee4272b | 135 | void (*failure_notify) _PARAMS((const char *)) = NULL; |
090089c4 | 136 | static char msg[128]; |
137 | ||
35570558 | 138 | extern int sys_nerr; |
35570558 | 139 | |
30a4f2a8 | 140 | #if XMALLOC_STATISTICS |
141 | #define DBG_MAXSIZE (1024*1024) | |
142 | #define DBG_GRAIN (16) | |
143 | #define DBG_MAXINDEX (DBG_MAXSIZE/DBG_GRAIN) | |
144 | #define DBG_INDEX(sz) (sz<DBG_MAXSIZE?(sz+DBG_GRAIN-1)/DBG_GRAIN:DBG_MAXINDEX) | |
145 | static int malloc_sizes[DBG_MAXINDEX + 1]; | |
146 | static int dbg_stat_init = 0; | |
147 | ||
b8d8561b | 148 | static void |
0673c0ba | 149 | stat_init(void) |
30a4f2a8 | 150 | { |
151 | int i; | |
152 | for (i = 0; i <= DBG_MAXINDEX; i++) | |
153 | malloc_sizes[i] = 0; | |
154 | dbg_stat_init = 1; | |
155 | } | |
156 | ||
b8d8561b | 157 | static int |
158 | malloc_stat(int sz) | |
30a4f2a8 | 159 | { |
160 | if (!dbg_stat_init) | |
161 | stat_init(); | |
162 | return malloc_sizes[DBG_INDEX(sz)] += 1; | |
163 | } | |
164 | ||
b8d8561b | 165 | void |
5d3ec1a4 | 166 | malloc_statistics(void (*func) (int, int, void *), void *data) |
30a4f2a8 | 167 | { |
168 | int i; | |
169 | for (i = 0; i <= DBG_MAXSIZE; i += DBG_GRAIN) | |
170 | func(i, malloc_sizes[DBG_INDEX(i)], data); | |
171 | } | |
172 | #endif /* XMALLOC_STATISTICS */ | |
173 | ||
090089c4 | 174 | |
45e93040 | 175 | |
1d012b4c | 176 | #if XMALLOC_DEBUG |
68b468e5 | 177 | #define DBG_ARRY_SZ (1<<10) |
178 | #define DBG_ARRY_BKTS (1<<8) | |
8c6551ac | 179 | static void *malloc_ptrs[DBG_ARRY_BKTS][DBG_ARRY_SZ]; |
180 | static int malloc_size[DBG_ARRY_BKTS][DBG_ARRY_SZ]; | |
45e93040 | 181 | static int dbg_initd = 0; |
8c6551ac | 182 | static int B = 0; |
45e93040 | 183 | static int I = 0; |
184 | static void *P; | |
185 | static void *Q; | |
186 | ||
b8d8561b | 187 | static void |
0673c0ba | 188 | check_init(void) |
45e93040 | 189 | { |
68b468e5 | 190 | for (B = 0; B < DBG_ARRY_BKTS; B++) { |
30a4f2a8 | 191 | for (I = 0; I < DBG_ARRY_SZ; I++) { |
192 | malloc_ptrs[B][I] = NULL; | |
193 | malloc_size[B][I] = 0; | |
194 | } | |
45e93040 | 195 | } |
196 | dbg_initd = 1; | |
197 | } | |
198 | ||
b8d8561b | 199 | static void |
200 | check_free(void *s) | |
45e93040 | 201 | { |
8c6551ac | 202 | B = (((int) s) >> 4) & 0xFF; |
45e93040 | 203 | for (I = 0; I < DBG_ARRY_SZ; I++) { |
8c6551ac | 204 | if (malloc_ptrs[B][I] != s) |
45e93040 | 205 | continue; |
8c6551ac | 206 | malloc_ptrs[B][I] = NULL; |
207 | malloc_size[B][I] = 0; | |
45e93040 | 208 | break; |
209 | } | |
210 | if (I == DBG_ARRY_SZ) { | |
211 | sprintf(msg, "xfree: ERROR: s=%p not found!", s); | |
212 | (*failure_notify) (msg); | |
213 | } | |
214 | } | |
215 | ||
b8d8561b | 216 | static void |
217 | check_malloc(void *p, size_t sz) | |
45e93040 | 218 | { |
219 | if (!dbg_initd) | |
220 | check_init(); | |
7fc9f088 | 221 | B = (((int) p) >> 4) & 0xFF; |
45e93040 | 222 | for (I = 0; I < DBG_ARRY_SZ; I++) { |
8c6551ac | 223 | if ((P = malloc_ptrs[B][I]) == NULL) |
45e93040 | 224 | continue; |
8c6551ac | 225 | Q = P + malloc_size[B][I]; |
45e93040 | 226 | if (P <= p && p < Q) { |
227 | sprintf(msg, "xmalloc: ERROR: p=%p falls in P=%p+%d", | |
8c6551ac | 228 | p, P, malloc_size[B][I]); |
45e93040 | 229 | (*failure_notify) (msg); |
230 | } | |
231 | } | |
232 | for (I = 0; I < DBG_ARRY_SZ; I++) { | |
8c6551ac | 233 | if ((P = malloc_ptrs[B][I])) |
45e93040 | 234 | continue; |
8c6551ac | 235 | malloc_ptrs[B][I] = p; |
236 | malloc_size[B][I] = (int) sz; | |
45e93040 | 237 | break; |
238 | } | |
239 | if (I == DBG_ARRY_SZ) | |
240 | (*failure_notify) ("xmalloc: debug out of array space!"); | |
241 | } | |
242 | #endif | |
243 | ||
7fc9f088 | 244 | #if XMALLOC_COUNT && !HAVE_MALLOCBLKSIZE |
b8d8561b | 245 | int |
246 | mallocblksize(void *p) | |
7fc9f088 | 247 | { |
248 | B = (((int) p) >> 4) & 0xFF; | |
249 | for (I = 0; I < DBG_ARRY_SZ; I++) { | |
250 | if (malloc_ptrs[B][I] == p) | |
251 | return malloc_size[B][I]; | |
252 | } | |
253 | return 0; | |
254 | } | |
255 | #endif | |
256 | ||
68b468e5 | 257 | #ifdef XMALLOC_COUNT |
b8d8561b | 258 | static void |
259 | xmalloc_count(void *p, int sign) | |
68b468e5 | 260 | { |
7fc9f088 | 261 | size_t sz; |
262 | static size_t total = 0; | |
263 | int memoryAccounted(); | |
264 | int mallinfoTotal(); | |
265 | sz = mallocblksize(p) * sign; | |
266 | total += sz; | |
267 | fprintf(stderr, "xmalloc_count=%9d accounted=%9d mallinfo=%9d\n", | |
268 | (int) total, | |
269 | memoryAccounted(), | |
270 | mallinfoTotal()); | |
68b468e5 | 271 | } |
b8d8561b | 272 | |
68b468e5 | 273 | #endif /* XMALLOC_COUNT */ |
274 | ||
090089c4 | 275 | /* |
276 | * xmalloc() - same as malloc(3). Used for portability. | |
277 | * Never returns NULL; fatal on error. | |
278 | */ | |
b8d8561b | 279 | void * |
280 | xmalloc(size_t sz) | |
090089c4 | 281 | { |
282 | static void *p; | |
283 | ||
284 | if (sz < 1) | |
285 | sz = 1; | |
286 | if ((p = malloc(sz)) == NULL) { | |
287 | if (failure_notify) { | |
288 | sprintf(msg, "xmalloc: Unable to allocate %d bytes!\n", | |
289 | (int) sz); | |
290 | (*failure_notify) (msg); | |
291 | } else { | |
292 | perror("malloc"); | |
293 | } | |
294 | exit(1); | |
295 | } | |
1d012b4c | 296 | #if XMALLOC_DEBUG |
45e93040 | 297 | check_malloc(p, sz); |
30a4f2a8 | 298 | #endif |
299 | #if XMALLOC_STATISTICS | |
300 | malloc_stat(sz); | |
68b468e5 | 301 | #endif |
302 | #if XMALLOC_COUNT | |
303 | xmalloc_count(p, 1); | |
45e93040 | 304 | #endif |
090089c4 | 305 | return (p); |
306 | } | |
307 | ||
308 | /* | |
309 | * xfree() - same as free(3). Will not call free(3) if s == NULL. | |
310 | */ | |
b8d8561b | 311 | void |
312 | xfree(void *s) | |
090089c4 | 313 | { |
68b468e5 | 314 | #if XMALLOC_COUNT |
315 | xmalloc_count(s, -1); | |
7fc9f088 | 316 | #endif |
317 | #if XMALLOC_DEBUG | |
318 | check_free(s); | |
45e93040 | 319 | #endif |
320 | if (s != NULL) | |
090089c4 | 321 | free(s); |
45e93040 | 322 | } |
323 | ||
324 | /* xxfree() - like xfree(), but we already know s != NULL */ | |
b8d8561b | 325 | void |
326 | xxfree(void *s) | |
45e93040 | 327 | { |
68b468e5 | 328 | #if XMALLOC_COUNT |
329 | xmalloc_count(s, -1); | |
7fc9f088 | 330 | #endif |
331 | #if XMALLOC_DEBUG | |
332 | check_free(s); | |
45e93040 | 333 | #endif |
334 | free(s); | |
090089c4 | 335 | } |
336 | ||
337 | /* | |
338 | * xrealloc() - same as realloc(3). Used for portability. | |
339 | * Never returns NULL; fatal on error. | |
340 | */ | |
b8d8561b | 341 | void * |
342 | xrealloc(void *s, size_t sz) | |
090089c4 | 343 | { |
344 | static void *p; | |
345 | ||
68b468e5 | 346 | #if XMALLOC_COUNT |
347 | xmalloc_count(s, -1); | |
348 | #endif | |
349 | ||
090089c4 | 350 | if (sz < 1) |
351 | sz = 1; | |
352 | if ((p = realloc(s, sz)) == NULL) { | |
353 | if (failure_notify) { | |
354 | sprintf(msg, "xrealloc: Unable to reallocate %d bytes!\n", | |
355 | (int) sz); | |
356 | (*failure_notify) (msg); | |
357 | } else { | |
358 | perror("realloc"); | |
359 | } | |
360 | exit(1); | |
361 | } | |
1d012b4c | 362 | #if XMALLOC_DEBUG |
45e93040 | 363 | check_malloc(p, sz); |
30a4f2a8 | 364 | #endif |
365 | #if XMALLOC_STATISTICS | |
366 | malloc_stat(sz); | |
68b468e5 | 367 | #endif |
368 | #if XMALLOC_COUNT | |
369 | xmalloc_count(p, 1); | |
45e93040 | 370 | #endif |
090089c4 | 371 | return (p); |
372 | } | |
373 | ||
374 | /* | |
375 | * xcalloc() - same as calloc(3). Used for portability. | |
376 | * Never returns NULL; fatal on error. | |
377 | */ | |
b8d8561b | 378 | void * |
379 | xcalloc(int n, size_t sz) | |
090089c4 | 380 | { |
381 | static void *p; | |
382 | ||
383 | if (n < 1) | |
384 | n = 1; | |
385 | if (sz < 1) | |
386 | sz = 1; | |
387 | if ((p = calloc(n, sz)) == NULL) { | |
388 | if (failure_notify) { | |
389 | sprintf(msg, "xcalloc: Unable to allocate %d blocks of %d bytes!\n", | |
390 | (int) n, (int) sz); | |
391 | (*failure_notify) (msg); | |
392 | } else { | |
393 | perror("xcalloc"); | |
394 | } | |
395 | exit(1); | |
396 | } | |
1d012b4c | 397 | #if XMALLOC_DEBUG |
45e93040 | 398 | check_malloc(p, sz * n); |
30a4f2a8 | 399 | #endif |
400 | #if XMALLOC_STATISTICS | |
401 | malloc_stat(sz); | |
68b468e5 | 402 | #endif |
403 | #if XMALLOC_COUNT | |
404 | xmalloc_count(p, 1); | |
45e93040 | 405 | #endif |
090089c4 | 406 | return (p); |
407 | } | |
408 | ||
409 | /* | |
410 | * xstrdup() - same as strdup(3). Used for portability. | |
411 | * Never returns NULL; fatal on error. | |
412 | */ | |
b8d8561b | 413 | char * |
0ee4272b | 414 | xstrdup(const char *s) |
090089c4 | 415 | { |
416 | static char *p = NULL; | |
30a4f2a8 | 417 | size_t sz; |
090089c4 | 418 | |
419 | if (s == NULL) { | |
420 | if (failure_notify) { | |
421 | (*failure_notify) ("xstrdup: tried to dup a NULL pointer!\n"); | |
422 | } else { | |
423 | fprintf(stderr, "xstrdup: tried to dup a NULL pointer!\n"); | |
424 | } | |
425 | exit(1); | |
426 | } | |
427 | sz = strlen(s); | |
30a4f2a8 | 428 | p = xmalloc((size_t) sz + 1); |
090089c4 | 429 | memcpy(p, s, sz); /* copy string */ |
430 | p[sz] = '\0'; /* terminate string */ | |
431 | return (p); | |
432 | } | |
433 | ||
090089c4 | 434 | /* |
4d38fc7e | 435 | * xstrerror() - strerror() wrapper |
090089c4 | 436 | */ |
0ee4272b | 437 | const char * |
0673c0ba | 438 | xstrerror(void) |
090089c4 | 439 | { |
35570558 | 440 | static char xstrerror_buf[BUFSIZ]; |
35570558 | 441 | if (errno < 0 || errno >= sys_nerr) |
090089c4 | 442 | return ("Unknown"); |
0f5efab0 | 443 | sprintf(xstrerror_buf, "(%d) %s", errno, strerror(errno)); |
35570558 | 444 | return xstrerror_buf; |
090089c4 | 445 | } |
446 | ||
d591088d | 447 | #if NOT_NEEDED |
75cf00f4 | 448 | /* |
449 | * xbstrerror with argument for late notification */ | |
450 | ||
451 | const char * | |
452 | xbstrerror(int err) | |
453 | { | |
454 | static char xbstrerror_buf[BUFSIZ]; | |
455 | if (err < 0 || err >= sys_nerr) | |
6a54c60e | 456 | return ("Unknown"); |
75cf00f4 | 457 | sprintf(xbstrerror_buf, "(%d) %s", err, strerror(err)); |
458 | return xbstrerror_buf; | |
459 | } | |
d591088d | 460 | #endif |
75cf00f4 | 461 | |
b8d8561b | 462 | void |
463 | Tolower(char *q) | |
673d7a4d | 464 | { |
465 | char *s = q; | |
466 | while (*s) { | |
b8d8561b | 467 | *s = tolower((unsigned char) *s); |
468 | s++; | |
673d7a4d | 469 | } |
470 | } | |
9d90e665 | 471 | |
472 | int | |
473 | tvSubMsec(struct timeval t1, struct timeval t2) | |
474 | { | |
475 | return (t2.tv_sec - t1.tv_sec) * 1000 + | |
6759a5fb | 476 | (t2.tv_usec - t1.tv_usec) / 1000; |
9d90e665 | 477 | } |
d5aa0e3b | 478 | |
88738790 | 479 | int |
480 | tvSubUsec(struct timeval t1, struct timeval t2) | |
481 | { | |
482 | return (t2.tv_sec - t1.tv_sec) * 1000000 + | |
483 | (t2.tv_usec - t1.tv_usec); | |
484 | } | |
485 | ||
d5aa0e3b | 486 | /* |
487 | * xstrncpy() - similar to strncpy(3) but terminates string | |
488 | * always with '\0' if n != 0, and doesn't do padding | |
489 | */ | |
490 | char * | |
491 | xstrncpy(char *dst, const char *src, size_t n) | |
492 | { | |
c1764328 | 493 | if (n == 0) |
494 | return dst; | |
495 | if (src == NULL) | |
496 | return dst; | |
497 | while (--n != 0 && *src != '\0') | |
498 | *dst++ = *src++; | |
499 | *dst = '\0'; | |
d5aa0e3b | 500 | return dst; |
501 | } |