]> git.ipfire.org Git - thirdparty/squid.git/blame - lib/util.c
gindent
[thirdparty/squid.git] / lib / util.c
CommitLineData
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 135void (*failure_notify) _PARAMS((const char *)) = NULL;
090089c4 136static char msg[128];
137
35570558 138extern 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)
145static int malloc_sizes[DBG_MAXINDEX + 1];
146static int dbg_stat_init = 0;
147
b8d8561b 148static void
0673c0ba 149stat_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 157static int
158malloc_stat(int sz)
30a4f2a8 159{
160 if (!dbg_stat_init)
161 stat_init();
162 return malloc_sizes[DBG_INDEX(sz)] += 1;
163}
164
b8d8561b 165void
5d3ec1a4 166malloc_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 179static void *malloc_ptrs[DBG_ARRY_BKTS][DBG_ARRY_SZ];
180static int malloc_size[DBG_ARRY_BKTS][DBG_ARRY_SZ];
45e93040 181static int dbg_initd = 0;
8c6551ac 182static int B = 0;
45e93040 183static int I = 0;
184static void *P;
185static void *Q;
186
b8d8561b 187static void
0673c0ba 188check_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 199static void
200check_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 216static void
217check_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 245int
246mallocblksize(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 258static void
259xmalloc_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 279void *
280xmalloc(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 311void
312xfree(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 325void
326xxfree(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 341void *
342xrealloc(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 378void *
379xcalloc(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 413char *
0ee4272b 414xstrdup(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 437const char *
0673c0ba 438xstrerror(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
451const char *
452xbstrerror(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 462void
463Tolower(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
472int
473tvSubMsec(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 479int
480tvSubUsec(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 */
490char *
491xstrncpy(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}