]> git.ipfire.org Git - thirdparty/squid.git/blame - src/tools.cc
Define ERR_COMM_CLOSING error status code to be used when the comm_write
[thirdparty/squid.git] / src / tools.cc
CommitLineData
94e891ea 1
30a4f2a8 2/*
f5b8bbc4 3 * $Id: tools.cc,v 1.126 1997/10/25 17:23:02 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);
5c5783a2 122
0a0bf5db 123#if USE_ASYNC_IO
f5b8bbc4 124static void safeunlinkComplete(void *data, int retcode, int errcode);
0a0bf5db 125#endif
24382924 126
f8cde24f 127#ifdef _SQUID_SOLARIS_
f5b8bbc4 128int getrusage(int, struct rusage *);
129int getpagesize(void);
130int gethostname(char *, int);
f8cde24f 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);
56878878 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);
56878878 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 stmemFreeMemory();
e5f6c5c2 370 netdbFreeMemory();
56e15c50 371 ipcacheFreeMemory();
372 fqdncacheFreeMemory();
100fc710 373#endif
9e4ad609 374 file_close(0);
375 file_close(1);
376 file_close(2);
377 fdDumpOpen();
378 fdFreeMemory();
a3d5953d 379 debug(21, 0) ("Squid Cache (Version %s): Exiting normally.\n",
0a21bd84 380 version_string);
c7433536 381 fclose(debug_log);
4d64d74a 382 exit(0);
383}
147d3115 384
24382924 385static void
0ee4272b 386fatal_common(const char *message)
090089c4 387{
db40ae20 388#if HAVE_SYSLOG
6e40f263 389 if (opt_syslog_enable)
233794cd 390 syslog(LOG_ALERT, "%s", message);
db40ae20 391#endif
2c47cf74 392 fprintf(debug_log, "FATAL: %s\n", message);
9e975e4e 393 if (opt_debug_stderr && debug_log != stderr)
a47b9029 394 fprintf(stderr, "FATAL: %s\n", message);
c5c666ab 395 fprintf(debug_log, "Squid Cache (Version %s): Terminated abnormally.\n",
8213067d 396 version_string);
2c47cf74 397 fflush(debug_log);
9e4ad609 398 PrintRusage();
399 dumpMallocStats();
090089c4 400}
401
402/* fatal */
b8d8561b 403void
0ee4272b 404fatal(const char *message)
090089c4 405{
429fdbec 406 releaseServerSockets();
d399be0e 407 /* check for store_rebuilding flag because fatal() is often
408 * used in early initialization phases, long before we ever
409 * get to the store log. */
410 if (!store_rebuilding)
e102ebda 411 storeWriteCleanLogs(0);
090089c4 412 fatal_common(message);
413 exit(1);
414}
415
416/* fatal with dumping core */
b8d8561b 417void
0ee4272b 418fatal_dump(const char *message)
090089c4 419{
429fdbec 420 releaseServerSockets();
090089c4 421 if (message)
422 fatal_common(message);
4a69c163 423 if (opt_catch_signals)
e102ebda 424 storeWriteCleanLogs(0);
090089c4 425 abort();
426}
427
b8d8561b 428void
a3d5953d 429debug_trap(const char *message)
85b701ed 430{
4a69c163 431 if (!opt_catch_signals)
85b701ed 432 fatal_dump(message);
a3d5953d 433 _db_level = 0;
434 _db_print("WARNING: %s\n", message);
85b701ed 435}
436
b8d8561b 437void
438sig_child(int sig)
090089c4 439{
30a4f2a8 440#ifdef _SQUID_NEXT_
441 union wait status;
442#else
090089c4 443 int status;
090089c4 444#endif
ff8d0ea6 445 pid_t pid;
090089c4 446
30a4f2a8 447 do {
448#ifdef _SQUID_NEXT_
449 pid = wait3(&status, WNOHANG, NULL);
090089c4 450#else
30a4f2a8 451 pid = waitpid(-1, &status, WNOHANG);
090089c4 452#endif
97a88399 453 /* no debug() here; bad things happen if the signal is delivered during _db_print() */
30a4f2a8 454#if HAVE_SIGACTION
455 } while (pid > 0);
234967c9 456#else
30a4f2a8 457 } while (pid > 0 || (pid < 0 && errno == EINTR));
458 signal(sig, sig_child);
234967c9 459#endif
30a4f2a8 460}
44a47c6e 461
0ee4272b 462const char *
0673c0ba 463getMyHostname(void)
44a47c6e 464{
95d659f0 465 LOCAL_ARRAY(char, host, SQUIDHOSTNAMELEN + 1);
44a47c6e 466 static int present = 0;
0ee4272b 467 const struct hostent *h = NULL;
019dd986 468 char *t = NULL;
469
b6f794d6 470 if ((t = Config.visibleHostname))
019dd986 471 return t;
44a47c6e 472
473 /* Get the host name and store it in host to return */
474 if (!present) {
475 host[0] = '\0';
476 if (gethostname(host, SQUIDHOSTNAMELEN) == -1) {
a3d5953d 477 debug(50, 1) ("getMyHostname: gethostname failed: %s\n",
44a47c6e 478 xstrerror());
479 return NULL;
480 } else {
e5f6c5c2 481 if ((h = gethostbyname(host)) != NULL) {
44a47c6e 482 /* DNS lookup successful */
483 /* use the official name from DNS lookup */
484 strcpy(host, h->h_name);
485 }
486 present = 1;
487 }
488 }
489 return host;
490}
491
0a0bf5db 492void
0ee4272b 493safeunlink(const char *s, int quiet)
44a47c6e 494{
0a0bf5db 495#if USE_ASYNC_IO
496 aioUnlink(s,
497 quiet ? NULL : safeunlinkComplete,
498 quiet ? NULL : xstrdup(s));
499#else
500 if (unlink(s) < 0 && !quiet)
a3d5953d 501 debug(50, 1) ("safeunlink: Couldn't delete %s: %s\n", s, xstrerror());
0a0bf5db 502#endif
503}
504
505#if USE_ASYNC_IO
506static void
507safeunlinkComplete(void *data, int retcode, int errcode)
508{
509 char *s = data;
510 if (retcode < 0) {
511 errno = errcode;
a3d5953d 512 debug(50, 1) ("safeunlink: Couldn't delete %s. %s\n", s, xstrerror());
0a0bf5db 513 errno = 0;
514 }
515 xfree(s);
44a47c6e 516}
0a0bf5db 517#endif
12b9e9b1 518
30a4f2a8 519/* leave a privilegied section. (Give up any privilegies)
520 * Routines that need privilegies can rap themselves in enter_suid()
521 * and leave_suid()
522 * To give upp all posibilites to gain privilegies use no_suid()
12b9e9b1 523 */
b8d8561b 524void
0673c0ba 525leave_suid(void)
12b9e9b1 526{
527 struct passwd *pwd = NULL;
528 struct group *grp = NULL;
a3d5953d 529 debug(21, 3) ("leave_suid: PID %d called\n", getpid());
12b9e9b1 530 if (geteuid() != 0)
531 return;
532 /* Started as a root, check suid option */
b6f794d6 533 if (Config.effectiveUser == NULL)
12b9e9b1 534 return;
b6f794d6 535 if ((pwd = getpwnam(Config.effectiveUser)) == NULL)
12b9e9b1 536 return;
b6f794d6 537 if (Config.effectiveGroup && (grp = getgrnam(Config.effectiveGroup))) {
429fdbec 538 if (setgid(grp->gr_gid) < 0)
a3d5953d 539 debug(50, 1) ("leave_suid: setgid: %s\n", xstrerror());
12b9e9b1 540 } else {
429fdbec 541 if (setgid(pwd->pw_gid) < 0)
a3d5953d 542 debug(50, 1) ("leave_suid: setgid: %s\n", xstrerror());
12b9e9b1 543 }
a3d5953d 544 debug(21, 3) ("leave_suid: PID %d giving up root, becoming '%s'\n",
30a4f2a8 545 getpid(), pwd->pw_name);
234967c9 546#if HAVE_SETRESUID
429fdbec 547 if (setresuid(pwd->pw_uid, pwd->pw_uid, 0) < 0)
a3d5953d 548 debug(50, 1) ("leave_suid: setresuid: %s\n", xstrerror());
234967c9 549#elif HAVE_SETEUID
429fdbec 550 if (seteuid(pwd->pw_uid) < 0)
a3d5953d 551 debug(50, 1) ("leave_suid: seteuid: %s\n", xstrerror());
234967c9 552#else
429fdbec 553 if (setuid(pwd->pw_uid) < 0)
a3d5953d 554 debug(50, 1) ("leave_suid: setuid: %s\n", xstrerror());
234967c9 555#endif
556}
557
30a4f2a8 558/* Enter a privilegied section */
b8d8561b 559void
0673c0ba 560enter_suid(void)
234967c9 561{
a3d5953d 562 debug(21, 3) ("enter_suid: PID %d taking root priveleges\n", getpid());
234967c9 563#if HAVE_SETRESUID
564 setresuid(-1, 0, -1);
565#else
566 setuid(0);
567#endif
568}
569
30a4f2a8 570/* Give up the posibility to gain privilegies.
571 * this should be used before starting a sub process
572 */
b8d8561b 573void
0673c0ba 574no_suid(void)
234967c9 575{
576 uid_t uid;
30a4f2a8 577 leave_suid();
234967c9 578 uid = geteuid();
a3d5953d 579 debug(21, 3) ("leave_suid: PID %d giving up root priveleges forever\n", getpid());
234967c9 580#if HAVE_SETRESUID
429fdbec 581 if (setresuid(uid, uid, uid) < 0)
a3d5953d 582 debug(50, 1) ("no_suid: setresuid: %s\n", xstrerror());
234967c9 583#else
584 setuid(0);
429fdbec 585 if (setuid(uid) < 0)
a3d5953d 586 debug(50, 1) ("no_suid: setuid: %s\n", xstrerror());
234967c9 587#endif
12b9e9b1 588}
ccff9601 589
b8d8561b 590void
0673c0ba 591writePidFile(void)
ccff9601 592{
9e4ad609 593 int fd;
0b4639af 594 const char *f = NULL;
973e9fe1 595 mode_t old_umask;
9e4ad609 596 char buf[32];
597 if ((f = Config.pidFilename) == NULL)
598 return;
599 if (!strcmp(Config.pidFilename, "none"))
ccff9601 600 return;
30a4f2a8 601 enter_suid();
973e9fe1 602 old_umask = umask(022);
9e4ad609 603 fd = file_open(f, O_WRONLY | O_CREAT | O_TRUNC, NULL, NULL);
973e9fe1 604 umask(old_umask);
30a4f2a8 605 leave_suid();
9e4ad609 606 if (fd < 0) {
a3d5953d 607 debug(50, 0) ("%s: %s\n", f, xstrerror());
9e4ad609 608 debug_trap("Could not write pid file");
609 return;
ccff9601 610 }
56878878 611 snprintf(buf, 32, "%d\n", (int) getpid());
9e4ad609 612 write(fd, buf, strlen(buf));
613 file_close(fd);
ccff9601 614}
c4fb974e 615
616
ff8d0ea6 617pid_t
0673c0ba 618readPidFile(void)
7690e8eb 619{
620 FILE *pid_fp = NULL;
9e4ad609 621 const char *f = Config.pidFilename;
ff8d0ea6 622 pid_t pid = -1;
623 int i;
7690e8eb 624
9e4ad609 625 if (f == NULL || !strcmp(Config.pidFilename, "none")) {
7690e8eb 626 fprintf(stderr, "%s: ERROR: No pid file name defined\n", appname);
627 exit(1);
628 }
629 pid_fp = fopen(f, "r");
630 if (pid_fp != NULL) {
ff8d0ea6 631 pid = 0;
632 if (fscanf(pid_fp, "%d", &i) == 1)
633 pid = (pid_t) i;
7690e8eb 634 fclose(pid_fp);
635 } else {
636 if (errno != ENOENT) {
637 fprintf(stderr, "%s: ERROR: Could not read pid file\n", appname);
638 fprintf(stderr, "\t%s: %s\n", f, xstrerror());
639 exit(1);
640 }
641 }
642 return pid;
643}
644
645
b8d8561b 646void
0673c0ba 647setMaxFD(void)
c4fb974e 648{
234967c9 649#if HAVE_SETRLIMIT
c4fb974e 650 /* try to use as many file descriptors as possible */
651 /* System V uses RLIMIT_NOFILE and BSD uses RLIMIT_OFILE */
652 struct rlimit rl;
653#if defined(RLIMIT_NOFILE)
654 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
a3d5953d 655 debug(50, 0) ("setrlimit: RLIMIT_NOFILE: %s\n", xstrerror());
c4fb974e 656 } else {
e83892e9 657 rl.rlim_cur = Squid_MaxFD;
30a4f2a8 658 if (rl.rlim_cur > rl.rlim_max)
e83892e9 659 Squid_MaxFD = rl.rlim_cur = rl.rlim_max;
c4fb974e 660 if (setrlimit(RLIMIT_NOFILE, &rl) < 0) {
56878878 661 snprintf(tmp_error_buf, ERROR_BUF_SZ,
662 "setrlimit: RLIMIT_NOFILE: %s", xstrerror());
234967c9 663 fatal_dump(tmp_error_buf);
c4fb974e 664 }
665 }
666#elif defined(RLIMIT_OFILE)
667 if (getrlimit(RLIMIT_OFILE, &rl) < 0) {
a3d5953d 668 debug(50, 0) ("setrlimit: RLIMIT_NOFILE: %s\n", xstrerror());
c4fb974e 669 } else {
e83892e9 670 rl.rlim_cur = Squid_MaxFD;
30a4f2a8 671 if (rl.rlim_cur > rl.rlim_max)
e83892e9 672 Squid_MaxFD = rl.rlim_cur = rl.rlim_max;
c4fb974e 673 if (setrlimit(RLIMIT_OFILE, &rl) < 0) {
56878878 674 snprintf(tmp_error_buf, ERROR_BUF_SZ,
675 "setrlimit: RLIMIT_OFILE: %s", xstrerror());
234967c9 676 fatal_dump(tmp_error_buf);
c4fb974e 677 }
678 }
679#endif
c4fb974e 680#else /* HAVE_SETRLIMIT */
a3d5953d 681 debug(21, 1) ("setMaxFD: Cannot increase: setrlimit() not supported on this system\n");
30a4f2a8 682#endif /* HAVE_SETRLIMIT */
683
684#if HAVE_SETRLIMIT && defined(RLIMIT_DATA)
685 if (getrlimit(RLIMIT_DATA, &rl) < 0) {
a3d5953d 686 debug(50, 0) ("getrlimit: RLIMIT_DATA: %s\n", xstrerror());
88738790 687 } else if (rl.rlim_max > rl.rlim_cur) {
30a4f2a8 688 rl.rlim_cur = rl.rlim_max; /* set it to the max */
689 if (setrlimit(RLIMIT_DATA, &rl) < 0) {
56878878 690 snprintf(tmp_error_buf, ERROR_BUF_SZ,
691 "setrlimit: RLIMIT_DATA: %s", xstrerror());
30a4f2a8 692 fatal_dump(tmp_error_buf);
693 }
694 }
695#endif /* RLIMIT_DATA */
ad7ef91a 696#if HAVE_SETRLIMIT && defined(RLIMIT_VMEM)
697 if (getrlimit(RLIMIT_VMEM, &rl) < 0) {
a3d5953d 698 debug(50, 0) ("getrlimit: RLIMIT_VMEM: %s\n", xstrerror());
88738790 699 } else if (rl.rlim_max > rl.rlim_cur) {
ad7ef91a 700 rl.rlim_cur = rl.rlim_max; /* set it to the max */
701 if (setrlimit(RLIMIT_VMEM, &rl) < 0) {
56878878 702 snprintf(tmp_error_buf, ERROR_BUF_SZ,
703 "setrlimit: RLIMIT_VMEM: %s", xstrerror());
ad7ef91a 704 fatal_dump(tmp_error_buf);
705 }
706 }
707#endif /* RLIMIT_VMEM */
c4fb974e 708}
3a57089e 709
b8d8561b 710time_t
0673c0ba 711getCurrentTime(void)
3a57089e 712{
94e891ea 713#if GETTIMEOFDAY_NO_TZP
30a4f2a8 714 gettimeofday(&current_time);
715#else
d598947a 716 gettimeofday(&current_time, NULL);
5f3f8d0e 717#endif
30a4f2a8 718 return squid_curtime = current_time.tv_sec;
5f3f8d0e 719}
fe113054 720
b8d8561b 721int
722percent(int a, int b)
30a4f2a8 723{
724 return b ? ((int) (100.0 * a / b + 0.5)) : 0;
725}
726
b8d8561b 727void
f5b8bbc4 728squid_signal(int sig, SIGHDLR *func, int flags)
30a4f2a8 729{
730#if HAVE_SIGACTION
731 struct sigaction sa;
732 sa.sa_handler = func;
733 sa.sa_flags = flags;
734 sigemptyset(&sa.sa_mask);
735 if (sigaction(sig, &sa, NULL) < 0)
a3d5953d 736 debug(50, 0) ("sigaction: sig=%d func=%p: %s\n", sig, func, xstrerror());
30a4f2a8 737#else
88738790 738 signal(sig, func);
30a4f2a8 739#endif
740}
396c5745 741
16b204c4 742struct in_addr
0ee4272b 743inaddrFromHostent(const struct hostent *hp)
16b204c4 744{
cc6a9d2e 745 struct in_addr s;
3c0117c9 746 xmemcpy(&s.s_addr, hp->h_addr, sizeof(s.s_addr));
cc6a9d2e 747 return s;
16b204c4 748}
88738790 749
9e4ad609 750double
1d8e0d40 751doubleAverage(double cur, double new, int N, int max)
9e4ad609 752{
1d8e0d40 753 if (N > max)
754 N = max;
755 return (cur * (N - 1.0) + new) / N;
9e4ad609 756}
757
758int
759intAverage(int cur, int new, int n, int max)
760{
761 if (n > max)
762 n = max;
763 return (cur * (n - 1)) + new / n;
764}
70364f29 765
766void
767logsFlush(void)
768{
769 if (debug_log)
770 fflush(debug_log);
771 if (cache_useragent_log)
772 fflush(cache_useragent_log);
773}
88738790 774
775char *
776checkNullString(char *p)
777{
778 return p ? p : "(NULL)";
779}