]> git.ipfire.org Git - thirdparty/squid.git/blame - src/tools.cc
Reamped objects being held in memory during transit. There will be a
[thirdparty/squid.git] / src / tools.cc
CommitLineData
94e891ea 1
30a4f2a8 2/*
03d7b07f 3 * $Id: tools.cc,v 1.122 1997/10/16 19:22:41 kostas 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
0ee4272b 119static void fatal_common _PARAMS((const char *));
24382924 120static void mail_warranty _PARAMS((void));
5c5783a2 121static void shutdownTimeoutHandler _PARAMS((int fd, void *data));
122
0a0bf5db 123#if USE_ASYNC_IO
124static void safeunlinkComplete _PARAMS((void *data, int retcode, int errcode));
125#endif
24382924 126
f8cde24f 127#ifdef _SQUID_SOLARIS_
128int getrusage _PARAMS((int, struct rusage *));
129int getpagesize _PARAMS((void));
130int gethostname _PARAMS((char *, int));
131#endif
132
429fdbec 133static void
134releaseServerSockets(void)
135{
812ed90c 136 int i;
429fdbec 137 /* Release the main ports as early as possible */
812ed90c 138 for (i = 0; i < NHttpSockets; i++) {
139 if (HttpSockets[i] >= 0)
88738790 140 close(HttpSockets[i]);
812ed90c 141 }
429fdbec 142 if (theInIcpConnection >= 0)
88738790 143 close(theInIcpConnection);
429fdbec 144 if (theOutIcpConnection >= 0 && theOutIcpConnection != theInIcpConnection)
88738790 145 close(theOutIcpConnection);
429fdbec 146}
147
b8d8561b 148static char *
0673c0ba 149dead_msg(void)
090089c4 150{
95d659f0 151 LOCAL_ARRAY(char, msg, 1024);
042461c3 152 snprintf(msg,1024, DEAD_MSG, version_string, version_string);
090089c4 153 return msg;
154}
155
24382924 156static void
0673c0ba 157mail_warranty(void)
090089c4 158{
019dd986 159 FILE *fp = NULL;
6e40f263 160 char *filename;
161 static char command[256];
162 if ((filename = tempnam(NULL, appname)) == NULL)
163 return;
164 if ((fp = fopen(filename, "w")) == NULL)
165 return;
166 fprintf(fp, "From: %s\n", appname);
edae7bc0 167 fprintf(fp, "To: %s\n", Config.adminEmail);
6e40f263 168 fprintf(fp, "Subject: %s\n", dead_msg());
169 fclose(fp);
042461c3 170 snprintf(command,256, "mail %s < %s", Config.adminEmail, filename);
6e40f263 171 system(command); /* XXX should avoid system(3) */
172 unlink(filename);
090089c4 173}
174
b8d8561b 175static void
43c3424b 176dumpMallocStats(void)
3f43b19b 177{
88738790 178#if HAVE_MSTATS && HAVE_GNUMALLOC_H
179 struct mstats ms = mstats();
180 fprintf(debug_log, "\ttotal space in arena: %6d KB\n",
181 ms.bytes_total >> 10);
182 fprintf(debug_log, "\tTotal free: %6d KB %d%%\n",
183 ms.bytes_free >> 10,
184 percent(ms.bytes_free, ms.bytes_total));
185#elif HAVE_MALLINFO
3f43b19b 186 struct mallinfo mp;
30a4f2a8 187 int t;
3f43b19b 188 if (!do_mallinfo)
189 return;
3f43b19b 190 mp = mallinfo();
9e4ad609 191 fprintf(debug_log, "Memory usage for %s via mallinfo():\n", appname);
192 fprintf(debug_log, "\ttotal space in arena: %6d KB\n",
30a4f2a8 193 mp.arena >> 10);
9e4ad609 194 fprintf(debug_log, "\tOrdinary blocks: %6d KB %6d blks\n",
30a4f2a8 195 mp.uordblks >> 10, mp.ordblks);
9e4ad609 196 fprintf(debug_log, "\tSmall blocks: %6d KB %6d blks\n",
30a4f2a8 197 mp.usmblks >> 10, mp.smblks);
9e4ad609 198 fprintf(debug_log, "\tHolding blocks: %6d KB %6d blks\n",
30a4f2a8 199 mp.hblkhd >> 10, mp.hblks);
9e4ad609 200 fprintf(debug_log, "\tFree Small blocks: %6d KB\n",
30a4f2a8 201 mp.fsmblks >> 10);
9e4ad609 202 fprintf(debug_log, "\tFree Ordinary blocks: %6d KB\n",
30a4f2a8 203 mp.fordblks >> 10);
204 t = mp.uordblks + mp.usmblks + mp.hblkhd;
9e4ad609 205 fprintf(debug_log, "\tTotal in use: %6d KB %d%%\n",
30a4f2a8 206 t >> 10, percent(t, mp.arena));
207 t = mp.fsmblks + mp.fordblks;
9e4ad609 208 fprintf(debug_log, "\tTotal free: %6d KB %d%%\n",
30a4f2a8 209 t >> 10, percent(t, mp.arena));
46c883ed 210#if HAVE_EXT_MALLINFO
9e4ad609 211 fprintf(debug_log, "\tmax size of small blocks:\t%d\n",
30a4f2a8 212 mp.mxfast);
9e4ad609 213 fprintf(debug_log, "\tnumber of small blocks in a holding block:\t%d\n",
3f43b19b 214 mp.nlblks);
9e4ad609 215 fprintf(debug_log, "\tsmall block rounding factor:\t%d\n",
30a4f2a8 216 mp.grain);
9e4ad609 217 fprintf(debug_log, "\tspace (including overhead) allocated in ord. blks:\t%d\n",
3f43b19b 218 mp.uordbytes);
9e4ad609 219 fprintf(debug_log, "\tnumber of ordinary blocks allocated:\t%d\n",
3f43b19b 220 mp.allocated);
9e4ad609 221 fprintf(debug_log, "\tbytes used in maintaining the free tree:\t%d\n",
3f43b19b 222 mp.treeoverhead);
46c883ed 223#endif /* HAVE_EXT_MALLINFO */
3f43b19b 224#endif /* HAVE_MALLINFO */
225}
30a4f2a8 226
9e4ad609 227static void
228PrintRusage(void)
f0f81709 229{
30a4f2a8 230#if HAVE_GETRUSAGE && defined(RUSAGE_SELF)
f0f81709 231 struct rusage rusage;
cd19f0b6 232#ifdef _SQUID_SOLARIS_
233 /* Solaris 2.5 has getrusage() permission bug -- Arjan de Vet */
234 enter_suid();
235#endif
f0f81709 236 getrusage(RUSAGE_SELF, &rusage);
cd19f0b6 237#ifdef _SQUID_SOLARIS_
238 leave_suid();
239#endif
9e4ad609 240 fprintf(debug_log, "CPU Usage: user %d sys %d\n",
30a4f2a8 241 (int) rusage.ru_utime.tv_sec, (int) rusage.ru_stime.tv_sec);
1fe4a4e1 242#if defined(_SQUID_SGI_) || defined(_SQUID_OSF_) || defined(BSD4_4)
9e4ad609 243 fprintf(debug_log, "Maximum Resident Size: %ld KB\n", rusage.ru_maxrss);
6fb52f6c 244#else /* _SQUID_SGI_ */
9e4ad609 245 fprintf(debug_log, "Maximum Resident Size: %ld KB\n",
2aea66ad 246 (rusage.ru_maxrss * getpagesize()) >> 10);
247#endif /* _SQUID_SGI_ */
9e4ad609 248 fprintf(debug_log, "Page faults with physical i/o: %ld\n",
f0f81709 249 rusage.ru_majflt);
2aea66ad 250#endif /* HAVE_GETRUSAGE */
f0f81709 251}
252
03d7b07f 253
b8d8561b 254void
255death(int sig)
44a47c6e 256{
0e08ce4b 257 if (sig == SIGSEGV)
2c47cf74 258 fprintf(debug_log, "FATAL: Received Segment Violation...dying.\n");
0e08ce4b 259 else if (sig == SIGBUS)
6e40f263 260 fprintf(debug_log, "FATAL: Received Bus Error...dying.\n");
0e08ce4b 261 else
2c47cf74 262 fprintf(debug_log, "FATAL: Received signal %d...dying.\n", sig);
0b4639af 263
264#ifdef PRINT_STACK_TRACE
265#ifdef _SQUID_HPUX_
266 {
4f07153c 267 extern void U_STACK_TRACE(void); /* link with -lcl */
0b4639af 268 fflush(debug_log);
269 dup2(fileno(debug_log), 2);
270 U_STACK_TRACE();
271 }
272#endif /* _SQUID_HPUX_ */
273#ifdef _SQUID_SOLARIS_
4f07153c 274 { /* get ftp://opcom.sun.ca/pub/tars/opcom_stack.tar.gz and */
275 extern void opcom_stack_trace(void); /* link with -lopcom_stack */
0b4639af 276 fflush(debug_log);
277 dup2(fileno(debug_log), fileno(stdout));
278 opcom_stack_trace();
279 fflush(stdout);
280 }
281#endif /* _SQUID_SOLARIS_ */
282#endif /* PRINT_STACK_TRACE */
283
6e40f263 284#if SA_RESETHAND == 0
44a47c6e 285 signal(SIGSEGV, SIG_DFL);
286 signal(SIGBUS, SIG_DFL);
0e08ce4b 287 signal(sig, SIG_DFL);
30a4f2a8 288#endif
429fdbec 289 releaseServerSockets();
e102ebda 290 storeWriteCleanLogs(0);
9e4ad609 291 PrintRusage();
292 dumpMallocStats();
6e40f263 293 if (squid_curtime - SQUID_RELEASE_TIME < 864000) {
294 /* skip if more than 10 days old */
edae7bc0 295 if (Config.adminEmail)
6e40f263 296 mail_warranty();
297 else
298 puts(dead_msg());
299 }
44a47c6e 300 abort();
301}
302
303
b8d8561b 304void
305sigusr2_handle(int sig)
090089c4 306{
30a4f2a8 307 static int state = 0;
545f551a 308 /* no debug() here; bad things happen if the signal is delivered during _db_print() */
30a4f2a8 309 if (state == 0) {
b6f794d6 310 _db_init(Config.Log.log, "ALL,10");
30a4f2a8 311 state = 1;
312 } else {
b6f794d6 313 _db_init(Config.Log.log, Config.debugOptions);
30a4f2a8 314 state = 0;
315 }
316#if !HAVE_SIGACTION
317 signal(sig, sigusr2_handle); /* reinstall */
090089c4 318#endif
319}
320
5c5783a2 321static void
322shutdownTimeoutHandler(int fd, void *data)
323{
a3d5953d 324 debug(21, 1) ("Forcing close of FD %d\n", fd);
5c5783a2 325 comm_close(fd);
326}
327
b8d8561b 328void
5c5783a2 329setSocketShutdownLifetimes(int to)
30a4f2a8 330{
f1dc9b30 331 fde *f = NULL;
30a4f2a8 332 int i;
429fdbec 333 for (i = Biggest_FD; i >= 0; i--) {
4f92c80c 334 f = &fd_table[i];
335 if (!f->read_handler && !f->write_handler)
336 continue;
337 if (f->type != FD_SOCKET)
338 continue;
339 if (f->timeout > 0 && (int) (f->timeout - squid_curtime) <= to)
340 continue;
341 commSetTimeout(i,
342 to,
343 f->timeout_handler ? f->timeout_handler : shutdownTimeoutHandler,
344 f->timeout_data);
30a4f2a8 345 }
346}
347
b8d8561b 348void
0673c0ba 349normal_shutdown(void)
4d64d74a 350{
a3d5953d 351 debug(21, 1) ("Shutting down...\n");
0b4639af 352 if (Config.pidFilename && strcmp(Config.pidFilename, "none")) {
30a4f2a8 353 enter_suid();
b6f794d6 354 safeunlink(Config.pidFilename, 0);
30a4f2a8 355 leave_suid();
234967c9 356 }
429fdbec 357 releaseServerSockets();
358 unlinkdClose();
e102ebda 359 storeWriteCleanLogs(0);
9e4ad609 360 PrintRusage();
361 dumpMallocStats();
457bedbd 362 storeCloseLog();
a4394ebd 363 accessLogClose();
100fc710 364#if PURIFY
0a21bd84 365 configFreeMemory();
0a21bd84 366 storeFreeMemory();
0a21bd84 367 dnsFreeMemory();
368 redirectFreeMemory();
0a21bd84 369 errorpageFreeMemory();
370 stmemFreeMemory();
e5f6c5c2 371 netdbFreeMemory();
56e15c50 372 ipcacheFreeMemory();
373 fqdncacheFreeMemory();
100fc710 374#endif
9e4ad609 375 file_close(0);
376 file_close(1);
377 file_close(2);
378 fdDumpOpen();
379 fdFreeMemory();
a3d5953d 380 debug(21, 0) ("Squid Cache (Version %s): Exiting normally.\n",
0a21bd84 381 version_string);
c7433536 382 fclose(debug_log);
4d64d74a 383 exit(0);
384}
147d3115 385
24382924 386static void
0ee4272b 387fatal_common(const char *message)
090089c4 388{
db40ae20 389#if HAVE_SYSLOG
6e40f263 390 if (opt_syslog_enable)
233794cd 391 syslog(LOG_ALERT, "%s", message);
db40ae20 392#endif
2c47cf74 393 fprintf(debug_log, "FATAL: %s\n", message);
9e975e4e 394 if (opt_debug_stderr && debug_log != stderr)
a47b9029 395 fprintf(stderr, "FATAL: %s\n", message);
c5c666ab 396 fprintf(debug_log, "Squid Cache (Version %s): Terminated abnormally.\n",
8213067d 397 version_string);
2c47cf74 398 fflush(debug_log);
9e4ad609 399 PrintRusage();
400 dumpMallocStats();
090089c4 401}
402
403/* fatal */
b8d8561b 404void
0ee4272b 405fatal(const char *message)
090089c4 406{
429fdbec 407 releaseServerSockets();
d399be0e 408 /* check for store_rebuilding flag because fatal() is often
409 * used in early initialization phases, long before we ever
410 * get to the store log. */
411 if (!store_rebuilding)
e102ebda 412 storeWriteCleanLogs(0);
090089c4 413 fatal_common(message);
414 exit(1);
415}
416
417/* fatal with dumping core */
b8d8561b 418void
0ee4272b 419fatal_dump(const char *message)
090089c4 420{
429fdbec 421 releaseServerSockets();
090089c4 422 if (message)
423 fatal_common(message);
4a69c163 424 if (opt_catch_signals)
e102ebda 425 storeWriteCleanLogs(0);
090089c4 426 abort();
427}
428
b8d8561b 429void
a3d5953d 430debug_trap(const char *message)
85b701ed 431{
4a69c163 432 if (!opt_catch_signals)
85b701ed 433 fatal_dump(message);
a3d5953d 434 _db_level = 0;
435 _db_print("WARNING: %s\n", message);
85b701ed 436}
437
b8d8561b 438void
439sig_child(int sig)
090089c4 440{
30a4f2a8 441#ifdef _SQUID_NEXT_
442 union wait status;
443#else
090089c4 444 int status;
090089c4 445#endif
ff8d0ea6 446 pid_t pid;
090089c4 447
30a4f2a8 448 do {
449#ifdef _SQUID_NEXT_
450 pid = wait3(&status, WNOHANG, NULL);
090089c4 451#else
30a4f2a8 452 pid = waitpid(-1, &status, WNOHANG);
090089c4 453#endif
97a88399 454 /* no debug() here; bad things happen if the signal is delivered during _db_print() */
30a4f2a8 455#if HAVE_SIGACTION
456 } while (pid > 0);
234967c9 457#else
30a4f2a8 458 } while (pid > 0 || (pid < 0 && errno == EINTR));
459 signal(sig, sig_child);
234967c9 460#endif
30a4f2a8 461}
44a47c6e 462
0ee4272b 463const char *
0673c0ba 464getMyHostname(void)
44a47c6e 465{
95d659f0 466 LOCAL_ARRAY(char, host, SQUIDHOSTNAMELEN + 1);
44a47c6e 467 static int present = 0;
0ee4272b 468 const struct hostent *h = NULL;
019dd986 469 char *t = NULL;
470
b6f794d6 471 if ((t = Config.visibleHostname))
019dd986 472 return t;
44a47c6e 473
474 /* Get the host name and store it in host to return */
475 if (!present) {
476 host[0] = '\0';
477 if (gethostname(host, SQUIDHOSTNAMELEN) == -1) {
a3d5953d 478 debug(50, 1) ("getMyHostname: gethostname failed: %s\n",
44a47c6e 479 xstrerror());
480 return NULL;
481 } else {
e5f6c5c2 482 if ((h = gethostbyname(host)) != NULL) {
44a47c6e 483 /* DNS lookup successful */
484 /* use the official name from DNS lookup */
485 strcpy(host, h->h_name);
486 }
487 present = 1;
488 }
489 }
490 return host;
491}
492
0a0bf5db 493void
0ee4272b 494safeunlink(const char *s, int quiet)
44a47c6e 495{
0a0bf5db 496#if USE_ASYNC_IO
497 aioUnlink(s,
498 quiet ? NULL : safeunlinkComplete,
499 quiet ? NULL : xstrdup(s));
500#else
501 if (unlink(s) < 0 && !quiet)
a3d5953d 502 debug(50, 1) ("safeunlink: Couldn't delete %s: %s\n", s, xstrerror());
0a0bf5db 503#endif
504}
505
506#if USE_ASYNC_IO
507static void
508safeunlinkComplete(void *data, int retcode, int errcode)
509{
510 char *s = data;
511 if (retcode < 0) {
512 errno = errcode;
a3d5953d 513 debug(50, 1) ("safeunlink: Couldn't delete %s. %s\n", s, xstrerror());
0a0bf5db 514 errno = 0;
515 }
516 xfree(s);
44a47c6e 517}
0a0bf5db 518#endif
12b9e9b1 519
30a4f2a8 520/* leave a privilegied section. (Give up any privilegies)
521 * Routines that need privilegies can rap themselves in enter_suid()
522 * and leave_suid()
523 * To give upp all posibilites to gain privilegies use no_suid()
12b9e9b1 524 */
b8d8561b 525void
0673c0ba 526leave_suid(void)
12b9e9b1 527{
528 struct passwd *pwd = NULL;
529 struct group *grp = NULL;
a3d5953d 530 debug(21, 3) ("leave_suid: PID %d called\n", getpid());
12b9e9b1 531 if (geteuid() != 0)
532 return;
533 /* Started as a root, check suid option */
b6f794d6 534 if (Config.effectiveUser == NULL)
12b9e9b1 535 return;
b6f794d6 536 if ((pwd = getpwnam(Config.effectiveUser)) == NULL)
12b9e9b1 537 return;
b6f794d6 538 if (Config.effectiveGroup && (grp = getgrnam(Config.effectiveGroup))) {
429fdbec 539 if (setgid(grp->gr_gid) < 0)
a3d5953d 540 debug(50, 1) ("leave_suid: setgid: %s\n", xstrerror());
12b9e9b1 541 } else {
429fdbec 542 if (setgid(pwd->pw_gid) < 0)
a3d5953d 543 debug(50, 1) ("leave_suid: setgid: %s\n", xstrerror());
12b9e9b1 544 }
a3d5953d 545 debug(21, 3) ("leave_suid: PID %d giving up root, becoming '%s'\n",
30a4f2a8 546 getpid(), pwd->pw_name);
234967c9 547#if HAVE_SETRESUID
429fdbec 548 if (setresuid(pwd->pw_uid, pwd->pw_uid, 0) < 0)
a3d5953d 549 debug(50, 1) ("leave_suid: setresuid: %s\n", xstrerror());
234967c9 550#elif HAVE_SETEUID
429fdbec 551 if (seteuid(pwd->pw_uid) < 0)
a3d5953d 552 debug(50, 1) ("leave_suid: seteuid: %s\n", xstrerror());
234967c9 553#else
429fdbec 554 if (setuid(pwd->pw_uid) < 0)
a3d5953d 555 debug(50, 1) ("leave_suid: setuid: %s\n", xstrerror());
234967c9 556#endif
557}
558
30a4f2a8 559/* Enter a privilegied section */
b8d8561b 560void
0673c0ba 561enter_suid(void)
234967c9 562{
a3d5953d 563 debug(21, 3) ("enter_suid: PID %d taking root priveleges\n", getpid());
234967c9 564#if HAVE_SETRESUID
565 setresuid(-1, 0, -1);
566#else
567 setuid(0);
568#endif
569}
570
30a4f2a8 571/* Give up the posibility to gain privilegies.
572 * this should be used before starting a sub process
573 */
b8d8561b 574void
0673c0ba 575no_suid(void)
234967c9 576{
577 uid_t uid;
30a4f2a8 578 leave_suid();
234967c9 579 uid = geteuid();
a3d5953d 580 debug(21, 3) ("leave_suid: PID %d giving up root priveleges forever\n", getpid());
234967c9 581#if HAVE_SETRESUID
429fdbec 582 if (setresuid(uid, uid, uid) < 0)
a3d5953d 583 debug(50, 1) ("no_suid: setresuid: %s\n", xstrerror());
234967c9 584#else
585 setuid(0);
429fdbec 586 if (setuid(uid) < 0)
a3d5953d 587 debug(50, 1) ("no_suid: setuid: %s\n", xstrerror());
234967c9 588#endif
12b9e9b1 589}
ccff9601 590
b8d8561b 591void
0673c0ba 592writePidFile(void)
ccff9601 593{
9e4ad609 594 int fd;
0b4639af 595 const char *f = NULL;
973e9fe1 596 mode_t old_umask;
9e4ad609 597 char buf[32];
598 if ((f = Config.pidFilename) == NULL)
599 return;
600 if (!strcmp(Config.pidFilename, "none"))
ccff9601 601 return;
30a4f2a8 602 enter_suid();
973e9fe1 603 old_umask = umask(022);
9e4ad609 604 fd = file_open(f, O_WRONLY | O_CREAT | O_TRUNC, NULL, NULL);
973e9fe1 605 umask(old_umask);
30a4f2a8 606 leave_suid();
9e4ad609 607 if (fd < 0) {
a3d5953d 608 debug(50, 0) ("%s: %s\n", f, xstrerror());
9e4ad609 609 debug_trap("Could not write pid file");
610 return;
ccff9601 611 }
042461c3 612 snprintf(buf,32, "%d\n", (int) getpid());
9e4ad609 613 write(fd, buf, strlen(buf));
614 file_close(fd);
ccff9601 615}
c4fb974e 616
617
ff8d0ea6 618pid_t
0673c0ba 619readPidFile(void)
7690e8eb 620{
621 FILE *pid_fp = NULL;
9e4ad609 622 const char *f = Config.pidFilename;
ff8d0ea6 623 pid_t pid = -1;
624 int i;
7690e8eb 625
9e4ad609 626 if (f == NULL || !strcmp(Config.pidFilename, "none")) {
7690e8eb 627 fprintf(stderr, "%s: ERROR: No pid file name defined\n", appname);
628 exit(1);
629 }
630 pid_fp = fopen(f, "r");
631 if (pid_fp != NULL) {
ff8d0ea6 632 pid = 0;
633 if (fscanf(pid_fp, "%d", &i) == 1)
634 pid = (pid_t) i;
7690e8eb 635 fclose(pid_fp);
636 } else {
637 if (errno != ENOENT) {
638 fprintf(stderr, "%s: ERROR: Could not read pid file\n", appname);
639 fprintf(stderr, "\t%s: %s\n", f, xstrerror());
640 exit(1);
641 }
642 }
643 return pid;
644}
645
646
b8d8561b 647void
0673c0ba 648setMaxFD(void)
c4fb974e 649{
234967c9 650#if HAVE_SETRLIMIT
c4fb974e 651 /* try to use as many file descriptors as possible */
652 /* System V uses RLIMIT_NOFILE and BSD uses RLIMIT_OFILE */
653 struct rlimit rl;
654#if defined(RLIMIT_NOFILE)
655 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
a3d5953d 656 debug(50, 0) ("setrlimit: RLIMIT_NOFILE: %s\n", xstrerror());
c4fb974e 657 } else {
e83892e9 658 rl.rlim_cur = Squid_MaxFD;
30a4f2a8 659 if (rl.rlim_cur > rl.rlim_max)
e83892e9 660 Squid_MaxFD = rl.rlim_cur = rl.rlim_max;
c4fb974e 661 if (setrlimit(RLIMIT_NOFILE, &rl) < 0) {
03d7b07f 662 /* NOTE: couldn't figure size of tmp_error_buf, thus
663 assuming ERROR_BUF_SZ */
664 snprintf(tmp_error_buf, ERROR_BUF_SZ,
665 "setrlimit: RLIMIT_NOFILE: %s", xstrerror());
234967c9 666 fatal_dump(tmp_error_buf);
c4fb974e 667 }
668 }
669#elif defined(RLIMIT_OFILE)
670 if (getrlimit(RLIMIT_OFILE, &rl) < 0) {
a3d5953d 671 debug(50, 0) ("setrlimit: RLIMIT_NOFILE: %s\n", xstrerror());
c4fb974e 672 } else {
e83892e9 673 rl.rlim_cur = Squid_MaxFD;
30a4f2a8 674 if (rl.rlim_cur > rl.rlim_max)
e83892e9 675 Squid_MaxFD = rl.rlim_cur = rl.rlim_max;
c4fb974e 676 if (setrlimit(RLIMIT_OFILE, &rl) < 0) {
03d7b07f 677 /* NOTE: couldn't figure size of tmp_error_buf, thus
678 assuming ERROR_BUF_SZ */
679 snprintf(tmp_error_buf, ERROR_BUF_SZ,
680 "setrlimit: RLIMIT_OFILE: %s", xstrerror());
234967c9 681 fatal_dump(tmp_error_buf);
c4fb974e 682 }
683 }
684#endif
c4fb974e 685#else /* HAVE_SETRLIMIT */
a3d5953d 686 debug(21, 1) ("setMaxFD: Cannot increase: setrlimit() not supported on this system\n");
30a4f2a8 687#endif /* HAVE_SETRLIMIT */
688
689#if HAVE_SETRLIMIT && defined(RLIMIT_DATA)
690 if (getrlimit(RLIMIT_DATA, &rl) < 0) {
a3d5953d 691 debug(50, 0) ("getrlimit: RLIMIT_DATA: %s\n", xstrerror());
88738790 692 } else if (rl.rlim_max > rl.rlim_cur) {
30a4f2a8 693 rl.rlim_cur = rl.rlim_max; /* set it to the max */
694 if (setrlimit(RLIMIT_DATA, &rl) < 0) {
03d7b07f 695 /* NOTE: couldn't figure size of tmp_error_buf, thus d
696 assuming ERROR_BUF_SZ */
697 snprintf(tmp_error_buf, ERROR_BUF_SZ,
698 "setrlimit: RLIMIT_DATA: %s", xstrerror());
30a4f2a8 699 fatal_dump(tmp_error_buf);
700 }
701 }
702#endif /* RLIMIT_DATA */
ad7ef91a 703#if HAVE_SETRLIMIT && defined(RLIMIT_VMEM)
704 if (getrlimit(RLIMIT_VMEM, &rl) < 0) {
a3d5953d 705 debug(50, 0) ("getrlimit: RLIMIT_VMEM: %s\n", xstrerror());
88738790 706 } else if (rl.rlim_max > rl.rlim_cur) {
ad7ef91a 707 rl.rlim_cur = rl.rlim_max; /* set it to the max */
708 if (setrlimit(RLIMIT_VMEM, &rl) < 0) {
03d7b07f 709 /* NOTE: couldn't figure size of tmp_error_buf, thus
710 assuming ERROR_BUF_SZ */
711 snprintf(tmp_error_buf, ERROR_BUF_SZ,
712 "setrlimit: RLIMIT_VMEM: %s", xstrerror());
ad7ef91a 713 fatal_dump(tmp_error_buf);
714 }
715 }
716#endif /* RLIMIT_VMEM */
c4fb974e 717}
3a57089e 718
b8d8561b 719time_t
0673c0ba 720getCurrentTime(void)
3a57089e 721{
94e891ea 722#if GETTIMEOFDAY_NO_TZP
30a4f2a8 723 gettimeofday(&current_time);
724#else
d598947a 725 gettimeofday(&current_time, NULL);
5f3f8d0e 726#endif
30a4f2a8 727 return squid_curtime = current_time.tv_sec;
5f3f8d0e 728}
fe113054 729
b8d8561b 730int
731percent(int a, int b)
30a4f2a8 732{
733 return b ? ((int) (100.0 * a / b + 0.5)) : 0;
734}
735
b8d8561b 736void
67508012 737squid_signal(int sig, void (*func) _PARAMS((int)), int flags)
30a4f2a8 738{
739#if HAVE_SIGACTION
740 struct sigaction sa;
741 sa.sa_handler = func;
742 sa.sa_flags = flags;
743 sigemptyset(&sa.sa_mask);
744 if (sigaction(sig, &sa, NULL) < 0)
a3d5953d 745 debug(50, 0) ("sigaction: sig=%d func=%p: %s\n", sig, func, xstrerror());
30a4f2a8 746#else
88738790 747 signal(sig, func);
30a4f2a8 748#endif
749}
396c5745 750
16b204c4 751struct in_addr
0ee4272b 752inaddrFromHostent(const struct hostent *hp)
16b204c4 753{
cc6a9d2e 754 struct in_addr s;
3c0117c9 755 xmemcpy(&s.s_addr, hp->h_addr, sizeof(s.s_addr));
cc6a9d2e 756 return s;
16b204c4 757}
88738790 758
9e4ad609 759double
1d8e0d40 760doubleAverage(double cur, double new, int N, int max)
9e4ad609 761{
1d8e0d40 762 if (N > max)
763 N = max;
764 return (cur * (N - 1.0) + new) / N;
9e4ad609 765}
766
767int
768intAverage(int cur, int new, int n, int max)
769{
770 if (n > max)
771 n = max;
772 return (cur * (n - 1)) + new / n;
773}
70364f29 774
775void
776logsFlush(void)
777{
778 if (debug_log)
779 fflush(debug_log);
780 if (cache_useragent_log)
781 fflush(cache_useragent_log);
782}
88738790 783
784char *
785checkNullString(char *p)
786{
787 return p ? p : "(NULL)";
788}