]> git.ipfire.org Git - thirdparty/squid.git/blame - src/tools.cc
- Take Stewarts MONOTONIC_STORE patch, remove the #else code
[thirdparty/squid.git] / src / tools.cc
CommitLineData
94e891ea 1
30a4f2a8 2/*
e3ef2b09 3 * $Id: tools.cc,v 1.145 1998/02/03 22:08:20 wessels Exp $
30a4f2a8 4 *
5 * DEBUG: section 21 Misc Functions
6 * AUTHOR: Harvest Derived
7 *
42c04c16 8 * SQUID Internet Object Cache http://squid.nlanr.net/Squid/
30a4f2a8 9 * --------------------------------------------------------
10 *
11 * Squid is the result of efforts by numerous individuals from the
12 * Internet community. Development is led by Duane Wessels of the
13 * National Laboratory for Applied Network Research and funded by
14 * the National Science Foundation.
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 *
30 */
019dd986 31
32/*
30a4f2a8 33 * Copyright (c) 1994, 1995. All rights reserved.
34 *
35 * The Harvest software was developed by the Internet Research Task
36 * Force Research Group on Resource Discovery (IRTF-RD):
37 *
38 * Mic Bowman of Transarc Corporation.
39 * Peter Danzig of the University of Southern California.
40 * Darren R. Hardy of the University of Colorado at Boulder.
41 * Udi Manber of the University of Arizona.
42 * Michael F. Schwartz of the University of Colorado at Boulder.
43 * Duane Wessels of the University of Colorado at Boulder.
44 *
45 * This copyright notice applies to software in the Harvest
46 * ``src/'' directory only. Users should consult the individual
47 * copyright notices in the ``components/'' subdirectories for
48 * copyright information about other software bundled with the
49 * Harvest source code distribution.
50 *
51 * TERMS OF USE
52 *
53 * The Harvest software may be used and re-distributed without
54 * charge, provided that the software origin and research team are
55 * cited in any use of the system. Most commonly this is
56 * accomplished by including a link to the Harvest Home Page
57 * (http://harvest.cs.colorado.edu/) from the query page of any
58 * Broker you deploy, as well as in the query result pages. These
59 * links are generated automatically by the standard Broker
60 * software distribution.
61 *
62 * The Harvest software is provided ``as is'', without express or
63 * implied warranty, and with no support nor obligation to assist
64 * in its use, correction, modification or enhancement. We assume
65 * no liability with respect to the infringement of copyrights,
66 * trade secrets, or any patents, and are not responsible for
67 * consequential damages. Proper use of the Harvest software is
68 * entirely the responsibility of the user.
69 *
70 * DERIVATIVE WORKS
71 *
72 * Users may make derivative works from the Harvest software, subject
73 * to the following constraints:
74 *
75 * - You must include the above copyright notice and these
76 * accompanying paragraphs in all forms of derivative works,
77 * and any documentation and other materials related to such
78 * distribution and use acknowledge that the software was
79 * developed at the above institutions.
80 *
81 * - You must notify IRTF-RD regarding your distribution of
82 * the derivative work.
83 *
84 * - You must clearly notify users that your are distributing
85 * a modified version and not the original Harvest software.
86 *
87 * - Any derivative product is also subject to these copyright
88 * and use restrictions.
89 *
90 * Note that the Harvest software is NOT in the public domain. We
91 * retain copyright, as specified above.
92 *
93 * HISTORY OF FREE SOFTWARE STATUS
94 *
95 * Originally we required sites to license the software in cases
96 * where they were going to build commercial products/services
97 * around Harvest. In June 1995 we changed this policy. We now
98 * allow people to use the core Harvest software (the code found in
99 * the Harvest ``src/'' directory) for free. We made this change
100 * in the interest of encouraging the widest possible deployment of
101 * the technology. The Harvest software is really a reference
102 * implementation of a set of protocols and formats, some of which
103 * we intend to standardize. We encourage commercial
104 * re-implementations of code complying to this set of standards.
019dd986 105 */
44a47c6e 106
107#include "squid.h"
108
090089c4 109#define DEAD_MSG "\
c5c666ab 110The Squid Cache (version %s) died.\n\
090089c4 111\n\
c5c666ab 112You've encountered a fatal error in the Squid Cache version %s.\n\
090089c4 113If a core file was created (possibly in the swap directory),\n\
b8de7ebe 114please execute 'gdb squid core' or 'dbx squid core', then type 'where',\n\
234967c9 115and report the trace back to squid-bugs@nlanr.net.\n\
090089c4 116\n\
117Thanks!\n"
118
f5b8bbc4 119static void fatal_common(const char *);
120static void mail_warranty(void);
121static void shutdownTimeoutHandler(int fd, void *data);
0a0bf5db 122#if USE_ASYNC_IO
f5b8bbc4 123static void safeunlinkComplete(void *data, int retcode, int errcode);
0a0bf5db 124#endif
24382924 125
429fdbec 126static void
127releaseServerSockets(void)
128{
812ed90c 129 int i;
429fdbec 130 /* Release the main ports as early as possible */
812ed90c 131 for (i = 0; i < NHttpSockets; i++) {
132 if (HttpSockets[i] >= 0)
88738790 133 close(HttpSockets[i]);
812ed90c 134 }
429fdbec 135 if (theInIcpConnection >= 0)
88738790 136 close(theInIcpConnection);
429fdbec 137 if (theOutIcpConnection >= 0 && theOutIcpConnection != theInIcpConnection)
88738790 138 close(theOutIcpConnection);
429fdbec 139}
140
b8d8561b 141static char *
0673c0ba 142dead_msg(void)
090089c4 143{
95d659f0 144 LOCAL_ARRAY(char, msg, 1024);
56878878 145 snprintf(msg, 1024, DEAD_MSG, version_string, version_string);
090089c4 146 return msg;
147}
148
24382924 149static void
0673c0ba 150mail_warranty(void)
090089c4 151{
019dd986 152 FILE *fp = NULL;
6e40f263 153 char *filename;
154 static char command[256];
155 if ((filename = tempnam(NULL, appname)) == NULL)
156 return;
157 if ((fp = fopen(filename, "w")) == NULL)
158 return;
159 fprintf(fp, "From: %s\n", appname);
edae7bc0 160 fprintf(fp, "To: %s\n", Config.adminEmail);
6e40f263 161 fprintf(fp, "Subject: %s\n", dead_msg());
162 fclose(fp);
56878878 163 snprintf(command, 256, "mail %s < %s", Config.adminEmail, filename);
6e40f263 164 system(command); /* XXX should avoid system(3) */
165 unlink(filename);
090089c4 166}
167
b8d8561b 168static void
43c3424b 169dumpMallocStats(void)
3f43b19b 170{
88738790 171#if HAVE_MSTATS && HAVE_GNUMALLOC_H
172 struct mstats ms = mstats();
173 fprintf(debug_log, "\ttotal space in arena: %6d KB\n",
a97cfa48 174 (int) (ms.bytes_total >> 10));
88738790 175 fprintf(debug_log, "\tTotal free: %6d KB %d%%\n",
a97cfa48 176 (int) (ms.bytes_free >> 10),
88738790 177 percent(ms.bytes_free, ms.bytes_total));
178#elif HAVE_MALLINFO
3f43b19b 179 struct mallinfo mp;
30a4f2a8 180 int t;
3f43b19b 181 if (!do_mallinfo)
182 return;
3f43b19b 183 mp = mallinfo();
9e4ad609 184 fprintf(debug_log, "Memory usage for %s via mallinfo():\n", appname);
185 fprintf(debug_log, "\ttotal space in arena: %6d KB\n",
30a4f2a8 186 mp.arena >> 10);
9e4ad609 187 fprintf(debug_log, "\tOrdinary blocks: %6d KB %6d blks\n",
30a4f2a8 188 mp.uordblks >> 10, mp.ordblks);
9e4ad609 189 fprintf(debug_log, "\tSmall blocks: %6d KB %6d blks\n",
30a4f2a8 190 mp.usmblks >> 10, mp.smblks);
9e4ad609 191 fprintf(debug_log, "\tHolding blocks: %6d KB %6d blks\n",
30a4f2a8 192 mp.hblkhd >> 10, mp.hblks);
9e4ad609 193 fprintf(debug_log, "\tFree Small blocks: %6d KB\n",
30a4f2a8 194 mp.fsmblks >> 10);
9e4ad609 195 fprintf(debug_log, "\tFree Ordinary blocks: %6d KB\n",
30a4f2a8 196 mp.fordblks >> 10);
197 t = mp.uordblks + mp.usmblks + mp.hblkhd;
9e4ad609 198 fprintf(debug_log, "\tTotal in use: %6d KB %d%%\n",
30a4f2a8 199 t >> 10, percent(t, mp.arena));
200 t = mp.fsmblks + mp.fordblks;
9e4ad609 201 fprintf(debug_log, "\tTotal free: %6d KB %d%%\n",
30a4f2a8 202 t >> 10, percent(t, mp.arena));
46c883ed 203#if HAVE_EXT_MALLINFO
9e4ad609 204 fprintf(debug_log, "\tmax size of small blocks:\t%d\n",
30a4f2a8 205 mp.mxfast);
9e4ad609 206 fprintf(debug_log, "\tnumber of small blocks in a holding block:\t%d\n",
3f43b19b 207 mp.nlblks);
9e4ad609 208 fprintf(debug_log, "\tsmall block rounding factor:\t%d\n",
30a4f2a8 209 mp.grain);
9e4ad609 210 fprintf(debug_log, "\tspace (including overhead) allocated in ord. blks:\t%d\n",
3f43b19b 211 mp.uordbytes);
9e4ad609 212 fprintf(debug_log, "\tnumber of ordinary blocks allocated:\t%d\n",
3f43b19b 213 mp.allocated);
9e4ad609 214 fprintf(debug_log, "\tbytes used in maintaining the free tree:\t%d\n",
3f43b19b 215 mp.treeoverhead);
46c883ed 216#endif /* HAVE_EXT_MALLINFO */
3f43b19b 217#endif /* HAVE_MALLINFO */
218}
30a4f2a8 219
f2908497 220void
221squid_getrusage(struct rusage *r)
f0f81709 222{
8da94b66 223 memset(r, '\0', sizeof(struct rusage));
30a4f2a8 224#if HAVE_GETRUSAGE && defined(RUSAGE_SELF)
cd19f0b6 225#ifdef _SQUID_SOLARIS_
226 /* Solaris 2.5 has getrusage() permission bug -- Arjan de Vet */
227 enter_suid();
228#endif
f2908497 229 getrusage(RUSAGE_SELF, r);
cd19f0b6 230#ifdef _SQUID_SOLARIS_
231 leave_suid();
232#endif
56983a01 233#endif
f2908497 234}
235
236double
237rusage_cputime(struct rusage *r)
238{
239 return (double) r->ru_stime.tv_sec +
240 (double) r->ru_utime.tv_sec +
241 (double) r->ru_stime.tv_usec / 1000000.0 +
242 (double) r->ru_utime.tv_usec / 1000000.0;
243}
244
245int
246rusage_maxrss(struct rusage *r)
247{
248#if defined(_SQUID_SGI_)
249 return r->ru_maxrss;
250#elif defined(_SQUID_OSF_)
251 return r->ru_maxrss;
252#elif defined(BSD4_4)
253 return r->ru_maxrss;
8505e57b 254#elif HAVE_GETPAGESIZE
f2908497 255 return (r->ru_maxrss * getpagesize()) >> 10;
c7a1083d 256#elif defined(PAGESIZE)
257 return (r->ru_maxrss * PAGESIZE) >> 10;
8505e57b 258#else
259 return r->ru_maxrss;
f2908497 260#endif
261}
262
263int
264rusage_pagefaults(struct rusage *r)
265{
266 return r->ru_majflt;
267}
268
269
270static void
271PrintRusage(void)
272{
273 struct rusage rusage;
274 squid_getrusage(&rusage);
275 fprintf(debug_log, "CPU Usage: %.3f seconds\n", rusage_cputime(&rusage));
276 fprintf(debug_log, "Maximum Resident Size: %d KB\n",
277 rusage_maxrss(&rusage));
278 fprintf(debug_log, "Page faults with physical i/o: %d\n",
279 rusage_pagefaults(&rusage));
f0f81709 280}
281
03d7b07f 282
b8d8561b 283void
284death(int sig)
44a47c6e 285{
0e08ce4b 286 if (sig == SIGSEGV)
2c47cf74 287 fprintf(debug_log, "FATAL: Received Segment Violation...dying.\n");
0e08ce4b 288 else if (sig == SIGBUS)
6e40f263 289 fprintf(debug_log, "FATAL: Received Bus Error...dying.\n");
0e08ce4b 290 else
2c47cf74 291 fprintf(debug_log, "FATAL: Received signal %d...dying.\n", sig);
0b4639af 292
293#ifdef PRINT_STACK_TRACE
294#ifdef _SQUID_HPUX_
295 {
4f07153c 296 extern void U_STACK_TRACE(void); /* link with -lcl */
0b4639af 297 fflush(debug_log);
298 dup2(fileno(debug_log), 2);
299 U_STACK_TRACE();
300 }
301#endif /* _SQUID_HPUX_ */
302#ifdef _SQUID_SOLARIS_
4f07153c 303 { /* get ftp://opcom.sun.ca/pub/tars/opcom_stack.tar.gz and */
304 extern void opcom_stack_trace(void); /* link with -lopcom_stack */
0b4639af 305 fflush(debug_log);
306 dup2(fileno(debug_log), fileno(stdout));
307 opcom_stack_trace();
308 fflush(stdout);
309 }
310#endif /* _SQUID_SOLARIS_ */
311#endif /* PRINT_STACK_TRACE */
312
6e40f263 313#if SA_RESETHAND == 0
44a47c6e 314 signal(SIGSEGV, SIG_DFL);
315 signal(SIGBUS, SIG_DFL);
0e08ce4b 316 signal(sig, SIG_DFL);
30a4f2a8 317#endif
429fdbec 318 releaseServerSockets();
e3ef2b09 319 storeDirWriteCleanLogs(0);
9e4ad609 320 PrintRusage();
321 dumpMallocStats();
6e40f263 322 if (squid_curtime - SQUID_RELEASE_TIME < 864000) {
323 /* skip if more than 10 days old */
edae7bc0 324 if (Config.adminEmail)
6e40f263 325 mail_warranty();
326 else
327 puts(dead_msg());
328 }
44a47c6e 329 abort();
330}
331
332
b8d8561b 333void
23d92c64 334sigusr2_handle(int sig)
090089c4 335{
30a4f2a8 336 static int state = 0;
545f551a 337 /* no debug() here; bad things happen if the signal is delivered during _db_print() */
30a4f2a8 338 if (state == 0) {
b6f794d6 339 _db_init(Config.Log.log, "ALL,10");
30a4f2a8 340 state = 1;
341 } else {
b6f794d6 342 _db_init(Config.Log.log, Config.debugOptions);
30a4f2a8 343 state = 0;
344 }
345#if !HAVE_SIGACTION
346 signal(sig, sigusr2_handle); /* reinstall */
090089c4 347#endif
348}
349
5c5783a2 350static void
79d39a72 351shutdownTimeoutHandler(int fd, void *datanotused)
5c5783a2 352{
a3d5953d 353 debug(21, 1) ("Forcing close of FD %d\n", fd);
5c5783a2 354 comm_close(fd);
355}
356
b8d8561b 357void
5c5783a2 358setSocketShutdownLifetimes(int to)
30a4f2a8 359{
f1dc9b30 360 fde *f = NULL;
30a4f2a8 361 int i;
429fdbec 362 for (i = Biggest_FD; i >= 0; i--) {
4f92c80c 363 f = &fd_table[i];
364 if (!f->read_handler && !f->write_handler)
365 continue;
366 if (f->type != FD_SOCKET)
367 continue;
368 if (f->timeout > 0 && (int) (f->timeout - squid_curtime) <= to)
369 continue;
370 commSetTimeout(i,
371 to,
372 f->timeout_handler ? f->timeout_handler : shutdownTimeoutHandler,
373 f->timeout_data);
30a4f2a8 374 }
375}
376
b8d8561b 377void
0673c0ba 378normal_shutdown(void)
4d64d74a 379{
a3d5953d 380 debug(21, 1) ("Shutting down...\n");
0b4639af 381 if (Config.pidFilename && strcmp(Config.pidFilename, "none")) {
30a4f2a8 382 enter_suid();
b6f794d6 383 safeunlink(Config.pidFilename, 0);
30a4f2a8 384 leave_suid();
234967c9 385 }
429fdbec 386 releaseServerSockets();
6cf028ab 387#if !USE_ASYNC_IO
429fdbec 388 unlinkdClose();
6cf028ab 389#endif
e3ef2b09 390 storeDirWriteCleanLogs(0);
9e4ad609 391 PrintRusage();
392 dumpMallocStats();
e3ef2b09 393 storeLogClose();
a4394ebd 394 accessLogClose();
100fc710 395#if PURIFY
0a21bd84 396 configFreeMemory();
0a21bd84 397 storeFreeMemory();
0a21bd84 398 dnsFreeMemory();
399 redirectFreeMemory();
0a21bd84 400 stmemFreeMemory();
e5f6c5c2 401 netdbFreeMemory();
56e15c50 402 ipcacheFreeMemory();
403 fqdncacheFreeMemory();
f899fac1 404 asnFreeMemory();
100fc710 405#endif
9e4ad609 406 file_close(0);
407 file_close(1);
408 file_close(2);
409 fdDumpOpen();
410 fdFreeMemory();
a3d5953d 411 debug(21, 0) ("Squid Cache (Version %s): Exiting normally.\n",
0a21bd84 412 version_string);
c7433536 413 fclose(debug_log);
4d64d74a 414 exit(0);
415}
147d3115 416
24382924 417static void
0ee4272b 418fatal_common(const char *message)
090089c4 419{
db40ae20 420#if HAVE_SYSLOG
6e40f263 421 if (opt_syslog_enable)
233794cd 422 syslog(LOG_ALERT, "%s", message);
db40ae20 423#endif
2c47cf74 424 fprintf(debug_log, "FATAL: %s\n", message);
9e975e4e 425 if (opt_debug_stderr && debug_log != stderr)
a47b9029 426 fprintf(stderr, "FATAL: %s\n", message);
c5c666ab 427 fprintf(debug_log, "Squid Cache (Version %s): Terminated abnormally.\n",
8213067d 428 version_string);
2c47cf74 429 fflush(debug_log);
9e4ad609 430 PrintRusage();
431 dumpMallocStats();
090089c4 432}
433
434/* fatal */
b8d8561b 435void
0ee4272b 436fatal(const char *message)
090089c4 437{
429fdbec 438 releaseServerSockets();
d399be0e 439 /* check for store_rebuilding flag because fatal() is often
440 * used in early initialization phases, long before we ever
441 * get to the store log. */
442 if (!store_rebuilding)
e3ef2b09 443 storeDirWriteCleanLogs(0);
090089c4 444 fatal_common(message);
445 exit(1);
446}
447
448/* fatal with dumping core */
b8d8561b 449void
0ee4272b 450fatal_dump(const char *message)
090089c4 451{
429fdbec 452 releaseServerSockets();
090089c4 453 if (message)
454 fatal_common(message);
4a69c163 455 if (opt_catch_signals)
e3ef2b09 456 storeDirWriteCleanLogs(0);
090089c4 457 abort();
458}
459
b8d8561b 460void
a3d5953d 461debug_trap(const char *message)
85b701ed 462{
4a69c163 463 if (!opt_catch_signals)
85b701ed 464 fatal_dump(message);
a3d5953d 465 _db_print("WARNING: %s\n", message);
85b701ed 466}
467
b8d8561b 468void
23d92c64 469sig_child(int sig)
090089c4 470{
30a4f2a8 471#ifdef _SQUID_NEXT_
472 union wait status;
473#else
090089c4 474 int status;
090089c4 475#endif
ff8d0ea6 476 pid_t pid;
090089c4 477
30a4f2a8 478 do {
479#ifdef _SQUID_NEXT_
480 pid = wait3(&status, WNOHANG, NULL);
090089c4 481#else
30a4f2a8 482 pid = waitpid(-1, &status, WNOHANG);
090089c4 483#endif
97a88399 484 /* no debug() here; bad things happen if the signal is delivered during _db_print() */
30a4f2a8 485#if HAVE_SIGACTION
486 } while (pid > 0);
234967c9 487#else
30a4f2a8 488 } while (pid > 0 || (pid < 0 && errno == EINTR));
489 signal(sig, sig_child);
234967c9 490#endif
30a4f2a8 491}
44a47c6e 492
0ee4272b 493const char *
0673c0ba 494getMyHostname(void)
44a47c6e 495{
95d659f0 496 LOCAL_ARRAY(char, host, SQUIDHOSTNAMELEN + 1);
44a47c6e 497 static int present = 0;
0ee4272b 498 const struct hostent *h = NULL;
019dd986 499 char *t = NULL;
500
79d39a72 501 if ((t = Config.visibleHostname) != NULL)
019dd986 502 return t;
44a47c6e 503
504 /* Get the host name and store it in host to return */
505 if (!present) {
506 host[0] = '\0';
507 if (gethostname(host, SQUIDHOSTNAMELEN) == -1) {
a3d5953d 508 debug(50, 1) ("getMyHostname: gethostname failed: %s\n",
44a47c6e 509 xstrerror());
510 return NULL;
511 } else {
e5f6c5c2 512 if ((h = gethostbyname(host)) != NULL) {
44a47c6e 513 /* DNS lookup successful */
514 /* use the official name from DNS lookup */
515 strcpy(host, h->h_name);
516 }
517 present = 1;
518 }
519 }
520 return host;
521}
522
0a0bf5db 523void
0ee4272b 524safeunlink(const char *s, int quiet)
44a47c6e 525{
0a0bf5db 526#if USE_ASYNC_IO
527 aioUnlink(s,
528 quiet ? NULL : safeunlinkComplete,
529 quiet ? NULL : xstrdup(s));
530#else
531 if (unlink(s) < 0 && !quiet)
a3d5953d 532 debug(50, 1) ("safeunlink: Couldn't delete %s: %s\n", s, xstrerror());
0a0bf5db 533#endif
534}
535
536#if USE_ASYNC_IO
537static void
538safeunlinkComplete(void *data, int retcode, int errcode)
539{
540 char *s = data;
541 if (retcode < 0) {
542 errno = errcode;
a3d5953d 543 debug(50, 1) ("safeunlink: Couldn't delete %s. %s\n", s, xstrerror());
0a0bf5db 544 errno = 0;
545 }
546 xfree(s);
44a47c6e 547}
0a0bf5db 548#endif
12b9e9b1 549
30a4f2a8 550/* leave a privilegied section. (Give up any privilegies)
551 * Routines that need privilegies can rap themselves in enter_suid()
552 * and leave_suid()
553 * To give upp all posibilites to gain privilegies use no_suid()
12b9e9b1 554 */
b8d8561b 555void
0673c0ba 556leave_suid(void)
12b9e9b1 557{
558 struct passwd *pwd = NULL;
559 struct group *grp = NULL;
a3d5953d 560 debug(21, 3) ("leave_suid: PID %d called\n", getpid());
12b9e9b1 561 if (geteuid() != 0)
562 return;
563 /* Started as a root, check suid option */
b6f794d6 564 if (Config.effectiveUser == NULL)
12b9e9b1 565 return;
b6f794d6 566 if ((pwd = getpwnam(Config.effectiveUser)) == NULL)
12b9e9b1 567 return;
b6f794d6 568 if (Config.effectiveGroup && (grp = getgrnam(Config.effectiveGroup))) {
429fdbec 569 if (setgid(grp->gr_gid) < 0)
a3d5953d 570 debug(50, 1) ("leave_suid: setgid: %s\n", xstrerror());
12b9e9b1 571 } else {
429fdbec 572 if (setgid(pwd->pw_gid) < 0)
a3d5953d 573 debug(50, 1) ("leave_suid: setgid: %s\n", xstrerror());
12b9e9b1 574 }
a3d5953d 575 debug(21, 3) ("leave_suid: PID %d giving up root, becoming '%s'\n",
30a4f2a8 576 getpid(), pwd->pw_name);
234967c9 577#if HAVE_SETRESUID
429fdbec 578 if (setresuid(pwd->pw_uid, pwd->pw_uid, 0) < 0)
a3d5953d 579 debug(50, 1) ("leave_suid: setresuid: %s\n", xstrerror());
234967c9 580#elif HAVE_SETEUID
429fdbec 581 if (seteuid(pwd->pw_uid) < 0)
a3d5953d 582 debug(50, 1) ("leave_suid: seteuid: %s\n", xstrerror());
234967c9 583#else
429fdbec 584 if (setuid(pwd->pw_uid) < 0)
a3d5953d 585 debug(50, 1) ("leave_suid: setuid: %s\n", xstrerror());
234967c9 586#endif
587}
588
30a4f2a8 589/* Enter a privilegied section */
b8d8561b 590void
0673c0ba 591enter_suid(void)
234967c9 592{
a3d5953d 593 debug(21, 3) ("enter_suid: PID %d taking root priveleges\n", getpid());
234967c9 594#if HAVE_SETRESUID
595 setresuid(-1, 0, -1);
596#else
597 setuid(0);
598#endif
599}
600
30a4f2a8 601/* Give up the posibility to gain privilegies.
602 * this should be used before starting a sub process
603 */
b8d8561b 604void
0673c0ba 605no_suid(void)
234967c9 606{
607 uid_t uid;
30a4f2a8 608 leave_suid();
234967c9 609 uid = geteuid();
a3d5953d 610 debug(21, 3) ("leave_suid: PID %d giving up root priveleges forever\n", getpid());
234967c9 611#if HAVE_SETRESUID
429fdbec 612 if (setresuid(uid, uid, uid) < 0)
a3d5953d 613 debug(50, 1) ("no_suid: setresuid: %s\n", xstrerror());
234967c9 614#else
615 setuid(0);
429fdbec 616 if (setuid(uid) < 0)
a3d5953d 617 debug(50, 1) ("no_suid: setuid: %s\n", xstrerror());
234967c9 618#endif
12b9e9b1 619}
ccff9601 620
b8d8561b 621void
0673c0ba 622writePidFile(void)
ccff9601 623{
9e4ad609 624 int fd;
0b4639af 625 const char *f = NULL;
973e9fe1 626 mode_t old_umask;
9e4ad609 627 char buf[32];
628 if ((f = Config.pidFilename) == NULL)
629 return;
630 if (!strcmp(Config.pidFilename, "none"))
ccff9601 631 return;
30a4f2a8 632 enter_suid();
973e9fe1 633 old_umask = umask(022);
6cf028ab 634 fd = file_open(f, O_WRONLY | O_CREAT | O_TRUNC, NULL, NULL, NULL);
973e9fe1 635 umask(old_umask);
30a4f2a8 636 leave_suid();
9e4ad609 637 if (fd < 0) {
a3d5953d 638 debug(50, 0) ("%s: %s\n", f, xstrerror());
9e4ad609 639 debug_trap("Could not write pid file");
640 return;
ccff9601 641 }
56878878 642 snprintf(buf, 32, "%d\n", (int) getpid());
9e4ad609 643 write(fd, buf, strlen(buf));
644 file_close(fd);
ccff9601 645}
c4fb974e 646
647
ff8d0ea6 648pid_t
0673c0ba 649readPidFile(void)
7690e8eb 650{
651 FILE *pid_fp = NULL;
9e4ad609 652 const char *f = Config.pidFilename;
ff8d0ea6 653 pid_t pid = -1;
654 int i;
7690e8eb 655
9e4ad609 656 if (f == NULL || !strcmp(Config.pidFilename, "none")) {
7690e8eb 657 fprintf(stderr, "%s: ERROR: No pid file name defined\n", appname);
658 exit(1);
659 }
660 pid_fp = fopen(f, "r");
661 if (pid_fp != NULL) {
ff8d0ea6 662 pid = 0;
663 if (fscanf(pid_fp, "%d", &i) == 1)
664 pid = (pid_t) i;
7690e8eb 665 fclose(pid_fp);
666 } else {
667 if (errno != ENOENT) {
668 fprintf(stderr, "%s: ERROR: Could not read pid file\n", appname);
669 fprintf(stderr, "\t%s: %s\n", f, xstrerror());
670 exit(1);
671 }
672 }
673 return pid;
674}
675
676
b8d8561b 677void
0673c0ba 678setMaxFD(void)
c4fb974e 679{
234967c9 680#if HAVE_SETRLIMIT
c4fb974e 681 /* try to use as many file descriptors as possible */
682 /* System V uses RLIMIT_NOFILE and BSD uses RLIMIT_OFILE */
683 struct rlimit rl;
684#if defined(RLIMIT_NOFILE)
685 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
a3d5953d 686 debug(50, 0) ("setrlimit: RLIMIT_NOFILE: %s\n", xstrerror());
c4fb974e 687 } else {
e83892e9 688 rl.rlim_cur = Squid_MaxFD;
30a4f2a8 689 if (rl.rlim_cur > rl.rlim_max)
e83892e9 690 Squid_MaxFD = rl.rlim_cur = rl.rlim_max;
c4fb974e 691 if (setrlimit(RLIMIT_NOFILE, &rl) < 0) {
56878878 692 snprintf(tmp_error_buf, ERROR_BUF_SZ,
693 "setrlimit: RLIMIT_NOFILE: %s", xstrerror());
234967c9 694 fatal_dump(tmp_error_buf);
c4fb974e 695 }
696 }
697#elif defined(RLIMIT_OFILE)
698 if (getrlimit(RLIMIT_OFILE, &rl) < 0) {
a3d5953d 699 debug(50, 0) ("setrlimit: RLIMIT_NOFILE: %s\n", xstrerror());
c4fb974e 700 } else {
e83892e9 701 rl.rlim_cur = Squid_MaxFD;
30a4f2a8 702 if (rl.rlim_cur > rl.rlim_max)
e83892e9 703 Squid_MaxFD = rl.rlim_cur = rl.rlim_max;
c4fb974e 704 if (setrlimit(RLIMIT_OFILE, &rl) < 0) {
56878878 705 snprintf(tmp_error_buf, ERROR_BUF_SZ,
706 "setrlimit: RLIMIT_OFILE: %s", xstrerror());
234967c9 707 fatal_dump(tmp_error_buf);
c4fb974e 708 }
709 }
710#endif
c4fb974e 711#else /* HAVE_SETRLIMIT */
a3d5953d 712 debug(21, 1) ("setMaxFD: Cannot increase: setrlimit() not supported on this system\n");
30a4f2a8 713#endif /* HAVE_SETRLIMIT */
714
715#if HAVE_SETRLIMIT && defined(RLIMIT_DATA)
716 if (getrlimit(RLIMIT_DATA, &rl) < 0) {
a3d5953d 717 debug(50, 0) ("getrlimit: RLIMIT_DATA: %s\n", xstrerror());
88738790 718 } else if (rl.rlim_max > rl.rlim_cur) {
30a4f2a8 719 rl.rlim_cur = rl.rlim_max; /* set it to the max */
720 if (setrlimit(RLIMIT_DATA, &rl) < 0) {
56878878 721 snprintf(tmp_error_buf, ERROR_BUF_SZ,
722 "setrlimit: RLIMIT_DATA: %s", xstrerror());
30a4f2a8 723 fatal_dump(tmp_error_buf);
724 }
725 }
726#endif /* RLIMIT_DATA */
ad7ef91a 727#if HAVE_SETRLIMIT && defined(RLIMIT_VMEM)
728 if (getrlimit(RLIMIT_VMEM, &rl) < 0) {
a3d5953d 729 debug(50, 0) ("getrlimit: RLIMIT_VMEM: %s\n", xstrerror());
88738790 730 } else if (rl.rlim_max > rl.rlim_cur) {
ad7ef91a 731 rl.rlim_cur = rl.rlim_max; /* set it to the max */
732 if (setrlimit(RLIMIT_VMEM, &rl) < 0) {
56878878 733 snprintf(tmp_error_buf, ERROR_BUF_SZ,
734 "setrlimit: RLIMIT_VMEM: %s", xstrerror());
ad7ef91a 735 fatal_dump(tmp_error_buf);
736 }
737 }
738#endif /* RLIMIT_VMEM */
c4fb974e 739}
3a57089e 740
b8d8561b 741time_t
0673c0ba 742getCurrentTime(void)
3a57089e 743{
94e891ea 744#if GETTIMEOFDAY_NO_TZP
30a4f2a8 745 gettimeofday(&current_time);
746#else
d598947a 747 gettimeofday(&current_time, NULL);
5f3f8d0e 748#endif
30a4f2a8 749 return squid_curtime = current_time.tv_sec;
5f3f8d0e 750}
fe113054 751
b8d8561b 752int
753percent(int a, int b)
30a4f2a8 754{
755 return b ? ((int) (100.0 * a / b + 0.5)) : 0;
756}
757
a7c05555 758double
f2908497 759dpercent(double a, double b)
760{
761 return b ? (100.0 * a / b) : 0.0;
762}
763
b8d8561b 764void
ea3a2a69 765squid_signal(int sig, SIGHDLR * func, int flags)
30a4f2a8 766{
767#if HAVE_SIGACTION
768 struct sigaction sa;
769 sa.sa_handler = func;
770 sa.sa_flags = flags;
771 sigemptyset(&sa.sa_mask);
772 if (sigaction(sig, &sa, NULL) < 0)
a3d5953d 773 debug(50, 0) ("sigaction: sig=%d func=%p: %s\n", sig, func, xstrerror());
30a4f2a8 774#else
88738790 775 signal(sig, func);
30a4f2a8 776#endif
777}
396c5745 778
16b204c4 779struct in_addr
0ee4272b 780inaddrFromHostent(const struct hostent *hp)
16b204c4 781{
cc6a9d2e 782 struct in_addr s;
3c0117c9 783 xmemcpy(&s.s_addr, hp->h_addr, sizeof(s.s_addr));
cc6a9d2e 784 return s;
16b204c4 785}
88738790 786
9e4ad609 787double
1d8e0d40 788doubleAverage(double cur, double new, int N, int max)
9e4ad609 789{
1d8e0d40 790 if (N > max)
791 N = max;
792 return (cur * (N - 1.0) + new) / N;
9e4ad609 793}
794
795int
796intAverage(int cur, int new, int n, int max)
797{
798 if (n > max)
799 n = max;
b14e03c0 800 return (cur * (n - 1) + new) / n;
9e4ad609 801}
70364f29 802
803void
804logsFlush(void)
805{
806 if (debug_log)
807 fflush(debug_log);
808 if (cache_useragent_log)
809 fflush(cache_useragent_log);
810}
88738790 811
812char *
813checkNullString(char *p)
814{
815 return p ? p : "(NULL)";
816}
2ac237e2 817
818void
819dlinkAdd(void *data, dlink_node * m, dlink_list * list)
820{
821 m->data = data;
822 m->prev = NULL;
823 m->next = list->head;
824 if (list->head)
825 list->head->prev = m;
826 list->head = m;
827 if (list->tail == NULL)
828 list->tail = m;
829}
830
831void
832dlinkDelete(dlink_node * m, dlink_list * list)
833{
834 if (m->next)
835 m->next->prev = m->prev;
836 if (m->prev)
837 m->prev->next = m->next;
838 if (m == list->head)
839 list->head = m->next;
840 if (m == list->tail)
841 list->tail = m->prev;
842}
a7c05555 843
0e473d70 844void
845kb_incr(kb_t * k, size_t v)
a7c05555 846{
0e473d70 847 k->bytes += v;
848 k->kb += (k->bytes >> 10);
849 k->bytes &= 0x3FF;
a7c05555 850}