]> git.ipfire.org Git - thirdparty/squid.git/blame - src/main.cc
Summary: Add squid-3.0 release notes.
[thirdparty/squid.git] / src / main.cc
CommitLineData
a47b9029 1
30a4f2a8 2/*
b0dd28ba 3 * $Id: main.cc,v 1.369 2003/02/25 12:24:35 robertc 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"
e6ccf245 37#include "authenticate.h"
38#include "Store.h"
39#include "ICP.h"
528b2c61 40#include "HttpReply.h"
41#include "Mem.h"
b0dd28ba 42#include "ACLASN.h"
43#include "ACL.h"
44a47c6e 44
30a4f2a8 45/* for error reporting from xmalloc and friends */
ea3a2a69 46extern void (*failure_notify) (const char *);
30a4f2a8 47
f1dc9b30 48static int opt_send_signal = -1;
f95b8144 49static int opt_no_daemon = 0;
e13ee7ad 50static int opt_parse_cfg_only = 0;
30a4f2a8 51static int icpPortNumOverride = 1; /* Want to detect "-u 0" */
e13ee7ad 52static int configured_once = 0;
30a4f2a8 53#if MALLOC_DBG
4d64d74a 54static int malloc_debug_level = 0;
30a4f2a8 55#endif
5cd39a10 56static volatile int do_reconfigure = 0;
57static volatile int do_rotate = 0;
2681d383 58static volatile int do_shutdown = 0;
4d7add01 59
5cd39a10 60static void mainRotate(void);
61static void mainReconfigure(void);
b984c445 62static SIGHDLR rotate_logs;
63static SIGHDLR reconfigure;
f5b8bbc4 64static void mainInitialize(void);
f5b8bbc4 65static void usage(void);
66static void mainParseOptions(int, char **);
67static void sendSignal(void);
68static void serverConnectionsOpen(void);
bbe199dc 69static void watch_child(char **);
85407535 70static void setEffectiveUser(void);
36a97e19 71#if MEM_GEN_TRACE
72extern void log_trace_done();
73extern void log_trace_init(char *);
74#endif
d723bf6b 75static EVH SquidShutdown;
b6a2f15e 76static void mainSetCwd(void);
efd900cb 77static int checkRunningPid(void);
85407535 78
e18d7fdc 79static const char *squid_start_script = "squid_start";
80
9bc73deb 81#if TEST_ACCESS
82#include "test_access.c"
83#endif
84
b8d8561b 85static void
0673c0ba 86usage(void)
ccff9601 87{
0ee4272b 88 fprintf(stderr,
62e76326 89 "Usage: %s [-dhsvzCDFNRVYX] [-f config-file] [-[au] port] [-k signal]\n"
90 " -a port Specify HTTP port number (default: %d).\n"
91 " -d level Write debugging to stderr also.\n"
92 " -f file Use given config-file instead of\n"
93 " %s\n"
94 " -h Print help message.\n"
95 " -k reconfigure|rotate|shutdown|interrupt|kill|debug|check|parse\n"
96 " Parse configuration file, then send signal to \n"
97 " running copy (except -k parse) and exit.\n"
98 " -s Enable logging to syslog.\n"
99 " -u port Specify ICP port number (default: %d), disable with 0.\n"
100 " -v Print version.\n"
101 " -z Create swap directories\n"
102 " -C Do not catch fatal signals.\n"
103 " -D Disable initial DNS tests.\n"
104 " -F Don't serve any requests until store is rebuilt.\n"
105 " -N No daemon mode.\n"
106 " -R Do not set REUSEADDR on port.\n"
107 " -S Double-check swap during rebuild.\n"
108 " -V Virtual host httpd-accelerator.\n"
109 " -X Force full debugging.\n"
110 " -Y Only return UDP_HIT or UDP_MISS_NOFETCH during fast reload.\n",
111 appname, CACHE_HTTP_PORT, DefaultConfigFile, CACHE_ICP_PORT);
77ffc99f 112 exit(1);
ccff9601 113}
114
b8d8561b 115static void
116mainParseOptions(int argc, char *argv[])
090089c4 117{
090089c4 118 extern char *optarg;
4d64d74a 119 int c;
090089c4 120
504123ec 121 while ((c = getopt(argc, argv, "CDFNRSVYXa:d:f:hk:m::su:vz?")) != -1) {
62e76326 122 switch (c) {
123
124 case 'C':
125 opt_catch_signals = 0;
126 break;
127
128 case 'D':
129 opt_dns_tests = 0;
130 break;
131
132 case 'F':
133 opt_foreground_rebuild = 1;
134 break;
135
136 case 'N':
137 opt_no_daemon = 1;
138 break;
139
140 case 'R':
141 opt_reuseaddr = 0;
142 break;
143
144 case 'S':
145 opt_store_doublecheck = 1;
146 break;
147
148 case 'V':
149
150 if (Config.Sockaddr.http)
151 Config.Sockaddr.http->vhost = 1;
152
3f38a55e 153#if USE_SSL
62e76326 154
155 else if (Config.Sockaddr.https)
156 Config.Sockaddr.https->http.vhost = 1;
157
158#endif
159
160 else
161 fatal("No http_port specified\n");
162
163 break;
164
165 case 'X':
166 /* force full debugging */
167 sigusr2_handle(SIGUSR2);
168
169 break;
170
171 case 'Y':
172 opt_reload_hit_only = 1;
173
174 break;
175
176 case 'a':
177 add_http_port(optarg);
178
179 break;
180
181 case 'd':
182 opt_debug_stderr = atoi(optarg);
183
184 break;
185
186 case 'f':
187 xfree(ConfigFile);
188
189 ConfigFile = xstrdup(optarg);
190
191 break;
192
193 case 'h':
194 usage();
195
196 break;
197
198 case 'k':
199 if ((int) strlen(optarg) < 1)
200 usage();
201
202 if (!strncmp(optarg, "reconfigure", strlen(optarg)))
203 opt_send_signal = SIGHUP;
204 else if (!strncmp(optarg, "rotate", strlen(optarg)))
7e7a0442 205#ifdef _SQUID_LINUX_THREADS_
62e76326 206
207 opt_send_signal = SIGQUIT;
208
e3175d1f 209#else
62e76326 210
211 opt_send_signal = SIGUSR1;
212
e3175d1f 213#endif
62e76326 214
215 else if (!strncmp(optarg, "debug", strlen(optarg)))
7e7a0442 216#ifdef _SQUID_LINUX_THREADS_
62e76326 217
218 opt_send_signal = SIGTRAP;
219
e3175d1f 220#else
62e76326 221
222 opt_send_signal = SIGUSR2;
223
224#endif
225
226 else if (!strncmp(optarg, "shutdown", strlen(optarg)))
227 opt_send_signal = SIGTERM;
228 else if (!strncmp(optarg, "interrupt", strlen(optarg)))
229 opt_send_signal = SIGINT;
230 else if (!strncmp(optarg, "kill", strlen(optarg)))
231 opt_send_signal = SIGKILL;
232 else if (!strncmp(optarg, "check", strlen(optarg)))
233 opt_send_signal = 0; /* SIGNULL */
234 else if (!strncmp(optarg, "parse", strlen(optarg)))
235 opt_parse_cfg_only = 1; /* parse cfg file only */
236 else
237 usage();
238
239 break;
240
241 case 'm':
242 if (optarg) {
30a4f2a8 243#if MALLOC_DBG
62e76326 244 malloc_debug_level = atoi(optarg);
245 /* NOTREACHED */
246 break;
30a4f2a8 247#else
62e76326 248
249 fatal("Need to add -DMALLOC_DBG when compiling to use -mX option");
250 /* NOTREACHED */
33ab18e8 251#endif
62e76326 252
253 } else {
33ab18e8 254#if XMALLOC_TRACE
62e76326 255 xmalloc_trace = !xmalloc_trace;
33ab18e8 256#else
62e76326 257
258 fatal("Need to configure --enable-xmalloc-debug-trace to use -m option");
30a4f2a8 259#endif
62e76326 260
261 }
262
263 case 's':
c307aec3 264#if HAVE_SYSLOG
62e76326 265
266 opt_syslog_enable = 1;
267 break;
c307aec3 268#else
62e76326 269
270 fatal("Logging to syslog not available on this platform");
271 /* NOTREACHED */
272#endif
273
274 case 'u':
275 icpPortNumOverride = atoi(optarg);
276
277 if (icpPortNumOverride < 0)
278 icpPortNumOverride = 0;
279
280 break;
281
282 case 'v':
283 printf("Squid Cache: Version %s\nconfigure options: %s\n", version_string, SQUID_CONFIGURE_OPTIONS);
284
285 exit(0);
286
287 /* NOTREACHED */
288
289 case 'z':
290 opt_create_swap_dirs = 1;
291
292 break;
293
294 case '?':
295
296 default:
297 usage();
298
299 break;
300 }
090089c4 301 }
4d64d74a 302}
090089c4 303
7a2f978b 304/* ARGSUSED */
b8d8561b 305static void
306rotate_logs(int sig)
30a4f2a8 307{
5cd39a10 308 do_rotate = 1;
30a4f2a8 309#if !HAVE_SIGACTION
62e76326 310
30a4f2a8 311 signal(sig, rotate_logs);
312#endif
313}
314
7a2f978b 315/* ARGSUSED */
b8d8561b 316static void
317reconfigure(int sig)
30a4f2a8 318{
5cd39a10 319 do_reconfigure = 1;
30a4f2a8 320#if !HAVE_SIGACTION
62e76326 321
30a4f2a8 322 signal(sig, reconfigure);
323#endif
324}
325
b8d8561b 326void
327shut_down(int sig)
30a4f2a8 328{
2681d383 329 do_shutdown = sig == SIGINT ? -1 : 1;
cadc2d55 330#ifdef KILL_PARENT_OPT
62e76326 331
5cd39a10 332 if (getppid() > 1) {
62e76326 333 debug(1, 1) ("Killing RunCache, pid %d\n", getppid());
334
335 if (kill(getppid(), sig) < 0)
336 debug(1, 1) ("kill %d: %s\n", getppid(), xstrerror());
88738790 337 }
62e76326 338
cadc2d55 339#endif
6e40f263 340#if SA_RESETHAND == 0
341 signal(SIGTERM, SIG_DFL);
62e76326 342
6e40f263 343 signal(SIGINT, SIG_DFL);
62e76326 344
6e40f263 345#endif
30a4f2a8 346}
347
24382924 348static void
0673c0ba 349serverConnectionsOpen(void)
4d64d74a 350{
d193a436 351 clientOpenListenSockets();
15df8349 352 icpConnectionsOpen();
ace287ee 353#if USE_HTCP
62e76326 354
ace287ee 355 htcpInit();
356#endif
678c6099 357#ifdef SQUID_SNMP
62e76326 358
3265e68d 359 snmpConnectionOpen();
320e9f36 360#endif
eb824054 361#if USE_WCCP
62e76326 362
320e9f36 363 wccpConnectionOpen();
2bbd722b 364#endif
62e76326 365
5ecceaa4 366 clientdbInit();
16b204c4 367 icmpOpen();
67508012 368 netdbInit();
f899fac1 369 asnInit();
b0dd28ba 370 ACL::Initialize();
85034133 371 peerSelectInit();
afd88fbe 372#if USE_CARP
62e76326 373
afd88fbe 374 carpInit();
375#endif
5f3f8d0e 376}
377
b8d8561b 378void
0673c0ba 379serverConnectionsClose(void)
5f3f8d0e 380{
0a5a8601 381 assert(shutting_down || reconfiguring);
c0fbae16 382 clientHttpConnectionsClose();
17e6c0a1 383 icpConnectionShutdown();
72549e05 384#if USE_HTCP
62e76326 385
72549e05 386 htcpSocketShutdown();
387#endif
62e76326 388
c0fbae16 389 icmpClose();
15df8349 390#ifdef SQUID_SNMP
62e76326 391
17e6c0a1 392 snmpConnectionShutdown();
320e9f36 393#endif
eb824054 394#if USE_WCCP
62e76326 395
320e9f36 396 wccpConnectionShutdown();
15df8349 397#endif
62e76326 398
4bac8de8 399 asnFreeMemory();
5f3f8d0e 400}
401
b8d8561b 402static void
dbe4fd8e 403mainReconfigure(void)
5f3f8d0e 404{
a60f7062 405 debug(1, 1) ("Restarting Squid Cache (version %s)...\n", version_string);
5cd39a10 406 reconfiguring = 1;
0ffd22bc 407 /* Already called serverConnectionsClose and ipcacheShutdownServers() */
15df8349 408 serverConnectionsClose();
17e6c0a1 409 icpConnectionClose();
72549e05 410#if USE_HTCP
62e76326 411
72549e05 412 htcpSocketClose();
413#endif
17e6c0a1 414#ifdef SQUID_SNMP
62e76326 415
17e6c0a1 416 snmpConnectionClose();
320e9f36 417#endif
eb824054 418#if USE_WCCP
62e76326 419
320e9f36 420 wccpConnectionClose();
17e6c0a1 421#endif
3c573763 422#if USE_DNSSERVERS
62e76326 423
74addf6c 424 dnsShutdown();
3c573763 425#else
62e76326 426
7b724b86 427 idnsShutdown();
eb824054 428#endif
62e76326 429
74addf6c 430 redirectShutdown();
431 authenticateShutdown();
d9572179 432 externalAclShutdown();
2db68ce5 433 storeDirCloseSwapLogs();
c68e9c6b 434 errorClean();
3aa4adbc 435 enter_suid(); /* root to read config file */
00fac1f8 436 parseConfigFile(ConfigFile);
3aa4adbc 437 setEffectiveUser();
b6f794d6 438 _db_init(Config.Log.log, Config.debugOptions);
429fdbec 439 ipcache_restart(); /* clear stuck entries */
94439e4e 440 authenticateUserCacheRestart(); /* clear stuck ACL entries */
429fdbec 441 fqdncache_restart(); /* sigh, fqdncache too */
0e70aa1e 442 parseEtcHosts();
53ad48e6 443 errorInitialize(); /* reload error pages */
3c573763 444#if USE_DNSSERVERS
62e76326 445
74addf6c 446 dnsInit();
3c573763 447#else
62e76326 448
7b724b86 449 idnsInit();
eb824054 450#endif
62e76326 451
74addf6c 452 redirectInit();
e6ccf245 453 authenticateInit(&Config.authConfiguration);
d9572179 454 externalAclInit();
1f38f50a 455#if USE_WCCP
62e76326 456
1f38f50a 457 wccpInit();
458#endif
62e76326 459
0ffd22bc 460 serverConnectionsOpen();
a86029b9 461 neighbors_init();
2db68ce5 462 storeDirOpenSwapLogs();
9c021a38 463 mimeInit(Config.mimeTablePathname);
b8890359 464 writePidFile(); /* write PID file */
aebbcd07 465 debug(1, 1) ("Ready to serve requests.\n");
5cd39a10 466 reconfiguring = 0;
467}
468
469static void
470mainRotate(void)
471{
472 icmpClose();
3c573763 473#if USE_DNSSERVERS
62e76326 474
e40aa8da 475 dnsShutdown();
3c573763 476#endif
62e76326 477
e40aa8da 478 redirectShutdown();
479 authenticateShutdown();
d9572179 480 externalAclShutdown();
5cd39a10 481 _db_rotate_log(); /* cache.log */
482 storeDirWriteCleanLogs(1);
483 storeLogRotate(); /* store.log */
484 accessLogRotate(); /* access.log */
485 useragentRotateLog(); /* useragent.log */
fd2c5549 486 refererRotateLog(); /* referer.log */
225644d7 487#if WIP_FWD_LOG
62e76326 488
225644d7 489 fwdLogRotate();
490#endif
62e76326 491
5cd39a10 492 icmpOpen();
3c573763 493#if USE_DNSSERVERS
62e76326 494
e40aa8da 495 dnsInit();
3c573763 496#endif
62e76326 497
e40aa8da 498 redirectInit();
e6ccf245 499 authenticateInit(&Config.authConfiguration);
d9572179 500 externalAclInit();
5f3f8d0e 501}
502
067bea91 503static void
85407535 504setEffectiveUser(void)
505{
506 leave_suid(); /* Run as non privilegied user */
cd377065 507#ifdef _SQUID_OS2_
62e76326 508
cd377065 509 return;
510#endif
62e76326 511
85407535 512 if (geteuid() == 0) {
62e76326 513 debug(0, 0) ("Squid is not safe to run as root! If you must\n");
514 debug(0, 0) ("start Squid as root, then you must configure\n");
515 debug(0, 0) ("it to run as a non-priveledged user with the\n");
516 debug(0, 0) ("'cache_effective_user' option in the config file.\n");
517 fatal("Don't run Squid as root, set 'cache_effective_user'!");
85407535 518 }
519}
520
b6a2f15e 521static void
522mainSetCwd(void)
523{
4a504376 524 char pathbuf[MAXPATHLEN];
62e76326 525
b6a2f15e 526 if (Config.coredump_dir) {
62e76326 527 if (0 == strcmp("none", Config.coredump_dir)) {
528 (void) 0;
529 } else if (chdir(Config.coredump_dir) == 0) {
530 debug(0, 1) ("Set Current Directory to %s\n", Config.coredump_dir);
531 return;
532 } else {
533 debug(50, 0) ("chdir: %s: %s\n", Config.coredump_dir, xstrerror());
534 }
b6a2f15e 535 }
62e76326 536
02e8115e 537 /* If we don't have coredump_dir or couldn't cd there, report current dir */
4a504376 538 if (getcwd(pathbuf, MAXPATHLEN)) {
62e76326 539 debug(0, 1) ("Current Directory is %s\n", pathbuf);
4a504376 540 } else {
62e76326 541 debug(50, 0) ("WARNING: Can't find current directory, getcwd: %s\n", xstrerror());
4a504376 542 }
b6a2f15e 543}
544
b67e2c8c 545#if DELAY_POOLS
546#include "DelayPools.h"
547#endif
548
b8d8561b 549static void
0673c0ba 550mainInitialize(void)
5f3f8d0e 551{
efd900cb 552 /* chroot if configured to run inside chroot */
62e76326 553
efd900cb 554 if (Config.chroot_dir && chroot(Config.chroot_dir)) {
62e76326 555 fatal("failed to chroot");
efd900cb 556 }
62e76326 557
1758c627 558 if (opt_catch_signals) {
62e76326 559 squid_signal(SIGSEGV, death, SA_NODEFER | SA_RESETHAND);
560 squid_signal(SIGBUS, death, SA_NODEFER | SA_RESETHAND);
44f99671 561 }
62e76326 562
30a4f2a8 563 squid_signal(SIGPIPE, SIG_IGN, SA_RESTART);
564 squid_signal(SIGCHLD, sig_child, SA_NODEFER | SA_RESTART);
44f99671 565
85407535 566 setEffectiveUser();
62e76326 567
30a4f2a8 568 if (icpPortNumOverride != 1)
62e76326 569 Config.Port.icp = (u_short) icpPortNumOverride;
30a4f2a8 570
b6f794d6 571 _db_init(Config.Log.log, Config.debugOptions);
62e76326 572
5c5783a2 573 fd_open(fileno(debug_log), FD_LOG, Config.Log.log);
62e76326 574
71a17702 575#if MEM_GEN_TRACE
62e76326 576
71a17702 577 log_trace_init("/tmp/squid.alloc");
62e76326 578
71a17702 579#endif
62e76326 580
a3d5953d 581 debug(1, 0) ("Starting Squid Cache version %s for %s...\n",
62e76326 582 version_string,
583 CONFIG_HOST_TYPE);
584
aebbcd07 585 debug(1, 1) ("Process ID %d\n", (int) getpid());
62e76326 586
a3d5953d 587 debug(1, 1) ("With %d file descriptors available\n", Squid_MaxFD);
5f3f8d0e 588
9f75c559 589 if (!configured_once)
62e76326 590 disk_init(); /* disk_init must go before ipcache_init() */
591
5f3f8d0e 592 ipcache_init();
62e76326 593
f88bb09c 594 fqdncache_init();
62e76326 595
0e70aa1e 596 parseEtcHosts();
62e76326 597
3c573763 598#if USE_DNSSERVERS
62e76326 599
74addf6c 600 dnsInit();
62e76326 601
3c573763 602#else
62e76326 603
7b724b86 604 idnsInit();
62e76326 605
eb824054 606#endif
62e76326 607
74addf6c 608 redirectInit();
62e76326 609
e6ccf245 610 authenticateInit(&Config.authConfiguration);
62e76326 611
d9572179 612 externalAclInit();
62e76326 613
b012353a 614 useragentOpenLog();
62e76326 615
fd2c5549 616 refererOpenLog();
62e76326 617
2ac76861 618 httpHeaderInitModule(); /* must go before any header processing (e.g. the one in errorInitialize) */
62e76326 619
2246b732 620 httpReplyInitModule(); /* must go before accepting replies */
62e76326 621
9b312a19 622 errorInitialize();
62e76326 623
7a2f978b 624 accessLogInit();
62e76326 625
3898f57f 626#if USE_IDENT
62e76326 627
05832ae1 628 identInit();
62e76326 629
3898f57f 630#endif
5e14bf6d 631#ifdef SQUID_SNMP
62e76326 632
5e14bf6d 633 snmpInit();
62e76326 634
5e14bf6d 635#endif
30a4f2a8 636#if MALLOC_DBG
62e76326 637
5f3f8d0e 638 malloc_debug(0, malloc_debug_level);
62e76326 639
5f3f8d0e 640#endif
641
dbe4fd8e 642 if (!configured_once) {
a3d0a19d 643#if USE_UNLINKD
62e76326 644 unlinkdInit();
645#endif
646
647 urlInitialize();
648 cachemgrInit();
649 statInit();
650 storeInit();
651 mainSetCwd();
652 /* after this point we want to see the mallinfo() output */
653 do_mallinfo = 1;
654 mimeInit(Config.mimeTablePathname);
655 pconnInit();
656 refreshInit();
0d7e5d78 657#if DELAY_POOLS
62e76326 658
659 DelayPools::Init();
0d7e5d78 660#endif
62e76326 661
662 fwdInit();
5f3f8d0e 663 }
62e76326 664
1f38f50a 665#if USE_WCCP
666 wccpInit();
62e76326 667
1f38f50a 668#endif
62e76326 669
2285407f 670 serverConnectionsOpen();
62e76326 671
a86029b9 672 neighbors_init();
62e76326 673
efd900cb 674 if (Config.chroot_dir)
62e76326 675 no_suid();
676
dbe4fd8e 677 if (!configured_once)
62e76326 678 writePidFile(); /* write PID file */
0a5b9b32 679
7e7a0442 680#ifdef _SQUID_LINUX_THREADS_
62e76326 681
e3175d1f 682 squid_signal(SIGQUIT, rotate_logs, SA_RESTART);
62e76326 683
e3175d1f 684 squid_signal(SIGTRAP, sigusr2_handle, SA_RESTART);
62e76326 685
e3175d1f 686#else
62e76326 687
30a4f2a8 688 squid_signal(SIGUSR1, rotate_logs, SA_RESTART);
62e76326 689
30a4f2a8 690 squid_signal(SIGUSR2, sigusr2_handle, SA_RESTART);
62e76326 691
9fc0b4b8 692#endif
62e76326 693
30a4f2a8 694 squid_signal(SIGHUP, reconfigure, SA_RESTART);
62e76326 695
30a4f2a8 696 squid_signal(SIGTERM, shut_down, SA_NODEFER | SA_RESETHAND | SA_RESTART);
62e76326 697
30a4f2a8 698 squid_signal(SIGINT, shut_down, SA_NODEFER | SA_RESETHAND | SA_RESTART);
62e76326 699
58a39dc9 700 memCheckInit();
62e76326 701
aebbcd07 702 debug(1, 1) ("Ready to serve requests.\n");
62e76326 703
dbe4fd8e 704 if (!configured_once) {
62e76326 705 eventAdd("storeMaintain", storeMaintainSwapSpace, NULL, 1.0, 1);
706
707 if (Config.onoff.announce)
708 eventAdd("start_announce", start_announce, NULL, 3600.0, 1);
709
710 eventAdd("ipcache_purgelru", ipcache_purgelru, NULL, 10.0, 1);
711
712 eventAdd("fqdncache_purgelru", fqdncache_purgelru, NULL, 15.0, 1);
713
88bfe092 714#if USE_XPROF_STATS
62e76326 715
716 eventAdd("cpuProfiling", xprof_event, NULL, 1.0, 1);
717
88bfe092 718#endif
62e76326 719
720 eventAdd("memPoolCleanIdlePools", Mem::CleanIdlePools, NULL, 15.0, 1);
4d7add01 721 }
62e76326 722
dbe4fd8e 723 configured_once = 1;
4d64d74a 724}
725
b8d8561b 726int
727main(int argc, char **argv)
4d64d74a 728{
729 int errcount = 0;
4d64d74a 730 int n; /* # of GC'd objects */
7e3ce7b9 731 mode_t oldmask;
0e6d05ef 732#if defined(_SQUID_MSWIN_) || defined(_SQUID_CYGWIN_)
62e76326 733
0e6d05ef 734 int WIN32_init_err;
735#endif
4d64d74a 736
a4ba1105 737#if HAVE_SBRK
62e76326 738
a4ba1105 739 sbrk_start = sbrk(0);
740#endif
741
88738790 742 debug_log = stderr;
62e76326 743
e83892e9 744 if (FD_SETSIZE < Squid_MaxFD)
62e76326 745 Squid_MaxFD = FD_SETSIZE;
399e85ea 746
0e6d05ef 747#if defined(_SQUID_MSWIN_) || defined(_SQUID_CYGWIN_)
62e76326 748
35fb8810 749 if ((WIN32_init_err = WIN32_Subsystem_Init()))
62e76326 750 return WIN32_init_err;
751
0e6d05ef 752#endif
753
7328e889 754 /* call mallopt() before anything else */
0b29fe44 755#if HAVE_MALLOPT
7328e889 756#ifdef M_GRAIN
757 /* Round up all sizes to a multiple of this */
758 mallopt(M_GRAIN, 16);
62e76326 759
7328e889 760#endif
761#ifdef M_MXFAST
762 /* biggest size that is considered a small block */
763 mallopt(M_MXFAST, 256);
62e76326 764
7328e889 765#endif
766#ifdef M_NBLKS
767 /* allocate this many small blocks at once */
768 mallopt(M_NLBLKS, 32);
62e76326 769
7328e889 770#endif
771#endif /* HAVE_MALLOPT */
772
7e3ce7b9 773 /*
774 * The plan here is to set the umask to 007 (deny others for
775 * read,write,execute), but only if the umask is not already
776 * set. Unfortunately, there is no way to get the current
777 * umask value without setting it.
778 */
779 oldmask = umask(S_IRWXO);
62e76326 780
7e3ce7b9 781 if (oldmask)
62e76326 782 umask(oldmask);
7e3ce7b9 783
30a4f2a8 784 memset(&local_addr, '\0', sizeof(struct in_addr));
62e76326 785
429fdbec 786 safe_inet_addr(localhost, &local_addr);
62e76326 787
28070024 788 memset(&any_addr, '\0', sizeof(struct in_addr));
62e76326 789
429fdbec 790 safe_inet_addr("0.0.0.0", &any_addr);
62e76326 791
28070024 792 memset(&no_addr, '\0', sizeof(struct in_addr));
62e76326 793
429fdbec 794 safe_inet_addr("255.255.255.255", &no_addr);
62e76326 795
88738790 796 squid_srandom(time(NULL));
4d64d74a 797
f2908497 798 getCurrentTime();
62e76326 799
f2908497 800 squid_start = current_time;
62e76326 801
4d64d74a 802 failure_notify = fatal_dump;
803
804 mainParseOptions(argc, argv);
805
e13ee7ad 806 /* parse configuration file
807 * note: in "normal" case this used to be called from mainInitialize() */
808 {
62e76326 809 int parse_err;
810
811 if (!ConfigFile)
812 ConfigFile = xstrdup(DefaultConfigFile);
813
814 assert(!configured_once);
815
5d620373 816#if USE_LEAKFINDER
62e76326 817
818 leakInit();
819
5d620373 820#endif
8a6218c6 821
62e76326 822 Mem::Init();
823
824 cbdataInit();
825
826 eventInit(); /* eventInit() is required for config parsing */
827
828 storeFsInit(); /* required for config parsing */
829
830 authenticateSchemeInit(); /* required for config parsign */
831
832 parse_err = parseConfigFile(ConfigFile);
833
834 if (opt_parse_cfg_only)
835 return parse_err;
e13ee7ad 836 }
efd900cb 837 if (-1 == opt_send_signal)
62e76326 838 if (checkRunningPid())
839 exit(1);
e13ee7ad 840
9bc73deb 841#if TEST_ACCESS
62e76326 842
9bc73deb 843 comm_init();
62e76326 844
9bc73deb 845 comm_select_init();
62e76326 846
9bc73deb 847 mainInitialize();
62e76326 848
9bc73deb 849 test_access();
62e76326 850
9bc73deb 851 return 0;
62e76326 852
9bc73deb 853#endif
854
7690e8eb 855 /* send signal to running copy and exit */
856 if (opt_send_signal != -1) {
62e76326 857 /* chroot if configured to run inside chroot */
858
859 if (Config.chroot_dir && chroot(Config.chroot_dir)) {
860 fatal("failed to chroot");
861 }
862
863 sendSignal();
864 /* NOTREACHED */
7690e8eb 865 }
62e76326 866
85407535 867 if (opt_create_swap_dirs) {
62e76326 868 /* chroot if configured to run inside chroot */
869
870 if (Config.chroot_dir && chroot(Config.chroot_dir)) {
871 fatal("failed to chroot");
872 }
873
874 setEffectiveUser();
875 debug(0, 0) ("Creating Swap Directories\n");
876 storeCreateSwapDirectories();
877 return 0;
067bea91 878 }
62e76326 879
f95b8144 880 if (!opt_no_daemon)
62e76326 881 watch_child(argv);
882
4d64d74a 883 setMaxFD();
884
1758c627 885 if (opt_catch_signals)
62e76326 886 for (n = Squid_MaxFD; n > 2; n--)
887 close(n);
4d64d74a 888
e13ee7ad 889 /* init comm module */
4d64d74a 890 comm_init();
62e76326 891
6a988308 892 comm_select_init();
4d64d74a 893
54f742e7 894 if (opt_no_daemon) {
62e76326 895 /* we have to init fdstat here. */
896 fd_open(0, FD_LOG, "stdin");
897 fd_open(1, FD_LOG, "stdout");
898 fd_open(2, FD_LOG, "stderr");
54f742e7 899 }
62e76326 900
4d64d74a 901 mainInitialize();
902
090089c4 903 /* main loop */
62e76326 904
983061ed 905 for (;;) {
62e76326 906 if (do_reconfigure) {
907 mainReconfigure();
908 do_reconfigure = 0;
909 } else if (do_rotate) {
910 mainRotate();
911 do_rotate = 0;
912 } else if (do_shutdown) {
913 time_t wait = do_shutdown > 0 ? (int) Config.shutdownLifetime : 0;
914 debug(1, 1) ("Preparing for shutdown after %d requests\n",
915 statCounter.client_http.requests);
916 debug(1, 1) ("Waiting %d seconds for active connections to finish\n",
917 (int) wait);
918 do_shutdown = 0;
919 shutting_down = 1;
920 serverConnectionsClose();
3c573763 921#if USE_DNSSERVERS
62e76326 922
923 dnsShutdown();
3c573763 924#else
62e76326 925
926 idnsShutdown();
eb824054 927#endif
62e76326 928
929 redirectShutdown();
930 externalAclShutdown();
931 eventAdd("SquidShutdown", SquidShutdown, NULL, (double) (wait + 1), 1);
932 }
933
934 eventRun();
f24629ba 935 int loop_delay = eventNextTime();
62e76326 936
937 if (loop_delay < 0)
938 loop_delay = 0;
939
a48a31d5 940 /* Attempt any pending storedir IO */
941 storeDirCallback();
62e76326 942
943 comm_calliocallback();
944
945 switch (comm_select(loop_delay)) {
946
947 case COMM_OK:
948 errcount = 0; /* reset if successful */
949 break;
950
951 case COMM_ERROR:
952 errcount++;
953 debug(1, 0) ("Select loop Error. Retry %d\n", errcount);
954
955 if (errcount == 10)
956 fatal_dump("Select Loop failed!");
957
958 break;
959
960 case COMM_TIMEOUT:
961 break;
962
963 case COMM_SHUTDOWN:
964 SquidShutdown(NULL);
965
966 break;
967
968 default:
969 fatal_dump("MAIN: Internal error -- this should never happen.");
970
971 break;
972 }
090089c4 973 }
62e76326 974
090089c4 975 /* NOTREACHED */
983061ed 976 return 0;
090089c4 977}
7690e8eb 978
b8d8561b 979static void
0673c0ba 980sendSignal(void)
7690e8eb 981{
ff8d0ea6 982 pid_t pid;
fedac7e5 983 debug_log = stderr;
fedac7e5 984 pid = readPidFile();
62e76326 985
fedac7e5 986 if (pid > 1) {
62e76326 987 if (kill(pid, opt_send_signal) &&
988 /* ignore permissions if just running check */
989 !(opt_send_signal == 0 && errno == EPERM)) {
990 fprintf(stderr, "%s: ERROR: Could not send ", appname);
991 fprintf(stderr, "signal %d to process %d: %s\n",
992 opt_send_signal, (int) pid, xstrerror());
993 exit(1);
994 }
fedac7e5 995 } else {
62e76326 996 fprintf(stderr, "%s: ERROR: No running copy\n", appname);
997 exit(1);
7690e8eb 998 }
62e76326 999
fedac7e5 1000 /* signal successfully sent */
1001 exit(0);
1002}
f95b8144 1003
e18d7fdc 1004/*
1005 * This function is run when Squid is in daemon mode, just
1006 * before the parent forks and starts up the child process.
1007 * It can be used for admin-specific tasks, such as notifying
1008 * someone that Squid is (re)started.
1009 */
1010static void
1011mainStartScript(const char *prog)
1012{
1013 char script[SQUID_MAXPATHLEN];
1014 char *t;
1015 size_t sl = 0;
1016 pid_t cpid;
1017 pid_t rpid;
1018 xstrncpy(script, prog, MAXPATHLEN);
62e76326 1019
e18d7fdc 1020 if ((t = strrchr(script, '/'))) {
62e76326 1021 *(++t) = '\0';
1022 sl = strlen(script);
e18d7fdc 1023 }
62e76326 1024
e18d7fdc 1025 xstrncpy(&script[sl], squid_start_script, MAXPATHLEN - sl);
62e76326 1026
e18d7fdc 1027 if ((cpid = fork()) == 0) {
62e76326 1028 /* child */
1029 execl(script, squid_start_script, 0);
1030 _exit(0);
e18d7fdc 1031 } else {
62e76326 1032 do {
e18d7fdc 1033#ifdef _SQUID_NEXT_
62e76326 1034 union wait status;
1035 rpid = wait3(&status, 0, NULL);
e18d7fdc 1036#else
62e76326 1037
1038 int status;
1039 rpid = waitpid(-1, &status, 0);
e18d7fdc 1040#endif
62e76326 1041
1042 } while (rpid != cpid);
e18d7fdc 1043 }
1044}
1045
efd900cb 1046static int
1047checkRunningPid(void)
1048{
1049 pid_t pid;
1050 debug_log = stderr;
1051 pid = readPidFile();
62e76326 1052
efd900cb 1053 if (pid < 2)
62e76326 1054 return 0;
1055
efd900cb 1056 if (kill(pid, 0) < 0)
62e76326 1057 return 0;
1058
efd900cb 1059 debug(0, 0) ("Squid is already running! Process ID %d\n", pid);
62e76326 1060
efd900cb 1061 return 1;
1062}
1063
f95b8144 1064static void
bbe199dc 1065watch_child(char *argv[])
f95b8144 1066{
1067 char *prog;
f95b8144 1068 int failcount = 0;
1069 time_t start;
1070 time_t stop;
1071#ifdef _SQUID_NEXT_
62e76326 1072
f95b8144 1073 union wait status;
1074#else
62e76326 1075
f95b8144 1076 int status;
1077#endif
62e76326 1078
e3a3b845 1079 pid_t pid;
54f742e7 1080 int i;
742724a4 1081 int nullfd;
62e76326 1082
f95b8144 1083 if (*(argv[0]) == '(')
62e76326 1084 return;
1085
54f742e7 1086 openlog(appname, LOG_PID | LOG_NDELAY | LOG_CONS, LOG_LOCAL4);
62e76326 1087
54f742e7 1088 if ((pid = fork()) < 0)
62e76326 1089 syslog(LOG_ALERT, "fork failed: %s", xstrerror());
54f742e7 1090 else if (pid > 0)
62e76326 1091 exit(0);
1092
54f742e7 1093 if (setsid() < 0)
62e76326 1094 syslog(LOG_ALERT, "setsid failed: %s", xstrerror());
1095
efd900cb 1096 closelog();
62e76326 1097
54f742e7 1098#ifdef TIOCNOTTY
62e76326 1099
c4aefe96 1100 if ((i = open("/dev/tty", O_RDWR | O_TEXT)) >= 0) {
62e76326 1101 ioctl(i, TIOCNOTTY, NULL);
1102 close(i);
54f742e7 1103 }
62e76326 1104
54f742e7 1105#endif
b05490a8 1106
1107
7f6ffd15 1108 /*
1109 * RBCOLLINS - if cygwin stackdumps when squid is run without
1110 * -N, check the cygwin1.dll version, it needs to be AT LEAST
1111 * 1.1.3. execvp had a bit overflow error in a loop..
1112 */
742724a4 1113 /* Connect stdio to /dev/null in daemon mode */
c4aefe96 1114 nullfd = open("/dev/null", O_RDWR | O_TEXT);
62e76326 1115
742724a4 1116 dup2(nullfd, 0);
62e76326 1117
742724a4 1118 if (opt_debug_stderr < 0) {
62e76326 1119 dup2(nullfd, 1);
1120 dup2(nullfd, 2);
742724a4 1121 }
62e76326 1122
742724a4 1123 /* Close all else */
1124 for (i = 3; i < Squid_MaxFD; i++)
62e76326 1125 close(i);
1126
f95b8144 1127 for (;;) {
62e76326 1128 mainStartScript(argv[0]);
1129
1130 if ((pid = fork()) == 0) {
1131 /* child */
1132 openlog(appname, LOG_PID | LOG_NDELAY | LOG_CONS, LOG_LOCAL4);
1133 prog = xstrdup(argv[0]);
1134 argv[0] = xstrdup("(squid)");
1135 execvp(prog, argv);
1136 syslog(LOG_ALERT, "execvp failed: %s", xstrerror());
1137 }
1138
1139 /* parent */
1140 openlog(appname, LOG_PID | LOG_NDELAY | LOG_CONS, LOG_LOCAL4);
1141
1142 syslog(LOG_NOTICE, "Squid Parent: child process %d started", pid);
1143
1144 time(&start);
1145
1146 squid_signal(SIGINT, SIG_IGN, SA_RESTART);
1147
f95b8144 1148#ifdef _SQUID_NEXT_
62e76326 1149
1150 pid = wait3(&status, 0, NULL);
1151
f95b8144 1152#else
62e76326 1153
1154 pid = waitpid(-1, &status, 0);
1155
1156#endif
1157
1158 time(&stop);
1159
1160 if (WIFEXITED(status)) {
1161 syslog(LOG_NOTICE,
1162 "Squid Parent: child process %d exited with status %d",
1163 pid, WEXITSTATUS(status));
1164 } else if (WIFSIGNALED(status)) {
1165 syslog(LOG_NOTICE,
1166 "Squid Parent: child process %d exited due to signal %d",
1167 pid, WTERMSIG(status));
1168 } else {
1169 syslog(LOG_NOTICE, "Squid Parent: child process %d exited", pid);
1170 }
1171
1172 if (stop - start < 10)
1173 failcount++;
1174 else
1175 failcount = 0;
1176
1177 if (failcount == 5) {
1178 syslog(LOG_ALERT, "Exiting due to repeated, frequent failures");
1179 exit(1);
1180 }
1181
1182 if (WIFEXITED(status))
1183 if (WEXITSTATUS(status) == 0)
1184 exit(0);
1185
1186 if (WIFSIGNALED(status)) {
1187 switch (WTERMSIG(status)) {
1188
1189 case SIGKILL:
1190 exit(0);
1191 break;
1192
1193 default:
1194 break;
1195 }
1196 }
1197
1198 squid_signal(SIGINT, SIG_DFL, SA_RESTART);
1199 sleep(3);
f95b8144 1200 }
62e76326 1201
bbe199dc 1202 /* NOTREACHED */
f95b8144 1203}
fff6ad65 1204
9ec1a1dc 1205static void
d723bf6b 1206SquidShutdown(void *unused)
fff6ad65 1207{
1208 debug(1, 1) ("Shutting down...\n");
d723bf6b 1209 icpConnectionClose();
1210#if USE_HTCP
62e76326 1211
d723bf6b 1212 htcpSocketClose();
1213#endif
1214#ifdef SQUID_SNMP
62e76326 1215
d723bf6b 1216 snmpConnectionClose();
320e9f36 1217#endif
eb824054 1218#if USE_WCCP
62e76326 1219
320e9f36 1220 wccpConnectionClose();
d723bf6b 1221#endif
62e76326 1222
fff6ad65 1223 releaseServerSockets();
d723bf6b 1224 commCloseAllSockets();
515ec4dc 1225#if DELAY_POOLS
62e76326 1226
b67e2c8c 1227 DelayPools::FreePools();
515ec4dc 1228#endif
62e76326 1229
5dae8514 1230 authenticateShutdown();
a3d0a19d 1231#if USE_UNLINKD
62e76326 1232
fff6ad65 1233 unlinkdClose();
a3d0a19d 1234#endif
62e76326 1235
cd748f27 1236 storeDirSync(); /* Flush pending object writes/unlinks */
fff6ad65 1237 storeDirWriteCleanLogs(0);
1238 PrintRusage();
1239 dumpMallocStats();
cd748f27 1240 storeDirSync(); /* Flush log writes */
fff6ad65 1241 storeLogClose();
1242 accessLogClose();
5b824235 1243 useragentLogClose();
c9b99797 1244 refererCloseLog();
225644d7 1245#if WIP_FWD_LOG
62e76326 1246
225644d7 1247 fwdUninit();
1248#endif
62e76326 1249
cd748f27 1250 storeDirSync(); /* Flush log close */
33ab18e8 1251#if PURIFY || XMALLOC_TRACE
62e76326 1252
cd748f27 1253 storeFsDone();
fff6ad65 1254 configFreeMemory();
1255 storeFreeMemory();
33ab18e8 1256 /*stmemFreeMemory(); */
fff6ad65 1257 netdbFreeMemory();
1258 ipcacheFreeMemory();
1259 fqdncacheFreeMemory();
1260 asnFreeMemory();
26a369ba 1261 clientdbFreeMemory();
7021844c 1262 httpHeaderCleanModule();
d2db411c 1263 statFreeMemory();
f1fc2a8d 1264 eventFreeMemory();
c68e9c6b 1265 mimeFreeMemory();
1266 errorClean();
fff6ad65 1267#endif
26a369ba 1268#if !XMALLOC_TRACE
62e76326 1269
54f742e7 1270 if (opt_no_daemon) {
62e76326 1271 file_close(0);
1272 file_close(1);
1273 file_close(2);
54f742e7 1274 }
62e76326 1275
33ab18e8 1276#endif
fff6ad65 1277 fdDumpOpen();
62e76326 1278
fff6ad65 1279 fdFreeMemory();
62e76326 1280
ddb43c58 1281 memClean();
62e76326 1282
33ab18e8 1283#if XMALLOC_TRACE
62e76326 1284
26a369ba 1285 xmalloc_find_leaks();
62e76326 1286
26a369ba 1287 debug(1, 0) ("Memory used after shutdown: %d\n", xmalloc_total);
62e76326 1288
33ab18e8 1289#endif
36a97e19 1290#if MEM_GEN_TRACE
62e76326 1291
399e85ea 1292 log_trace_done();
62e76326 1293
36a97e19 1294#endif
62e76326 1295
ab50ee9e 1296 if (Config.pidFilename && strcmp(Config.pidFilename, "none") != 0) {
62e76326 1297 enter_suid();
1298 safeunlink(Config.pidFilename, 0);
1299 leave_suid();
ab50ee9e 1300 }
62e76326 1301
a60f7062 1302 debug(1, 1) ("Squid Cache (Version %s): Exiting normally.\n",
62e76326 1303 version_string);
1304
7e3ce7b9 1305 if (debug_log)
62e76326 1306 fclose(debug_log);
1307
fff6ad65 1308 exit(0);
1309}