]> git.ipfire.org Git - thirdparty/squid.git/blame - src/main.cc
maximum_icp_query_timeout comment fix. Found by Toby Dickenson.
[thirdparty/squid.git] / src / main.cc
CommitLineData
a47b9029 1
30a4f2a8 2/*
5ff76111 3 * $Id: main.cc,v 1.332 2001/01/30 10:06:50 hno Exp $
30a4f2a8 4 *
5 * DEBUG: section 1 Startup and Main Loop
6 * AUTHOR: Harvest Derived
7 *
2b6662ba 8 * SQUID Web Proxy Cache http://www.squid-cache.org/
e25c139f 9 * ----------------------------------------------------------
30a4f2a8 10 *
2b6662ba 11 * Squid is the result of efforts by numerous individuals from
12 * the Internet community; see the CONTRIBUTORS file for full
13 * details. Many organizations have provided support for Squid's
14 * development; see the SPONSORS file for full details. Squid is
15 * Copyrighted (C) 2001 by the Regents of the University of
16 * California; see the COPYRIGHT file for full details. Squid
17 * incorporates software developed and/or copyrighted by other
18 * sources; see the CREDITS file for full details.
30a4f2a8 19 *
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
cbdec147 32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
e25c139f 33 *
30a4f2a8 34 */
44a47c6e 35
36#include "squid.h"
37
30a4f2a8 38/* for error reporting from xmalloc and friends */
ea3a2a69 39extern void (*failure_notify) (const char *);
30a4f2a8 40
f1dc9b30 41static int opt_send_signal = -1;
f95b8144 42static int opt_no_daemon = 0;
e13ee7ad 43static int opt_parse_cfg_only = 0;
30a4f2a8 44static int httpPortNumOverride = 1;
45static int icpPortNumOverride = 1; /* Want to detect "-u 0" */
e13ee7ad 46static int configured_once = 0;
30a4f2a8 47#if MALLOC_DBG
4d64d74a 48static int malloc_debug_level = 0;
30a4f2a8 49#endif
5cd39a10 50static volatile int do_reconfigure = 0;
51static volatile int do_rotate = 0;
2681d383 52static volatile int do_shutdown = 0;
4d7add01 53
5cd39a10 54static void mainRotate(void);
55static void mainReconfigure(void);
b984c445 56static SIGHDLR rotate_logs;
57static SIGHDLR reconfigure;
58#if ALARM_UPDATES_TIME
59static SIGHDLR time_tick;
60#endif
f5b8bbc4 61static void mainInitialize(void);
f5b8bbc4 62static void usage(void);
63static void mainParseOptions(int, char **);
64static void sendSignal(void);
65static void serverConnectionsOpen(void);
bbe199dc 66static void watch_child(char **);
85407535 67static void setEffectiveUser(void);
36a97e19 68#if MEM_GEN_TRACE
69extern void log_trace_done();
70extern void log_trace_init(char *);
71#endif
d723bf6b 72static EVH SquidShutdown;
b6a2f15e 73static void mainSetCwd(void);
efd900cb 74static int checkRunningPid(void);
85407535 75
e18d7fdc 76static const char *squid_start_script = "squid_start";
77
9bc73deb 78#if TEST_ACCESS
79#include "test_access.c"
80#endif
81
b8d8561b 82static void
0673c0ba 83usage(void)
ccff9601 84{
0ee4272b 85 fprintf(stderr,
969c39b9 86 "Usage: %s [-dhsvzCDFNRVYX] [-f config-file] [-[au] port] [-k signal]\n"
15df8349 87 " -a port Specify HTTP port number (default: %d).\n"
b6157f5e 88 " -d level Write debugging to stderr also.\n"
0ee4272b 89 " -f file Use given config-file instead of\n"
90 " %s\n"
91 " -h Print help message.\n"
e13ee7ad 92 " -k reconfigure|rotate|shutdown|interrupt|kill|debug|check|parse\n"
93 " Parse configuration file, then send signal to \n"
94 " running copy (except -k parse) and exit.\n"
0ee4272b 95 " -s Enable logging to syslog.\n"
96 " -u port Specify ICP port number (default: %d), disable with 0.\n"
97 " -v Print version.\n"
85407535 98 " -z Create swap directories\n"
0ee4272b 99 " -C Do not catch fatal signals.\n"
100 " -D Disable initial DNS tests.\n"
a411c763 101 " -F Don't serve any requests until store is rebuilt.\n"
969c39b9 102 " -N No daemon mode.\n"
0ee4272b 103 " -R Do not set REUSEADDR on port.\n"
504123ec 104 " -S Double-check swap during rebuild.\n"
0ee4272b 105 " -V Virtual host httpd-accelerator.\n"
3013ac6d 106 " -X Force full debugging.\n"
429fdbec 107 " -Y Only return UDP_HIT or UDP_MISS_NOFETCH during fast reload.\n",
30a4f2a8 108 appname, CACHE_HTTP_PORT, DefaultConfigFile, CACHE_ICP_PORT);
77ffc99f 109 exit(1);
ccff9601 110}
111
b8d8561b 112static void
113mainParseOptions(int argc, char *argv[])
090089c4 114{
090089c4 115 extern char *optarg;
4d64d74a 116 int c;
090089c4 117
504123ec 118 while ((c = getopt(argc, argv, "CDFNRSVYXa:d:f:hk:m::su:vz?")) != -1) {
090089c4 119 switch (c) {
090089c4 120 case 'C':
1758c627 121 opt_catch_signals = 0;
090089c4 122 break;
123 case 'D':
30a4f2a8 124 opt_dns_tests = 0;
090089c4 125 break;
30a4f2a8 126 case 'F':
127 opt_foreground_rebuild = 1;
090089c4 128 break;
f95b8144 129 case 'N':
130 opt_no_daemon = 1;
9e2225aa 131 break;
090089c4 132 case 'R':
3b4be6a6 133 opt_reuseaddr = 0;
090089c4 134 break;
b109de6b 135 case 'S':
504123ec 136 opt_store_doublecheck = 1;
b109de6b 137 break;
30a4f2a8 138 case 'V':
139 vhost_mode = 1;
140 break;
e924600d 141 case 'X':
142 /* force full debugging */
143 sigusr2_handle(SIGUSR2);
144 break;
30a4f2a8 145 case 'Y':
146 opt_reload_hit_only = 1;
147 break;
148 case 'a':
149 httpPortNumOverride = atoi(optarg);
150 break;
0d90407c 151 case 'd':
723e8aa3 152 opt_debug_stderr = atoi(optarg);
0d90407c 153 break;
090089c4 154 case 'f':
00fac1f8 155 xfree(ConfigFile);
156 ConfigFile = xstrdup(optarg);
090089c4 157 break;
30a4f2a8 158 case 'h':
159 usage();
090089c4 160 break;
7690e8eb 161 case 'k':
24382924 162 if ((int) strlen(optarg) < 1)
7690e8eb 163 usage();
164 if (!strncmp(optarg, "reconfigure", strlen(optarg)))
165 opt_send_signal = SIGHUP;
166 else if (!strncmp(optarg, "rotate", strlen(optarg)))
7e7a0442 167#ifdef _SQUID_LINUX_THREADS_
e3175d1f 168 opt_send_signal = SIGQUIT;
169#else
7690e8eb 170 opt_send_signal = SIGUSR1;
e3175d1f 171#endif
7690e8eb 172 else if (!strncmp(optarg, "debug", strlen(optarg)))
7e7a0442 173#ifdef _SQUID_LINUX_THREADS_
e3175d1f 174 opt_send_signal = SIGTRAP;
175#else
7690e8eb 176 opt_send_signal = SIGUSR2;
e3175d1f 177#endif
7690e8eb 178 else if (!strncmp(optarg, "shutdown", strlen(optarg)))
179 opt_send_signal = SIGTERM;
6759a5fb 180 else if (!strncmp(optarg, "interrupt", strlen(optarg)))
181 opt_send_signal = SIGINT;
7690e8eb 182 else if (!strncmp(optarg, "kill", strlen(optarg)))
183 opt_send_signal = SIGKILL;
184 else if (!strncmp(optarg, "check", strlen(optarg)))
fedac7e5 185 opt_send_signal = 0; /* SIGNULL */
e13ee7ad 186 else if (!strncmp(optarg, "parse", strlen(optarg)))
8a6218c6 187 opt_parse_cfg_only = 1; /* parse cfg file only */
7690e8eb 188 else
189 usage();
190 break;
090089c4 191 case 'm':
33ab18e8 192 if (optarg) {
30a4f2a8 193#if MALLOC_DBG
33ab18e8 194 malloc_debug_level = atoi(optarg);
195 /* NOTREACHED */
196 break;
30a4f2a8 197#else
33ab18e8 198 fatal("Need to add -DMALLOC_DBG when compiling to use -mX option");
199 /* NOTREACHED */
200#endif
201 } else {
202#if XMALLOC_TRACE
203 xmalloc_trace = !xmalloc_trace;
204#else
205 fatal("Need to configure --enable-xmalloc-debug-trace to use -m option");
30a4f2a8 206#endif
33ab18e8 207 }
30a4f2a8 208 case 's':
6e40f263 209 opt_syslog_enable = 1;
30a4f2a8 210 break;
211 case 'u':
212 icpPortNumOverride = atoi(optarg);
213 if (icpPortNumOverride < 0)
214 icpPortNumOverride = 0;
215 break;
216 case 'v':
217 printf("Squid Cache: Version %s\n", version_string);
218 exit(0);
219 /* NOTREACHED */
090089c4 220 case 'z':
85407535 221 opt_create_swap_dirs = 1;
090089c4 222 break;
223 case '?':
090089c4 224 default:
ccff9601 225 usage();
090089c4 226 break;
227 }
090089c4 228 }
4d64d74a 229}
090089c4 230
7a2f978b 231/* ARGSUSED */
b8d8561b 232static void
233rotate_logs(int sig)
30a4f2a8 234{
5cd39a10 235 do_rotate = 1;
30a4f2a8 236#if !HAVE_SIGACTION
237 signal(sig, rotate_logs);
238#endif
239}
240
b984c445 241#if ALARM_UPDATES_TIME
97c03d3c 242static void
243time_tick(int sig)
244{
245 getCurrentTime();
246 alarm(1);
247#if !HAVE_SIGACTION
248 signal(sig, time_tick);
249#endif
250}
38d04788 251
b984c445 252#endif
97c03d3c 253
7a2f978b 254/* ARGSUSED */
b8d8561b 255static void
256reconfigure(int sig)
30a4f2a8 257{
5cd39a10 258 do_reconfigure = 1;
30a4f2a8 259#if !HAVE_SIGACTION
260 signal(sig, reconfigure);
261#endif
262}
263
b8d8561b 264void
265shut_down(int sig)
30a4f2a8 266{
2681d383 267 do_shutdown = sig == SIGINT ? -1 : 1;
cadc2d55 268#ifdef KILL_PARENT_OPT
5cd39a10 269 if (getppid() > 1) {
270 debug(1, 1) ("Killing RunCache, pid %d\n", getppid());
271 kill(getppid(), sig);
88738790 272 }
cadc2d55 273#endif
6e40f263 274#if SA_RESETHAND == 0
275 signal(SIGTERM, SIG_DFL);
276 signal(SIGINT, SIG_DFL);
277#endif
30a4f2a8 278}
279
24382924 280static void
0673c0ba 281serverConnectionsOpen(void)
4d64d74a 282{
15df8349 283 clientHttpConnectionsOpen();
284 icpConnectionsOpen();
ace287ee 285#if USE_HTCP
286 htcpInit();
287#endif
678c6099 288#ifdef SQUID_SNMP
3265e68d 289 snmpConnectionOpen();
320e9f36 290#endif
eb824054 291#if USE_WCCP
320e9f36 292 wccpConnectionOpen();
2bbd722b 293#endif
5ecceaa4 294 clientdbInit();
16b204c4 295 icmpOpen();
67508012 296 netdbInit();
f899fac1 297 asnInit();
85034133 298 peerSelectInit();
afd88fbe 299#if USE_CARP
300 carpInit();
301#endif
5f3f8d0e 302}
303
b8d8561b 304void
0673c0ba 305serverConnectionsClose(void)
5f3f8d0e 306{
0a5a8601 307 assert(shutting_down || reconfiguring);
c0fbae16 308 clientHttpConnectionsClose();
17e6c0a1 309 icpConnectionShutdown();
72549e05 310#if USE_HTCP
311 htcpSocketShutdown();
312#endif
c0fbae16 313 icmpClose();
15df8349 314#ifdef SQUID_SNMP
17e6c0a1 315 snmpConnectionShutdown();
320e9f36 316#endif
eb824054 317#if USE_WCCP
320e9f36 318 wccpConnectionShutdown();
15df8349 319#endif
4bac8de8 320 asnFreeMemory();
5f3f8d0e 321}
322
b8d8561b 323static void
dbe4fd8e 324mainReconfigure(void)
5f3f8d0e 325{
a60f7062 326 debug(1, 1) ("Restarting Squid Cache (version %s)...\n", version_string);
5cd39a10 327 reconfiguring = 1;
0ffd22bc 328 /* Already called serverConnectionsClose and ipcacheShutdownServers() */
15df8349 329 serverConnectionsClose();
17e6c0a1 330 icpConnectionClose();
72549e05 331#if USE_HTCP
332 htcpSocketClose();
333#endif
17e6c0a1 334#ifdef SQUID_SNMP
335 snmpConnectionClose();
320e9f36 336#endif
eb824054 337#if USE_WCCP
320e9f36 338 wccpConnectionClose();
17e6c0a1 339#endif
3c573763 340#if USE_DNSSERVERS
74addf6c 341 dnsShutdown();
3c573763 342#else
7b724b86 343 idnsShutdown();
eb824054 344#endif
74addf6c 345 redirectShutdown();
346 authenticateShutdown();
2db68ce5 347 storeDirCloseSwapLogs();
c68e9c6b 348 errorClean();
00fac1f8 349 parseConfigFile(ConfigFile);
b6f794d6 350 _db_init(Config.Log.log, Config.debugOptions);
429fdbec 351 ipcache_restart(); /* clear stuck entries */
94439e4e 352 authenticateUserCacheRestart(); /* clear stuck ACL entries */
429fdbec 353 fqdncache_restart(); /* sigh, fqdncache too */
0e70aa1e 354 parseEtcHosts();
53ad48e6 355 errorInitialize(); /* reload error pages */
3c573763 356#if USE_DNSSERVERS
74addf6c 357 dnsInit();
3c573763 358#else
7b724b86 359 idnsInit();
eb824054 360#endif
74addf6c 361 redirectInit();
94439e4e 362 authenticateInit(&Config.authConfig);
1f38f50a 363#if USE_WCCP
364 wccpInit();
365#endif
0ffd22bc 366 serverConnectionsOpen();
e06ce23a 367 if (theOutIcpConnection >= 0) {
5942e8d4 368 if (!Config2.Accel.on || Config.onoff.accel_with_proxy)
e06ce23a 369 neighbors_open(theOutIcpConnection);
370 else
371 debug(1, 1) ("ICP port disabled in httpd_accelerator mode\n");
372 }
2db68ce5 373 storeDirOpenSwapLogs();
9c021a38 374 mimeInit(Config.mimeTablePathname);
b8890359 375 writePidFile(); /* write PID file */
aebbcd07 376 debug(1, 1) ("Ready to serve requests.\n");
5cd39a10 377 reconfiguring = 0;
378}
379
380static void
381mainRotate(void)
382{
383 icmpClose();
3c573763 384#if USE_DNSSERVERS
e40aa8da 385 dnsShutdown();
3c573763 386#endif
e40aa8da 387 redirectShutdown();
388 authenticateShutdown();
5cd39a10 389 _db_rotate_log(); /* cache.log */
390 storeDirWriteCleanLogs(1);
391 storeLogRotate(); /* store.log */
392 accessLogRotate(); /* access.log */
393 useragentRotateLog(); /* useragent.log */
fd2c5549 394 refererRotateLog(); /* referer.log */
225644d7 395#if WIP_FWD_LOG
396 fwdLogRotate();
397#endif
5cd39a10 398 icmpOpen();
3c573763 399#if USE_DNSSERVERS
e40aa8da 400 dnsInit();
3c573763 401#endif
e40aa8da 402 redirectInit();
94439e4e 403 authenticateInit(&Config.authConfig);
5f3f8d0e 404}
405
067bea91 406static void
85407535 407setEffectiveUser(void)
408{
409 leave_suid(); /* Run as non privilegied user */
cd377065 410#ifdef _SQUID_OS2_
411 return;
412#endif
85407535 413 if (geteuid() == 0) {
414 debug(0, 0) ("Squid is not safe to run as root! If you must\n");
415 debug(0, 0) ("start Squid as root, then you must configure\n");
416 debug(0, 0) ("it to run as a non-priveledged user with the\n");
417 debug(0, 0) ("'cache_effective_user' option in the config file.\n");
418 fatal("Don't run Squid as root, set 'cache_effective_user'!");
419 }
420}
421
b6a2f15e 422static void
423mainSetCwd(void)
424{
425 if (Config.coredump_dir) {
426 if (!chdir(Config.coredump_dir)) {
427 debug(0, 1) ("Set Current Directory to %s\n", Config.coredump_dir);
428 return;
429 } else {
430 debug(50, 0) ("chdir: %s: %s\n", Config.coredump_dir, xstrerror());
431 }
432 }
5ff76111 433 debug(0, 1) ("Current Directory is %s\n", p);
434 xfree(p);
435 return;
b6a2f15e 436}
437
b8d8561b 438static void
0673c0ba 439mainInitialize(void)
5f3f8d0e 440{
efd900cb 441 /* chroot if configured to run inside chroot */
442 if (Config.chroot_dir && chroot(Config.chroot_dir)) {
443 fatal("failed to chroot");
444 }
1758c627 445 if (opt_catch_signals) {
30a4f2a8 446 squid_signal(SIGSEGV, death, SA_NODEFER | SA_RESETHAND);
447 squid_signal(SIGBUS, death, SA_NODEFER | SA_RESETHAND);
44f99671 448 }
30a4f2a8 449 squid_signal(SIGPIPE, SIG_IGN, SA_RESTART);
450 squid_signal(SIGCHLD, sig_child, SA_NODEFER | SA_RESTART);
44f99671 451
85407535 452 setEffectiveUser();
7e3ce7b9 453 assert(Config.Sockaddr.http);
30a4f2a8 454 if (httpPortNumOverride != 1)
7e3ce7b9 455 Config.Sockaddr.http->s.sin_port = htons(httpPortNumOverride);
30a4f2a8 456 if (icpPortNumOverride != 1)
f2052513 457 Config.Port.icp = (u_short) icpPortNumOverride;
30a4f2a8 458
b6f794d6 459 _db_init(Config.Log.log, Config.debugOptions);
5c5783a2 460 fd_open(fileno(debug_log), FD_LOG, Config.Log.log);
71a17702 461#if MEM_GEN_TRACE
462 log_trace_init("/tmp/squid.alloc");
463#endif
a3d5953d 464 debug(1, 0) ("Starting Squid Cache version %s for %s...\n",
30a4f2a8 465 version_string,
466 CONFIG_HOST_TYPE);
aebbcd07 467 debug(1, 1) ("Process ID %d\n", (int) getpid());
a3d5953d 468 debug(1, 1) ("With %d file descriptors available\n", Squid_MaxFD);
5f3f8d0e 469
9f75c559 470 if (!configured_once)
234967c9 471 disk_init(); /* disk_init must go before ipcache_init() */
5f3f8d0e 472 ipcache_init();
f88bb09c 473 fqdncache_init();
0e70aa1e 474 parseEtcHosts();
3c573763 475#if USE_DNSSERVERS
74addf6c 476 dnsInit();
3c573763 477#else
7b724b86 478 idnsInit();
eb824054 479#endif
74addf6c 480 redirectInit();
94439e4e 481 authenticateInit(&Config.authConfig);
b012353a 482 useragentOpenLog();
fd2c5549 483 refererOpenLog();
2ac76861 484 httpHeaderInitModule(); /* must go before any header processing (e.g. the one in errorInitialize) */
2246b732 485 httpReplyInitModule(); /* must go before accepting replies */
9b312a19 486 errorInitialize();
7a2f978b 487 accessLogInit();
3898f57f 488#if USE_IDENT
05832ae1 489 identInit();
3898f57f 490#endif
5e14bf6d 491#ifdef SQUID_SNMP
492 snmpInit();
493#endif
30a4f2a8 494#if MALLOC_DBG
5f3f8d0e 495 malloc_debug(0, malloc_debug_level);
496#endif
497
dbe4fd8e 498 if (!configured_once) {
a3d0a19d 499#if USE_UNLINKD
429fdbec 500 unlinkdInit();
a3d0a19d 501#endif
7111c86a 502 urlInitialize();
22f3fd98 503 cachemgrInit();
a7c05555 504 statInit();
5f3f8d0e 505 storeInit();
b6a2f15e 506 mainSetCwd();
5f3f8d0e 507 /* after this point we want to see the mallinfo() output */
508 do_mallinfo = 1;
812ed90c 509 mimeInit(Config.mimeTablePathname);
603a02fd 510 pconnInit();
1c3e77cd 511 refreshInit();
0d7e5d78 512#if DELAY_POOLS
95e36d02 513 delayPoolsInit();
0d7e5d78 514#endif
8ddcc35d 515 fwdInit();
5f3f8d0e 516 }
1f38f50a 517#if USE_WCCP
518 wccpInit();
519#endif
2285407f 520 serverConnectionsOpen();
e06ce23a 521 if (theOutIcpConnection >= 0) {
5942e8d4 522 if (!Config2.Accel.on || Config.onoff.accel_with_proxy)
e06ce23a 523 neighbors_open(theOutIcpConnection);
524 else
525 debug(1, 1) ("ICP port disabled in httpd_accelerator mode\n");
526 }
efd900cb 527 if (Config.chroot_dir)
528 no_suid();
dbe4fd8e 529 if (!configured_once)
0a5b9b32 530 writePidFile(); /* write PID file */
531
7e7a0442 532#ifdef _SQUID_LINUX_THREADS_
e3175d1f 533 squid_signal(SIGQUIT, rotate_logs, SA_RESTART);
534 squid_signal(SIGTRAP, sigusr2_handle, SA_RESTART);
535#else
30a4f2a8 536 squid_signal(SIGUSR1, rotate_logs, SA_RESTART);
537 squid_signal(SIGUSR2, sigusr2_handle, SA_RESTART);
9fc0b4b8 538#endif
30a4f2a8 539 squid_signal(SIGHUP, reconfigure, SA_RESTART);
540 squid_signal(SIGTERM, shut_down, SA_NODEFER | SA_RESETHAND | SA_RESTART);
541 squid_signal(SIGINT, shut_down, SA_NODEFER | SA_RESETHAND | SA_RESTART);
b984c445 542#if ALARM_UPDATES_TIME
97c03d3c 543 squid_signal(SIGALRM, time_tick, SA_RESTART);
544 alarm(1);
b984c445 545#endif
58a39dc9 546 memCheckInit();
aebbcd07 547 debug(1, 1) ("Ready to serve requests.\n");
dbe4fd8e 548 if (!configured_once) {
52040193 549 eventAdd("storeMaintain", storeMaintainSwapSpace, NULL, 1.0, 1);
17a0a4ee 550 if (Config.onoff.announce)
52040193 551 eventAdd("start_announce", start_announce, NULL, 3600.0, 1);
552 eventAdd("ipcache_purgelru", ipcache_purgelru, NULL, 10.0, 1);
553 eventAdd("fqdncache_purgelru", fqdncache_purgelru, NULL, 15.0, 1);
4d7add01 554 }
dbe4fd8e 555 configured_once = 1;
4d64d74a 556}
557
b8d8561b 558int
559main(int argc, char **argv)
4d64d74a 560{
561 int errcount = 0;
4d64d74a 562 int n; /* # of GC'd objects */
bc528c78 563 time_t loop_delay;
7e3ce7b9 564 mode_t oldmask;
4d64d74a 565
88738790 566 debug_log = stderr;
e83892e9 567 if (FD_SETSIZE < Squid_MaxFD)
568 Squid_MaxFD = FD_SETSIZE;
399e85ea 569
7328e889 570 /* call mallopt() before anything else */
0b29fe44 571#if HAVE_MALLOPT
7328e889 572#ifdef M_GRAIN
573 /* Round up all sizes to a multiple of this */
574 mallopt(M_GRAIN, 16);
575#endif
576#ifdef M_MXFAST
577 /* biggest size that is considered a small block */
578 mallopt(M_MXFAST, 256);
579#endif
580#ifdef M_NBLKS
581 /* allocate this many small blocks at once */
582 mallopt(M_NLBLKS, 32);
583#endif
584#endif /* HAVE_MALLOPT */
585
7e3ce7b9 586 /*
587 * The plan here is to set the umask to 007 (deny others for
588 * read,write,execute), but only if the umask is not already
589 * set. Unfortunately, there is no way to get the current
590 * umask value without setting it.
591 */
592 oldmask = umask(S_IRWXO);
593 if (oldmask)
594 umask(oldmask);
595
30a4f2a8 596 memset(&local_addr, '\0', sizeof(struct in_addr));
429fdbec 597 safe_inet_addr(localhost, &local_addr);
28070024 598 memset(&any_addr, '\0', sizeof(struct in_addr));
429fdbec 599 safe_inet_addr("0.0.0.0", &any_addr);
28070024 600 memset(&no_addr, '\0', sizeof(struct in_addr));
429fdbec 601 safe_inet_addr("255.255.255.255", &no_addr);
88738790 602 squid_srandom(time(NULL));
4d64d74a 603
f2908497 604 getCurrentTime();
605 squid_start = current_time;
4d64d74a 606 failure_notify = fatal_dump;
607
608 mainParseOptions(argc, argv);
609
e13ee7ad 610 /* parse configuration file
611 * note: in "normal" case this used to be called from mainInitialize() */
612 {
613 int parse_err;
614 if (!ConfigFile)
615 ConfigFile = xstrdup(DefaultConfigFile);
3cc5715b 616 assert(!configured_once);
5d620373 617#if USE_LEAKFINDER
618 leakInit();
619#endif
28c60158 620 memInit();
621 cbdataInit();
9bc73deb 622 eventInit(); /* eventInit() is required for config parsing */
cd748f27 623 storeFsInit(); /* required for config parsing */
94439e4e 624 authenticateSchemeInit(); /* required for config parsign */
e13ee7ad 625 parse_err = parseConfigFile(ConfigFile);
8a6218c6 626
e13ee7ad 627 if (opt_parse_cfg_only)
628 return parse_err;
629 }
efd900cb 630 if (-1 == opt_send_signal)
631 if (checkRunningPid())
632 exit(1);
e13ee7ad 633
9bc73deb 634#if TEST_ACCESS
635 comm_init();
636 comm_select_init();
637 mainInitialize();
638 test_access();
639 return 0;
640#endif
641
7690e8eb 642 /* send signal to running copy and exit */
643 if (opt_send_signal != -1) {
efd900cb 644 /* chroot if configured to run inside chroot */
645 if (Config.chroot_dir && chroot(Config.chroot_dir)) {
646 fatal("failed to chroot");
647 }
7690e8eb 648 sendSignal();
649 /* NOTREACHED */
650 }
85407535 651 if (opt_create_swap_dirs) {
efd900cb 652 /* chroot if configured to run inside chroot */
653 if (Config.chroot_dir && chroot(Config.chroot_dir)) {
654 fatal("failed to chroot");
655 }
067bea91 656 setEffectiveUser();
657 debug(0, 0) ("Creating Swap Directories\n");
658 storeCreateSwapDirectories();
659 return 0;
660 }
f95b8144 661 if (!opt_no_daemon)
bbe199dc 662 watch_child(argv);
4d64d74a 663 setMaxFD();
664
1758c627 665 if (opt_catch_signals)
e83892e9 666 for (n = Squid_MaxFD; n > 2; n--)
30a4f2a8 667 close(n);
4d64d74a 668
e13ee7ad 669 /* init comm module */
4d64d74a 670 comm_init();
6a988308 671 comm_select_init();
4d64d74a 672
54f742e7 673 if (opt_no_daemon) {
674 /* we have to init fdstat here. */
675 fd_open(0, FD_LOG, "stdin");
676 fd_open(1, FD_LOG, "stdout");
677 fd_open(2, FD_LOG, "stderr");
678 }
4d64d74a 679 mainInitialize();
680
090089c4 681 /* main loop */
983061ed 682 for (;;) {
5cd39a10 683 if (do_reconfigure) {
969c39b9 684 mainReconfigure();
5cd39a10 685 do_reconfigure = 0;
686 } else if (do_rotate) {
687 mainRotate();
688 do_rotate = 0;
2681d383 689 } else if (do_shutdown) {
73c9ccc5 690 time_t wait = do_shutdown > 0 ? (int) Config.shutdownLifetime : 0;
5cd39a10 691 debug(1, 1) ("Preparing for shutdown after %d requests\n",
83704487 692 statCounter.client_http.requests);
5cd39a10 693 debug(1, 1) ("Waiting %d seconds for active connections to finish\n",
73c9ccc5 694 wait);
2681d383 695 do_shutdown = 0;
696 shutting_down = 1;
d723bf6b 697 serverConnectionsClose();
3c573763 698#if USE_DNSSERVERS
74addf6c 699 dnsShutdown();
3c573763 700#else
7b724b86 701 idnsShutdown();
eb824054 702#endif
74addf6c 703 redirectShutdown();
d723bf6b 704 eventAdd("SquidShutdown", SquidShutdown, NULL, (double) (wait + 1), 1);
30a4f2a8 705 }
48f44632 706 eventRun();
707 if ((loop_delay = eventNextTime()) < 0)
4d7add01 708 loop_delay = 0;
812ed90c 709#if HAVE_POLL
710 switch (comm_poll(loop_delay)) {
711#else
9ca89c5a 712 switch (comm_select(loop_delay)) {
812ed90c 713#endif
090089c4 714 case COMM_OK:
234967c9 715 errcount = 0; /* reset if successful */
090089c4 716 break;
717 case COMM_ERROR:
718 errcount++;
a3d5953d 719 debug(1, 0) ("Select loop Error. Retry %d\n", errcount);
090089c4 720 if (errcount == 10)
4d64d74a 721 fatal_dump("Select Loop failed!");
090089c4 722 break;
9ca89c5a 723 case COMM_TIMEOUT:
6c93e119 724 break;
d723bf6b 725 case COMM_SHUTDOWN:
726 SquidShutdown(NULL);
727 break;
090089c4 728 default:
6eb42cae 729 fatal_dump("MAIN: Internal error -- this should never happen.");
090089c4 730 break;
731 }
732 }
733 /* NOTREACHED */
983061ed 734 return 0;
090089c4 735}
7690e8eb 736
b8d8561b 737static void
0673c0ba 738sendSignal(void)
7690e8eb 739{
ff8d0ea6 740 pid_t pid;
fedac7e5 741 debug_log = stderr;
fedac7e5 742 pid = readPidFile();
743 if (pid > 1) {
744 if (kill(pid, opt_send_signal) &&
745 /* ignore permissions if just running check */
746 !(opt_send_signal == 0 && errno == EPERM)) {
747 fprintf(stderr, "%s: ERROR: Could not send ", appname);
748 fprintf(stderr, "signal %d to process %d: %s\n",
41d30aa8 749 opt_send_signal, (int) pid, xstrerror());
7690e8eb 750 exit(1);
751 }
fedac7e5 752 } else {
753 fprintf(stderr, "%s: ERROR: No running copy\n", appname);
754 exit(1);
7690e8eb 755 }
fedac7e5 756 /* signal successfully sent */
757 exit(0);
758}
f95b8144 759
e18d7fdc 760/*
761 * This function is run when Squid is in daemon mode, just
762 * before the parent forks and starts up the child process.
763 * It can be used for admin-specific tasks, such as notifying
764 * someone that Squid is (re)started.
765 */
766static void
767mainStartScript(const char *prog)
768{
769 char script[SQUID_MAXPATHLEN];
770 char *t;
771 size_t sl = 0;
772 pid_t cpid;
773 pid_t rpid;
774 xstrncpy(script, prog, MAXPATHLEN);
775 if ((t = strrchr(script, '/'))) {
776 *(++t) = '\0';
777 sl = strlen(script);
778 }
779 xstrncpy(&script[sl], squid_start_script, MAXPATHLEN - sl);
780 if ((cpid = fork()) == 0) {
781 /* child */
782 execl(script, squid_start_script, 0);
783 _exit(0);
784 } else {
785 do {
786#ifdef _SQUID_NEXT_
787 union wait status;
788 rpid = wait3(&status, 0, NULL);
789#else
790 int status;
791 rpid = waitpid(-1, &status, 0);
792#endif
793 } while (rpid != cpid);
794 }
795}
796
efd900cb 797static int
798checkRunningPid(void)
799{
800 pid_t pid;
801 debug_log = stderr;
802 pid = readPidFile();
803 if (pid < 2)
804 return 0;
805 if (kill(pid, 0) < 0)
806 return 0;
807 debug(0, 0) ("Squid is already running! Process ID %d\n", pid);
808 return 1;
809}
810
f95b8144 811static void
bbe199dc 812watch_child(char *argv[])
f95b8144 813{
814 char *prog;
f95b8144 815 int failcount = 0;
816 time_t start;
817 time_t stop;
818#ifdef _SQUID_NEXT_
819 union wait status;
820#else
821 int status;
822#endif
e3a3b845 823 pid_t pid;
54f742e7 824 int i;
742724a4 825 int nullfd;
f95b8144 826 if (*(argv[0]) == '(')
827 return;
54f742e7 828 openlog(appname, LOG_PID | LOG_NDELAY | LOG_CONS, LOG_LOCAL4);
829 if ((pid = fork()) < 0)
830 syslog(LOG_ALERT, "fork failed: %s", xstrerror());
831 else if (pid > 0)
832 exit(0);
833 if (setsid() < 0)
834 syslog(LOG_ALERT, "setsid failed: %s", xstrerror());
efd900cb 835 closelog();
54f742e7 836#ifdef TIOCNOTTY
c4aefe96 837 if ((i = open("/dev/tty", O_RDWR | O_TEXT)) >= 0) {
54f742e7 838 ioctl(i, TIOCNOTTY, NULL);
839 close(i);
840 }
841#endif
b05490a8 842
843
7f6ffd15 844 /*
845 * RBCOLLINS - if cygwin stackdumps when squid is run without
846 * -N, check the cygwin1.dll version, it needs to be AT LEAST
847 * 1.1.3. execvp had a bit overflow error in a loop..
848 */
742724a4 849 /* Connect stdio to /dev/null in daemon mode */
c4aefe96 850 nullfd = open("/dev/null", O_RDWR | O_TEXT);
742724a4 851 dup2(nullfd, 0);
852 if (opt_debug_stderr < 0) {
853 dup2(nullfd, 1);
854 dup2(nullfd, 2);
855 }
856 /* Close all else */
857 for (i = 3; i < Squid_MaxFD; i++)
54f742e7 858 close(i);
f95b8144 859 for (;;) {
e18d7fdc 860 mainStartScript(argv[0]);
54f742e7 861 if ((pid = fork()) == 0) {
f95b8144 862 /* child */
efd900cb 863 openlog(appname, LOG_PID | LOG_NDELAY | LOG_CONS, LOG_LOCAL4);
f95b8144 864 prog = xstrdup(argv[0]);
bbe199dc 865 argv[0] = xstrdup("(squid)");
866 execvp(prog, argv);
54f742e7 867 syslog(LOG_ALERT, "execvp failed: %s", xstrerror());
f95b8144 868 }
54f742e7 869 /* parent */
efd900cb 870 openlog(appname, LOG_PID | LOG_NDELAY | LOG_CONS, LOG_LOCAL4);
54f742e7 871 syslog(LOG_NOTICE, "Squid Parent: child process %d started", pid);
872 time(&start);
873 squid_signal(SIGINT, SIG_IGN, SA_RESTART);
f95b8144 874#ifdef _SQUID_NEXT_
54f742e7 875 pid = wait3(&status, 0, NULL);
f95b8144 876#else
54f742e7 877 pid = waitpid(-1, &status, 0);
f95b8144 878#endif
879 time(&stop);
54f742e7 880 if (WIFEXITED(status)) {
881 syslog(LOG_NOTICE,
882 "Squid Parent: child process %d exited with status %d",
883 pid, WEXITSTATUS(status));
884 } else if (WIFSIGNALED(status)) {
885 syslog(LOG_NOTICE,
886 "Squid Parent: child process %d exited due to signal %d",
887 pid, WTERMSIG(status));
888 } else {
889 syslog(LOG_NOTICE, "Squid Parent: child process %d exited", pid);
890 }
f95b8144 891 if (stop - start < 10)
892 failcount++;
a8e69881 893 else
894 failcount = 0;
54f742e7 895 if (failcount == 5) {
896 syslog(LOG_ALERT, "Exiting due to repeated, frequent failures");
f95b8144 897 exit(1);
54f742e7 898 }
f95b8144 899 if (WIFEXITED(status))
900 if (WEXITSTATUS(status) == 0)
901 exit(0);
0fb4fc71 902 squid_signal(SIGINT, SIG_DFL, SA_RESTART);
f95b8144 903 sleep(3);
904 }
bbe199dc 905 /* NOTREACHED */
f95b8144 906}
fff6ad65 907
9ec1a1dc 908static void
d723bf6b 909SquidShutdown(void *unused)
fff6ad65 910{
911 debug(1, 1) ("Shutting down...\n");
912 if (Config.pidFilename && strcmp(Config.pidFilename, "none")) {
913 enter_suid();
914 safeunlink(Config.pidFilename, 0);
915 leave_suid();
916 }
d723bf6b 917 icpConnectionClose();
918#if USE_HTCP
919 htcpSocketClose();
920#endif
921#ifdef SQUID_SNMP
922 snmpConnectionClose();
320e9f36 923#endif
eb824054 924#if USE_WCCP
320e9f36 925 wccpConnectionClose();
d723bf6b 926#endif
fff6ad65 927 releaseServerSockets();
d723bf6b 928 commCloseAllSockets();
5dae8514 929 authenticateShutdown();
a3d0a19d 930#if USE_UNLINKD
fff6ad65 931 unlinkdClose();
a3d0a19d 932#endif
cd748f27 933 storeDirSync(); /* Flush pending object writes/unlinks */
fff6ad65 934 storeDirWriteCleanLogs(0);
935 PrintRusage();
936 dumpMallocStats();
cd748f27 937 storeDirSync(); /* Flush log writes */
fff6ad65 938 storeLogClose();
939 accessLogClose();
225644d7 940#if WIP_FWD_LOG
941 fwdUninit();
942#endif
cd748f27 943 storeDirSync(); /* Flush log close */
33ab18e8 944#if PURIFY || XMALLOC_TRACE
cd748f27 945 storeFsDone();
fff6ad65 946 configFreeMemory();
947 storeFreeMemory();
33ab18e8 948 /*stmemFreeMemory(); */
fff6ad65 949 netdbFreeMemory();
950 ipcacheFreeMemory();
951 fqdncacheFreeMemory();
952 asnFreeMemory();
26a369ba 953 clientdbFreeMemory();
7021844c 954 httpHeaderCleanModule();
d2db411c 955 statFreeMemory();
f1fc2a8d 956 eventFreeMemory();
c68e9c6b 957 mimeFreeMemory();
958 errorClean();
fff6ad65 959#endif
26a369ba 960#if !XMALLOC_TRACE
54f742e7 961 if (opt_no_daemon) {
962 file_close(0);
963 file_close(1);
964 file_close(2);
965 }
33ab18e8 966#endif
fff6ad65 967 fdDumpOpen();
968 fdFreeMemory();
ddb43c58 969 memClean();
33ab18e8 970#if XMALLOC_TRACE
26a369ba 971 xmalloc_find_leaks();
972 debug(1, 0) ("Memory used after shutdown: %d\n", xmalloc_total);
33ab18e8 973#endif
36a97e19 974#if MEM_GEN_TRACE
399e85ea 975 log_trace_done();
36a97e19 976#endif
a60f7062 977 debug(1, 1) ("Squid Cache (Version %s): Exiting normally.\n",
fff6ad65 978 version_string);
7e3ce7b9 979 if (debug_log)
980 fclose(debug_log);
fff6ad65 981 exit(0);
982}