]> git.ipfire.org Git - thirdparty/squid.git/blame - src/main.cc
Need to #include helper.h in dns.cc for --disable-internal-dns
[thirdparty/squid.git] / src / main.cc
CommitLineData
a47b9029 1
30a4f2a8 2/*
559da936 3 * $Id: main.cc,v 1.437 2006/09/25 15:04:07 adrian 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"
450e0c10 37#include "AccessLogEntry.h"
e6ccf245 38#include "authenticate.h"
62ee09ca 39#include "CacheManager.h"
40#include "ConfigParser.h"
aa839030 41#include "errorpage.h"
a553a5a3 42#include "event.h"
43#include "EventLoop.h"
62ee09ca 44#include "ExternalACL.h"
e6ccf245 45#include "Store.h"
46#include "ICP.h"
528b2c61 47#include "HttpReply.h"
62ee09ca 48#include "pconn.h"
528b2c61 49#include "Mem.h"
b0dd28ba 50#include "ACLASN.h"
51#include "ACL.h"
75faaa7a 52#include "htcp.h"
59b2d47f 53#include "StoreFileSystem.h"
b9ae18aa 54#include "DiskIO/DiskIOModule.h"
f900210a 55#include "comm.h"
62ee09ca 56#if USE_EPOLL
57#include "comm_epoll.h"
58#endif
59#if USE_KQUEUE
60#include "comm_kqueue.h"
61#endif
62#if USE_POLL
63#include "comm_poll.h"
64#endif
65#if USE_SELECT
66#include "comm_select.h"
67#endif
663c0a38 68#if USE_SELECT_WIN32
69#include "comm_select.h"
70#endif
985c86bc 71#include "SquidTime.h"
c8f4eac4 72#include "SwapDir.h"
b6b6f466 73#include "forward.h"
d9e7ee1f 74#include "MemPool.h"
44a47c6e 75
1a774556 76#if USE_WIN32_SERVICE
77
78#include "squid_windows.h"
79#include <process.h>
80
81static int opt_install_service = FALSE;
82static int opt_remove_service = FALSE;
83static int opt_signal_service = FALSE;
84static int opt_command_line = FALSE;
85extern void WIN32_svcstatusupdate(DWORD, DWORD);
86void WINAPI WIN32_svcHandler(DWORD);
87
88#endif
89
30a4f2a8 90/* for error reporting from xmalloc and friends */
b293c4d8 91SQUIDCEXTERN void (*failure_notify) (const char *);
30a4f2a8 92
e13ee7ad 93static int opt_parse_cfg_only = 0;
5e6d4736 94static char *opt_syslog_facility = NULL;
30a4f2a8 95static int icpPortNumOverride = 1; /* Want to detect "-u 0" */
e13ee7ad 96static int configured_once = 0;
30a4f2a8 97#if MALLOC_DBG
4d64d74a 98static int malloc_debug_level = 0;
30a4f2a8 99#endif
5cd39a10 100static volatile int do_reconfigure = 0;
101static volatile int do_rotate = 0;
2681d383 102static volatile int do_shutdown = 0;
ae1feb30 103static volatile int shutdown_status = 0;
4d7add01 104
5cd39a10 105static void mainRotate(void);
106static void mainReconfigure(void);
f5b8bbc4 107static void mainInitialize(void);
f5b8bbc4 108static void usage(void);
109static void mainParseOptions(int, char **);
110static void sendSignal(void);
111static void serverConnectionsOpen(void);
bbe199dc 112static void watch_child(char **);
85407535 113static void setEffectiveUser(void);
36a97e19 114#if MEM_GEN_TRACE
115extern void log_trace_done();
116extern void log_trace_init(char *);
117#endif
8ff3fa2e 118static void SquidShutdown(void);
b6a2f15e 119static void mainSetCwd(void);
efd900cb 120static int checkRunningPid(void);
85407535 121
62ee09ca 122static CacheManager manager;
123
b293c4d8 124#ifndef _SQUID_MSWIN_
e18d7fdc 125static const char *squid_start_script = "squid_start";
b293c4d8 126#endif
e18d7fdc 127
9bc73deb 128#if TEST_ACCESS
129#include "test_access.c"
130#endif
131
8ff3fa2e 132/* temporary thunk across to the unrefactored store interface */
133
134class StoreRootEngine : public AsyncEngine
135{
136
137public:
138 int checkEvents(int timeout)
139 {
140 Store::Root().callback();
141 return EVENT_IDLE;
142 };
143};
144
a553a5a3 145class SignalDispatcher : public CompletionDispatcher
146{
147
148public:
8ff3fa2e 149 SignalDispatcher(EventLoop &loop) : loop(loop), events_dispatched(false) {}
a553a5a3 150
151 void addEventLoop(EventLoop * loop);
8ff3fa2e 152 virtual bool dispatch();
a553a5a3 153
154private:
155 static void StopEventLoop(void * data)
156 {
157 static_cast<SignalDispatcher *>(data)->loop.stop();
158 }
159
160 EventLoop &loop;
8ff3fa2e 161 bool events_dispatched;
a553a5a3 162};
163
8ff3fa2e 164bool
a553a5a3 165SignalDispatcher::dispatch()
166{
559da936 167 PROF_start(SignalDispatcher_dispatch);
a553a5a3 168 if (do_reconfigure) {
169 mainReconfigure();
170 do_reconfigure = 0;
a553a5a3 171 } else if (do_rotate) {
172 mainRotate();
173 do_rotate = 0;
174 } else if (do_shutdown) {
175 time_t wait = do_shutdown > 0 ? (int) Config.shutdownLifetime : 0;
176 debug(1, 1) ("Preparing for shutdown after %d requests\n",
177 statCounter.client_http.requests);
178 debug(1, 1) ("Waiting %d seconds for active connections to finish\n",
179 (int) wait);
180 do_shutdown = 0;
181 shutting_down = 1;
182#if USE_WIN32_SERVICE
183
184 WIN32_svcstatusupdate(SERVICE_STOP_PENDING, (wait + 1) * 1000);
185#endif
186
187 serverConnectionsClose();
8ff3fa2e 188 eventAdd("SquidShutdown", StopEventLoop, this, (double) (wait + 1), 1, false);
a553a5a3 189 }
8ff3fa2e 190
191 bool result = events_dispatched;
192 events_dispatched = false;
559da936 193 PROF_stop(SignalDispatcher_dispatch);
8ff3fa2e 194 return result;
a553a5a3 195}
196
b8d8561b 197static void
0673c0ba 198usage(void)
ccff9601 199{
0ee4272b 200 fprintf(stderr,
0e657244 201#if USE_WIN32_SERVICE
5e6d4736 202 "Usage: %s [-cdhirvzCDFNRVYX] [-s | -l facility] [-f config-file] [-[au] port] [-k signal] [-n name] [-O CommandLine]\n"
0e657244 203#else
5e6d4736 204 "Usage: %s [-cdhvzCDFNRVYX] [-s | -l facility] [-f config-file] [-[au] port] [-k signal]\n"
0e657244 205#endif
62e76326 206 " -a port Specify HTTP port number (default: %d).\n"
207 " -d level Write debugging to stderr also.\n"
208 " -f file Use given config-file instead of\n"
209 " %s\n"
210 " -h Print help message.\n"
0e657244 211#if USE_WIN32_SERVICE
212 " -i Installs as a Windows Service (see -n option).\n"
213#endif
62e76326 214 " -k reconfigure|rotate|shutdown|interrupt|kill|debug|check|parse\n"
215 " Parse configuration file, then send signal to \n"
216 " running copy (except -k parse) and exit.\n"
0e657244 217#if USE_WIN32_SERVICE
218 " -n name Specify Windows Service name to use for service operations\n"
219 " default is: " _WIN_SQUID_DEFAULT_SERVICE_NAME ".\n"
220 " -r Removes a Windows Service (see -n option).\n"
221#endif
5e6d4736 222 " -s | -l facility\n"
223 " Enable logging to syslog.\n"
62e76326 224 " -u port Specify ICP port number (default: %d), disable with 0.\n"
225 " -v Print version.\n"
226 " -z Create swap directories\n"
227 " -C Do not catch fatal signals.\n"
228 " -D Disable initial DNS tests.\n"
229 " -F Don't serve any requests until store is rebuilt.\n"
230 " -N No daemon mode.\n"
0e657244 231#if USE_WIN32_SERVICE
232 " -O options\n"
233 " Set Windows Service Command line options in Registry.\n"
234#endif
62e76326 235 " -R Do not set REUSEADDR on port.\n"
236 " -S Double-check swap during rebuild.\n"
237 " -V Virtual host httpd-accelerator.\n"
238 " -X Force full debugging.\n"
239 " -Y Only return UDP_HIT or UDP_MISS_NOFETCH during fast reload.\n",
240 appname, CACHE_HTTP_PORT, DefaultConfigFile, CACHE_ICP_PORT);
77ffc99f 241 exit(1);
ccff9601 242}
243
b8d8561b 244static void
245mainParseOptions(int argc, char *argv[])
090089c4 246{
090089c4 247 extern char *optarg;
4d64d74a 248 int c;
090089c4 249
0e657244 250#if USE_WIN32_SERVICE
251
5e6d4736 252 while ((c = getopt(argc, argv, "CDFNO:RSVYXa:d:f:hik:m::n:rsl:u:vz?")) != -1)
0e657244 253#else
254
5e6d4736 255 while ((c = getopt(argc, argv, "CDFNRSVYXa:d:f:hk:m::sl:u:vz?")) != -1)
0e657244 256#endif
257
9b7292ce 258 {
259
260 switch (c)
261 {
62e76326 262
263 case 'C':
264 opt_catch_signals = 0;
265 break;
266
267 case 'D':
268 opt_dns_tests = 0;
269 break;
270
271 case 'F':
272 opt_foreground_rebuild = 1;
273 break;
274
275 case 'N':
276 opt_no_daemon = 1;
277 break;
0e657244 278#if USE_WIN32_SERVICE
279
280 case 'O':
281 opt_command_line = 1;
282 WIN32_Command_Line = xstrdup(optarg);
283 break;
284#endif
62e76326 285
286 case 'R':
287 opt_reuseaddr = 0;
288 break;
289
290 case 'S':
291 opt_store_doublecheck = 1;
292 break;
293
294 case 'V':
295
296 if (Config.Sockaddr.http)
297 Config.Sockaddr.http->vhost = 1;
298
3f38a55e 299#if USE_SSL
62e76326 300
301 else if (Config.Sockaddr.https)
302 Config.Sockaddr.https->http.vhost = 1;
303
304#endif
305
306 else
307 fatal("No http_port specified\n");
308
309 break;
310
311 case 'X':
312 /* force full debugging */
313 sigusr2_handle(SIGUSR2);
314
315 break;
316
317 case 'Y':
318 opt_reload_hit_only = 1;
319
320 break;
321
0e657244 322#if USE_WIN32_SERVICE
323
324 case 'i':
325 opt_install_service = TRUE;
326
327 break;
328
329#endif
330
62e76326 331 case 'a':
332 add_http_port(optarg);
333
334 break;
335
336 case 'd':
337 opt_debug_stderr = atoi(optarg);
338
339 break;
340
341 case 'f':
342 xfree(ConfigFile);
343
344 ConfigFile = xstrdup(optarg);
345
346 break;
347
348 case 'h':
349 usage();
350
351 break;
352
353 case 'k':
354 if ((int) strlen(optarg) < 1)
355 usage();
356
357 if (!strncmp(optarg, "reconfigure", strlen(optarg)))
358 opt_send_signal = SIGHUP;
359 else if (!strncmp(optarg, "rotate", strlen(optarg)))
7e7a0442 360#ifdef _SQUID_LINUX_THREADS_
62e76326 361
362 opt_send_signal = SIGQUIT;
363
e3175d1f 364#else
62e76326 365
366 opt_send_signal = SIGUSR1;
367
e3175d1f 368#endif
62e76326 369
370 else if (!strncmp(optarg, "debug", strlen(optarg)))
7e7a0442 371#ifdef _SQUID_LINUX_THREADS_
62e76326 372
373 opt_send_signal = SIGTRAP;
374
e3175d1f 375#else
62e76326 376
377 opt_send_signal = SIGUSR2;
378
379#endif
380
381 else if (!strncmp(optarg, "shutdown", strlen(optarg)))
382 opt_send_signal = SIGTERM;
383 else if (!strncmp(optarg, "interrupt", strlen(optarg)))
384 opt_send_signal = SIGINT;
385 else if (!strncmp(optarg, "kill", strlen(optarg)))
386 opt_send_signal = SIGKILL;
ae1feb30 387
388#ifdef SIGTTIN
389
390 else if (!strncmp(optarg, "restart", strlen(optarg)))
391 opt_send_signal = SIGTTIN; /* exit and restart by parent */
392
393#endif
394
62e76326 395 else if (!strncmp(optarg, "check", strlen(optarg)))
396 opt_send_signal = 0; /* SIGNULL */
397 else if (!strncmp(optarg, "parse", strlen(optarg)))
398 opt_parse_cfg_only = 1; /* parse cfg file only */
399 else
400 usage();
401
402 break;
403
404 case 'm':
405 if (optarg) {
30a4f2a8 406#if MALLOC_DBG
d9e7ee1f 407 malloc_debug_level = atoi(optarg);
30a4f2a8 408#else
62e76326 409
d9e7ee1f 410 fatal("Need to add -DMALLOC_DBG when compiling to use -mX option");
33ab18e8 411#endif
62e76326 412
413 } else {
33ab18e8 414#if XMALLOC_TRACE
62e76326 415 xmalloc_trace = !xmalloc_trace;
33ab18e8 416#else
62e76326 417
418 fatal("Need to configure --enable-xmalloc-debug-trace to use -m option");
30a4f2a8 419#endif
62e76326 420
421 }
422
d9e7ee1f 423 break;
424 /* NOTREACHED */
425
0e657244 426#if USE_WIN32_SERVICE
427
428 case 'n':
429 xfree(WIN32_Service_name);
430
431 WIN32_Service_name = xstrdup(optarg);
432
433 opt_signal_service = TRUE;
434
435 break;
436
437 case 'r':
438 opt_remove_service = TRUE;
439
440 break;
441
442#endif
443
5e6d4736 444 case 'l':
445 opt_syslog_facility = xstrdup(optarg);
446
62e76326 447 case 's':
c307aec3 448#if HAVE_SYSLOG
62e76326 449
5e6d4736 450 _db_set_syslog(opt_syslog_facility);
0e657244 451
62e76326 452 break;
0e657244 453
c307aec3 454#else
62e76326 455
456 fatal("Logging to syslog not available on this platform");
0e657244 457
62e76326 458 /* NOTREACHED */
459#endif
460
461 case 'u':
462 icpPortNumOverride = atoi(optarg);
463
464 if (icpPortNumOverride < 0)
465 icpPortNumOverride = 0;
466
467 break;
468
469 case 'v':
470 printf("Squid Cache: Version %s\nconfigure options: %s\n", version_string, SQUID_CONFIGURE_OPTIONS);
471
1a774556 472#if USE_WIN32_SERVICE
473
474 printf("Compiled as Windows System Service.\n");
475
476#endif
477
62e76326 478 exit(0);
479
480 /* NOTREACHED */
481
482 case 'z':
930dea4a 483 opt_debug_stderr = 1;
484
62e76326 485 opt_create_swap_dirs = 1;
486
487 break;
488
489 case '?':
490
491 default:
492 usage();
493
494 break;
495 }
9b7292ce 496
090089c4 497 }
4d64d74a 498}
090089c4 499
7a2f978b 500/* ARGSUSED */
b293c4d8 501void
9b7292ce 502rotate_logs(int sig)
503{
5cd39a10 504 do_rotate = 1;
a50bfe93 505#ifndef _SQUID_MSWIN_
30a4f2a8 506#if !HAVE_SIGACTION
62e76326 507
30a4f2a8 508 signal(sig, rotate_logs);
509#endif
a50bfe93 510#endif
30a4f2a8 511}
512
7a2f978b 513/* ARGSUSED */
b293c4d8 514void
9b7292ce 515reconfigure(int sig)
516{
5cd39a10 517 do_reconfigure = 1;
a50bfe93 518#ifndef _SQUID_MSWIN_
30a4f2a8 519#if !HAVE_SIGACTION
62e76326 520
30a4f2a8 521 signal(sig, reconfigure);
522#endif
a50bfe93 523#endif
30a4f2a8 524}
525
b8d8561b 526void
9b7292ce 527shut_down(int sig)
528{
2681d383 529 do_shutdown = sig == SIGINT ? -1 : 1;
ae1feb30 530#ifdef SIGTTIN
531
532 if (SIGTTIN == sig)
533 shutdown_status = 1;
534
535#endif
a50bfe93 536#ifndef _SQUID_MSWIN_
cadc2d55 537#ifdef KILL_PARENT_OPT
62e76326 538
5cd39a10 539 if (getppid() > 1) {
36584579 540 debugs(1, 1, "Killing RunCache, pid " << getppid());
62e76326 541
542 if (kill(getppid(), sig) < 0)
36584579 543 debugs(1, 1, "kill " << getppid() << ": " << xstrerror());
88738790 544 }
62e76326 545
cadc2d55 546#endif
6e40f263 547#if SA_RESETHAND == 0
548 signal(SIGTERM, SIG_DFL);
62e76326 549
6e40f263 550 signal(SIGINT, SIG_DFL);
62e76326 551
a50bfe93 552#endif
6e40f263 553#endif
30a4f2a8 554}
555
24382924 556static void
9b7292ce 557serverConnectionsOpen(void)
558{
d193a436 559 clientOpenListenSockets();
15df8349 560 icpConnectionsOpen();
ace287ee 561#if USE_HTCP
62e76326 562
ace287ee 563 htcpInit();
564#endif
678c6099 565#ifdef SQUID_SNMP
62e76326 566
3265e68d 567 snmpConnectionOpen();
320e9f36 568#endif
eb824054 569#if USE_WCCP
62e76326 570
320e9f36 571 wccpConnectionOpen();
2bbd722b 572#endif
62e76326 573
0b0cfcf2 574#if USE_WCCPv2
575
576 wccp2ConnectionOpen();
577#endif
578
5ecceaa4 579 clientdbInit();
16b204c4 580 icmpOpen();
67508012 581 netdbInit();
f899fac1 582 asnInit();
b0dd28ba 583 ACL::Initialize();
85034133 584 peerSelectInit();
afd88fbe 585#if USE_CARP
62e76326 586
afd88fbe 587 carpInit();
588#endif
5f3f8d0e 589}
590
b8d8561b 591void
9b7292ce 592serverConnectionsClose(void)
593{
0a5a8601 594 assert(shutting_down || reconfiguring);
c0fbae16 595 clientHttpConnectionsClose();
17e6c0a1 596 icpConnectionShutdown();
72549e05 597#if USE_HTCP
62e76326 598
72549e05 599 htcpSocketShutdown();
600#endif
62e76326 601
c0fbae16 602 icmpClose();
15df8349 603#ifdef SQUID_SNMP
62e76326 604
17e6c0a1 605 snmpConnectionShutdown();
320e9f36 606#endif
eb824054 607#if USE_WCCP
62e76326 608
0b0cfcf2 609 wccpConnectionClose();
610#endif
611#if USE_WCCPv2
612
613 wccp2ConnectionClose();
15df8349 614#endif
62e76326 615
4bac8de8 616 asnFreeMemory();
5f3f8d0e 617}
618
b8d8561b 619static void
9b7292ce 620mainReconfigure(void)
621{
eba1bf37 622 debug(1, 1) ("Reconfiguring Squid Cache (version %s)...\n", version_string);
5cd39a10 623 reconfiguring = 1;
0ffd22bc 624 /* Already called serverConnectionsClose and ipcacheShutdownServers() */
15df8349 625 serverConnectionsClose();
17e6c0a1 626 icpConnectionClose();
72549e05 627#if USE_HTCP
62e76326 628
72549e05 629 htcpSocketClose();
630#endif
17e6c0a1 631#ifdef SQUID_SNMP
62e76326 632
17e6c0a1 633 snmpConnectionClose();
320e9f36 634#endif
3c573763 635#if USE_DNSSERVERS
62e76326 636
74addf6c 637 dnsShutdown();
3c573763 638#else
62e76326 639
7b724b86 640 idnsShutdown();
eb824054 641#endif
62e76326 642
74addf6c 643 redirectShutdown();
644 authenticateShutdown();
d9572179 645 externalAclShutdown();
2db68ce5 646 storeDirCloseSwapLogs();
2e923080 647 storeLogClose();
648 accessLogClose();
649 useragentLogClose();
650 refererCloseLog();
c68e9c6b 651 errorClean();
3aa4adbc 652 enter_suid(); /* root to read config file */
62ee09ca 653 parseConfigFile(ConfigFile, manager);
3aa4adbc 654 setEffectiveUser();
b6f794d6 655 _db_init(Config.Log.log, Config.debugOptions);
429fdbec 656 ipcache_restart(); /* clear stuck entries */
94439e4e 657 authenticateUserCacheRestart(); /* clear stuck ACL entries */
429fdbec 658 fqdncache_restart(); /* sigh, fqdncache too */
0e70aa1e 659 parseEtcHosts();
53ad48e6 660 errorInitialize(); /* reload error pages */
2e923080 661 accessLogInit();
662 storeLogOpen();
663 useragentOpenLog();
664 refererOpenLog();
3c573763 665#if USE_DNSSERVERS
62e76326 666
74addf6c 667 dnsInit();
3c573763 668#else
62e76326 669
7b724b86 670 idnsInit();
eb824054 671#endif
62e76326 672
74addf6c 673 redirectInit();
e6ccf245 674 authenticateInit(&Config.authConfiguration);
d9572179 675 externalAclInit();
1f38f50a 676#if USE_WCCP
62e76326 677
1f38f50a 678 wccpInit();
679#endif
0b0cfcf2 680#if USE_WCCPv2
681
682 wccp2Init();
683#endif
62e76326 684
0ffd22bc 685 serverConnectionsOpen();
9c2e9b50 686
62ee09ca 687 if (theOutIcpConnection >= 0) {
9c2e9b50 688 neighbors_init();
62ee09ca 689 neighborsRegisterWithCacheManager(manager);
690 }
9c2e9b50 691
2db68ce5 692 storeDirOpenSwapLogs();
9c2e9b50 693
9c021a38 694 mimeInit(Config.mimeTablePathname);
9c2e9b50 695
926375e6 696 if (Config.onoff.announce) {
697 if (!eventFind(start_announce, NULL))
698 eventAdd("start_announce", start_announce, NULL, 3600.0, 1);
699 } else {
700 if (eventFind(start_announce, NULL))
701 eventDelete(start_announce, NULL);
702 }
703
b8890359 704 writePidFile(); /* write PID file */
9c2e9b50 705
aebbcd07 706 debug(1, 1) ("Ready to serve requests.\n");
9c2e9b50 707
5cd39a10 708 reconfiguring = 0;
709}
710
711static void
9b7292ce 712mainRotate(void)
713{
5cd39a10 714 icmpClose();
3c573763 715#if USE_DNSSERVERS
62e76326 716
e40aa8da 717 dnsShutdown();
3c573763 718#endif
62e76326 719
e40aa8da 720 redirectShutdown();
721 authenticateShutdown();
d9572179 722 externalAclShutdown();
5cd39a10 723 _db_rotate_log(); /* cache.log */
724 storeDirWriteCleanLogs(1);
725 storeLogRotate(); /* store.log */
726 accessLogRotate(); /* access.log */
727 useragentRotateLog(); /* useragent.log */
fd2c5549 728 refererRotateLog(); /* referer.log */
225644d7 729#if WIP_FWD_LOG
62e76326 730
225644d7 731 fwdLogRotate();
732#endif
62e76326 733
5cd39a10 734 icmpOpen();
3c573763 735#if USE_DNSSERVERS
62e76326 736
e40aa8da 737 dnsInit();
3c573763 738#endif
62e76326 739
e40aa8da 740 redirectInit();
e6ccf245 741 authenticateInit(&Config.authConfiguration);
d9572179 742 externalAclInit();
5f3f8d0e 743}
744
067bea91 745static void
9b7292ce 746setEffectiveUser(void)
747{
85407535 748 leave_suid(); /* Run as non privilegied user */
cd377065 749#ifdef _SQUID_OS2_
62e76326 750
cd377065 751 return;
752#endif
62e76326 753
85407535 754 if (geteuid() == 0) {
62e76326 755 debug(0, 0) ("Squid is not safe to run as root! If you must\n");
756 debug(0, 0) ("start Squid as root, then you must configure\n");
757 debug(0, 0) ("it to run as a non-priveledged user with the\n");
758 debug(0, 0) ("'cache_effective_user' option in the config file.\n");
759 fatal("Don't run Squid as root, set 'cache_effective_user'!");
85407535 760 }
761}
762
b6a2f15e 763static void
9b7292ce 764mainSetCwd(void)
765{
4a504376 766 char pathbuf[MAXPATHLEN];
62e76326 767
b6a2f15e 768 if (Config.coredump_dir) {
62e76326 769 if (0 == strcmp("none", Config.coredump_dir)) {
770 (void) 0;
771 } else if (chdir(Config.coredump_dir) == 0) {
772 debug(0, 1) ("Set Current Directory to %s\n", Config.coredump_dir);
773 return;
774 } else {
775 debug(50, 0) ("chdir: %s: %s\n", Config.coredump_dir, xstrerror());
776 }
b6a2f15e 777 }
62e76326 778
02e8115e 779 /* If we don't have coredump_dir or couldn't cd there, report current dir */
4a504376 780 if (getcwd(pathbuf, MAXPATHLEN)) {
62e76326 781 debug(0, 1) ("Current Directory is %s\n", pathbuf);
4a504376 782 } else {
62e76326 783 debug(50, 0) ("WARNING: Can't find current directory, getcwd: %s\n", xstrerror());
4a504376 784 }
b6a2f15e 785}
786
b67e2c8c 787#if DELAY_POOLS
788#include "DelayPools.h"
789#endif
790
b8d8561b 791static void
9b7292ce 792mainInitialize(void)
793{
efd900cb 794 /* chroot if configured to run inside chroot */
62e76326 795
efd900cb 796 if (Config.chroot_dir && chroot(Config.chroot_dir)) {
62e76326 797 fatal("failed to chroot");
efd900cb 798 }
62e76326 799
1758c627 800 if (opt_catch_signals) {
62e76326 801 squid_signal(SIGSEGV, death, SA_NODEFER | SA_RESETHAND);
802 squid_signal(SIGBUS, death, SA_NODEFER | SA_RESETHAND);
44f99671 803 }
62e76326 804
30a4f2a8 805 squid_signal(SIGPIPE, SIG_IGN, SA_RESTART);
806 squid_signal(SIGCHLD, sig_child, SA_NODEFER | SA_RESTART);
44f99671 807
85407535 808 setEffectiveUser();
62e76326 809
30a4f2a8 810 if (icpPortNumOverride != 1)
62e76326 811 Config.Port.icp = (u_short) icpPortNumOverride;
30a4f2a8 812
b6f794d6 813 _db_init(Config.Log.log, Config.debugOptions);
62e76326 814
5c5783a2 815 fd_open(fileno(debug_log), FD_LOG, Config.Log.log);
62e76326 816
71a17702 817#if MEM_GEN_TRACE
62e76326 818
71a17702 819 log_trace_init("/tmp/squid.alloc");
62e76326 820
71a17702 821#endif
62e76326 822
a3d5953d 823 debug(1, 0) ("Starting Squid Cache version %s for %s...\n",
62e76326 824 version_string,
825 CONFIG_HOST_TYPE);
826
ec4daaa5 827#ifdef _SQUID_WIN32_
b293c4d8 828
829 if (WIN32_run_mode == _WIN_SQUID_RUN_MODE_SERVICE) {
830 debug(1, 0) ("Running as %s Windows System Service on %s\n", WIN32_Service_name, WIN32_OS_string);
831 debug(1, 0) ("Service command line is: %s\n", WIN32_Service_Command_Line);
832 } else
833 debug(1, 0) ("Running on %s\n",WIN32_OS_string);
834
835#endif
836
36584579 837 debugs(1, 1, "Process ID " << getpid());
62e76326 838
a3d5953d 839 debug(1, 1) ("With %d file descriptors available\n", Squid_MaxFD);
5f3f8d0e 840
6c1962dd 841#ifdef _SQUID_MSWIN_
842
843 debug(1, 1) ("With %d CRT stdio descriptors available\n", _getmaxstdio());
844
845 if (WIN32_Socks_initialized)
846 debug(1, 1)("Windows sockets initialized\n");
847
848#endif
849
9f75c559 850 if (!configured_once)
62e76326 851 disk_init(); /* disk_init must go before ipcache_init() */
852
5f3f8d0e 853 ipcache_init();
62e76326 854
f88bb09c 855 fqdncache_init();
62e76326 856
0e70aa1e 857 parseEtcHosts();
62e76326 858
3c573763 859#if USE_DNSSERVERS
62e76326 860
74addf6c 861 dnsInit();
62e76326 862
3c573763 863#else
62e76326 864
7b724b86 865 idnsInit();
62e76326 866
eb824054 867#endif
62e76326 868
74addf6c 869 redirectInit();
62e76326 870
e6ccf245 871 authenticateInit(&Config.authConfiguration);
62e76326 872
d9572179 873 externalAclInit();
62e76326 874
b012353a 875 useragentOpenLog();
62e76326 876
fd2c5549 877 refererOpenLog();
62e76326 878
2ac76861 879 httpHeaderInitModule(); /* must go before any header processing (e.g. the one in errorInitialize) */
62e76326 880
2246b732 881 httpReplyInitModule(); /* must go before accepting replies */
62e76326 882
9b312a19 883 errorInitialize();
62e76326 884
7a2f978b 885 accessLogInit();
62e76326 886
3898f57f 887#if USE_IDENT
62e76326 888
05832ae1 889 identInit();
62e76326 890
3898f57f 891#endif
5e14bf6d 892#ifdef SQUID_SNMP
62e76326 893
5e14bf6d 894 snmpInit();
62e76326 895
5e14bf6d 896#endif
30a4f2a8 897#if MALLOC_DBG
62e76326 898
5f3f8d0e 899 malloc_debug(0, malloc_debug_level);
62e76326 900
5f3f8d0e 901#endif
902
dbe4fd8e 903 if (!configured_once) {
a3d0a19d 904#if USE_UNLINKD
62e76326 905 unlinkdInit();
906#endif
907
908 urlInitialize();
62e76326 909 statInit();
910 storeInit();
911 mainSetCwd();
912 /* after this point we want to see the mallinfo() output */
913 do_mallinfo = 1;
914 mimeInit(Config.mimeTablePathname);
62e76326 915 refreshInit();
0d7e5d78 916#if DELAY_POOLS
62e76326 917
918 DelayPools::Init();
0d7e5d78 919#endif
62e76326 920
b6b6f466 921 FwdState::initModule();
62ee09ca 922 /* register the modules in the cache manager menus */
923 accessLogRegisterWithCacheManager(manager);
924 asnRegisterWithCacheManager(manager);
925 authenticateRegisterWithCacheManager(&Config.authConfiguration, manager);
926#if USE_CARP
927
928 carpRegisterWithCacheManager(manager);
929#endif
930
931 cbdataRegisterWithCacheManager(manager);
932 /* These use separate calls so that the comm loops can eventually
933 * coexist.
934 */
935#ifdef USE_EPOLL
936
937 commEPollRegisterWithCacheManager(manager);
938#endif
939#ifdef USE_KQUEUE
940
941 commKQueueRegisterWithCacheManager(manager);
942#endif
943#ifdef USE_POLL
944
945 commPollRegisterWithCacheManager(manager);
946#endif
947#ifdef USE_SELECT
948
949 commSelectRegisterWithCacheManager(manager);
950#endif
951
952 clientdbRegisterWithCacheManager(manager);
610ee341 953#if DELAY_POOLS
954
62ee09ca 955 DelayPools::RegisterWithCacheManager(manager);
610ee341 956#endif
957
62ee09ca 958 DiskIOModule::RegisterAllModulesWithCacheManager(manager);
959#if USE_DNSSERVERS
960
961 dnsRegisterWithCacheManager(manager);
962#endif
963
964 eventInit(manager);
965 externalAclRegisterWithCacheManager(manager);
966 fqdncacheRegisterWithCacheManager(manager);
967 FwdState::RegisterWithCacheManager(manager);
968 httpHeaderRegisterWithCacheManager(manager);
5615c096 969#if !USE_DNSSERVERS
970
62ee09ca 971 idnsRegisterWithCacheManager(manager);
5615c096 972#endif
973
62ee09ca 974 ipcacheRegisterWithCacheManager(manager);
975 Mem::RegisterWithCacheManager(manager);
976 netdbRegisterWitHCacheManager(manager);
977 PconnModule::GetInstance()->registerWithCacheManager(manager);
978 redirectRegisterWithCacheManager(manager);
979 refreshRegisterWithCacheManager(manager);
980 statRegisterWithCacheManager(manager);
981 storeDigestRegisterWithCacheManager(manager);
982 StoreFileSystem::RegisterAllFsWithCacheManager(manager);
983 storeRegisterWithCacheManager(manager);
984#if DEBUGSTRINGS
985
986 StringRegistry::Instance().registerWithCacheManager(manager);
987#endif
988
610ee341 989#if USE_XPROF_STATS
990
62ee09ca 991 xprofRegisterWithCacheManager(manager);
610ee341 992#endif
993
5f3f8d0e 994 }
62e76326 995
1f38f50a 996#if USE_WCCP
997 wccpInit();
62e76326 998
0b0cfcf2 999#endif
1000#if USE_WCCPv2
1001
1002 wccp2Init();
1003
1f38f50a 1004#endif
62e76326 1005
2285407f 1006 serverConnectionsOpen();
62e76326 1007
62ee09ca 1008 if (theOutIcpConnection >= 0) {
9c2e9b50 1009 neighbors_init();
62ee09ca 1010 neighborsRegisterWithCacheManager(manager);
1011 }
62e76326 1012
efd900cb 1013 if (Config.chroot_dir)
62e76326 1014 no_suid();
1015
dbe4fd8e 1016 if (!configured_once)
62e76326 1017 writePidFile(); /* write PID file */
0a5b9b32 1018
7e7a0442 1019#ifdef _SQUID_LINUX_THREADS_
62e76326 1020
e3175d1f 1021 squid_signal(SIGQUIT, rotate_logs, SA_RESTART);
62e76326 1022
e3175d1f 1023 squid_signal(SIGTRAP, sigusr2_handle, SA_RESTART);
62e76326 1024
e3175d1f 1025#else
62e76326 1026
30a4f2a8 1027 squid_signal(SIGUSR1, rotate_logs, SA_RESTART);
62e76326 1028
30a4f2a8 1029 squid_signal(SIGUSR2, sigusr2_handle, SA_RESTART);
62e76326 1030
9fc0b4b8 1031#endif
62e76326 1032
30a4f2a8 1033 squid_signal(SIGHUP, reconfigure, SA_RESTART);
62e76326 1034
30a4f2a8 1035 squid_signal(SIGTERM, shut_down, SA_NODEFER | SA_RESETHAND | SA_RESTART);
62e76326 1036
30a4f2a8 1037 squid_signal(SIGINT, shut_down, SA_NODEFER | SA_RESETHAND | SA_RESTART);
62e76326 1038
ae1feb30 1039#ifdef SIGTTIN
1040
1041 squid_signal(SIGTTIN, shut_down, SA_NODEFER | SA_RESETHAND | SA_RESTART);
1042
1043#endif
1044
58a39dc9 1045 memCheckInit();
62e76326 1046
aebbcd07 1047 debug(1, 1) ("Ready to serve requests.\n");
62e76326 1048
dbe4fd8e 1049 if (!configured_once) {
c8f4eac4 1050 eventAdd("storeMaintain", Store::Maintain, NULL, 1.0, 1);
62e76326 1051
1052 if (Config.onoff.announce)
1053 eventAdd("start_announce", start_announce, NULL, 3600.0, 1);
1054
1055 eventAdd("ipcache_purgelru", ipcache_purgelru, NULL, 10.0, 1);
1056
1057 eventAdd("fqdncache_purgelru", fqdncache_purgelru, NULL, 15.0, 1);
1058
88bfe092 1059#if USE_XPROF_STATS
62e76326 1060
1061 eventAdd("cpuProfiling", xprof_event, NULL, 1.0, 1);
1062
88bfe092 1063#endif
62e76326 1064
1065 eventAdd("memPoolCleanIdlePools", Mem::CleanIdlePools, NULL, 15.0, 1);
f900210a 1066
1067 eventAdd("commCheckHalfClosed", commCheckHalfClosed, NULL, 1.0, false);
4d7add01 1068 }
62e76326 1069
dbe4fd8e 1070 configured_once = 1;
4d64d74a 1071}
1072
6c1962dd 1073#if USE_WIN32_SERVICE
1074/* When USE_WIN32_SERVICE is defined, the main function is placed in win32.cc */
1075extern "C" void WINAPI
a0aa9e74 1076 SquidWinSvcMain(int argc, char **argv)
1077{
1078 SquidMain(argc, argv);
1079}
1080
1081int
1082SquidMain(int argc, char **argv)
6c1962dd 1083#else
b8d8561b 1084int
1085main(int argc, char **argv)
9b7292ce 1086#endif
1087{
9b7292ce 1088 mode_t oldmask;
a0aa9e74 1089#ifdef _SQUID_WIN32_
1090
1091 int WIN32_init_err;
1092#endif
4d64d74a 1093
a4ba1105 1094#if HAVE_SBRK
62e76326 1095
9b7292ce 1096 sbrk_start = sbrk(0);
a4ba1105 1097#endif
1098
3dc275d6 1099 Debug::parseOptions("ALL,1");
9b7292ce 1100 debug_log = stderr;
62e76326 1101
b9269882 1102#if defined(SQUID_MAXFD_LIMIT)
1103
1104 if (SQUID_MAXFD_LIMIT < Squid_MaxFD)
1105 Squid_MaxFD = SQUID_MAXFD_LIMIT;
1106
1107#endif
399e85ea 1108
ec4daaa5 1109#ifdef _SQUID_WIN32_
6c1962dd 1110
a0aa9e74 1111 if ((WIN32_init_err = WIN32_Subsystem_Init(&argc, &argv)))
1112 return WIN32_init_err;
62e76326 1113
0e6d05ef 1114#endif
1115
9b7292ce 1116 /* call mallopt() before anything else */
0b29fe44 1117#if HAVE_MALLOPT
7328e889 1118#ifdef M_GRAIN
9b7292ce 1119 /* Round up all sizes to a multiple of this */
1120 mallopt(M_GRAIN, 16);
62e76326 1121
7328e889 1122#endif
1123#ifdef M_MXFAST
9b7292ce 1124 /* biggest size that is considered a small block */
1125 mallopt(M_MXFAST, 256);
62e76326 1126
7328e889 1127#endif
1128#ifdef M_NBLKS
9b7292ce 1129 /* allocate this many small blocks at once */
1130 mallopt(M_NLBLKS, 32);
62e76326 1131
7328e889 1132#endif
1133#endif /* HAVE_MALLOPT */
1134
9b7292ce 1135 /*
1136 * The plan here is to set the umask to 007 (deny others for
1137 * read,write,execute), but only if the umask is not already
1138 * set. Unfortunately, there is no way to get the current
1139 * umask value without setting it.
1140 */
1141 oldmask = umask(S_IRWXO);
62e76326 1142
9b7292ce 1143 if (oldmask)
1144 umask(oldmask);
7e3ce7b9 1145
ddfcbc22 1146 memset(&local_addr, '\0', sizeof(struct IN_ADDR));
62e76326 1147
9b7292ce 1148 safe_inet_addr(localhost, &local_addr);
62e76326 1149
ddfcbc22 1150 memset(&any_addr, '\0', sizeof(struct IN_ADDR));
62e76326 1151
9b7292ce 1152 safe_inet_addr("0.0.0.0", &any_addr);
62e76326 1153
ddfcbc22 1154 memset(&no_addr, '\0', sizeof(struct IN_ADDR));
62e76326 1155
9b7292ce 1156 safe_inet_addr("255.255.255.255", &no_addr);
62e76326 1157
9b7292ce 1158 squid_srandom(time(NULL));
4d64d74a 1159
9b7292ce 1160 getCurrentTime();
62e76326 1161
9b7292ce 1162 squid_start = current_time;
62e76326 1163
9b7292ce 1164 failure_notify = fatal_dump;
4d64d74a 1165
6c1962dd 1166#if USE_WIN32_SERVICE
1167
9b7292ce 1168 WIN32_svcstatusupdate(SERVICE_START_PENDING, 10000);
6c1962dd 1169
1170#endif
1171
9b7292ce 1172 mainParseOptions(argc, argv);
4d64d74a 1173
6c1962dd 1174#if USE_WIN32_SERVICE
1175
a0aa9e74 1176 if (opt_install_service)
1177 {
9b7292ce 1178 WIN32_InstallService();
a0aa9e74 1179 return 0;
9b7292ce 1180 }
6c1962dd 1181
a0aa9e74 1182 if (opt_remove_service)
1183 {
9b7292ce 1184 WIN32_RemoveService();
a0aa9e74 1185 return 0;
9b7292ce 1186 }
6c1962dd 1187
a0aa9e74 1188 if (opt_command_line)
1189 {
9b7292ce 1190 WIN32_SetServiceCommandLine();
a0aa9e74 1191 return 0;
9b7292ce 1192 }
6c1962dd 1193
1194#endif
1195
9b7292ce 1196 /* parse configuration file
1197 * note: in "normal" case this used to be called from mainInitialize() */
1198 {
1199 int parse_err;
62e76326 1200
9b7292ce 1201 if (!ConfigFile)
1202 ConfigFile = xstrdup(DefaultConfigFile);
62e76326 1203
9b7292ce 1204 assert(!configured_once);
62e76326 1205
9b7292ce 1206 Mem::Init();
62e76326 1207
9b7292ce 1208 storeFsInit(); /* required for config parsing */
62e76326 1209
b9ae18aa 1210 /* May not be needed for parsing, have not audited for such */
1211 DiskIOModule::SetupAllModules();
1212
59b2d47f 1213 /* Shouldn't be needed for config parsing, but have not audited for such */
1214 StoreFileSystem::SetupAllFs();
1215
c8f4eac4 1216 /* we may want the parsing process to set this up in the future */
1217 Store::Root(new StoreController);
1218
62ee09ca 1219 parse_err = parseConfigFile(ConfigFile, manager);
62e76326 1220
9b7292ce 1221 if (opt_parse_cfg_only)
6c1962dd 1222
9b7292ce 1223 return parse_err;
9b7292ce 1224 }
1225 if (-1 == opt_send_signal)
1226 if (checkRunningPid())
1227 exit(1);
e13ee7ad 1228
9bc73deb 1229#if TEST_ACCESS
62e76326 1230
9b7292ce 1231 comm_init();
62e76326 1232
9b7292ce 1233 comm_select_init();
62e76326 1234
9b7292ce 1235 mainInitialize();
62e76326 1236
9b7292ce 1237 test_access();
62e76326 1238
9b7292ce 1239 return 0;
62e76326 1240
9bc73deb 1241#endif
1242
9b7292ce 1243 /* send signal to running copy and exit */
a0aa9e74 1244 if (opt_send_signal != -1)
1245 {
9b7292ce 1246 /* chroot if configured to run inside chroot */
62e76326 1247
a572d8be 1248 if (Config.chroot_dir) {
1249 if (chroot(Config.chroot_dir))
1250 fatal("failed to chroot");
1251
1252 no_suid();
1253 } else {
1254 leave_suid();
9b7292ce 1255 }
62e76326 1256
9b7292ce 1257 sendSignal();
1258 /* NOTREACHED */
1259 }
62e76326 1260
a0aa9e74 1261 if (opt_create_swap_dirs)
1262 {
9b7292ce 1263 /* chroot if configured to run inside chroot */
0e657244 1264
9b7292ce 1265 if (Config.chroot_dir && chroot(Config.chroot_dir)) {
1266 fatal("failed to chroot");
1267 }
62e76326 1268
9b7292ce 1269 setEffectiveUser();
1270 debug(0, 0) ("Creating Swap Directories\n");
c8f4eac4 1271 Store::Root().create();
6c1962dd 1272
9b7292ce 1273 return 0;
9b7292ce 1274 }
62e76326 1275
9b7292ce 1276 if (!opt_no_daemon)
1277 watch_child(argv);
62e76326 1278
9b7292ce 1279 setMaxFD();
4d64d74a 1280
9b7292ce 1281 /* init comm module */
1282 comm_init();
62e76326 1283
9b7292ce 1284 comm_select_init();
4d64d74a 1285
a0aa9e74 1286 if (opt_no_daemon)
1287 {
9b7292ce 1288 /* we have to init fdstat here. */
1289 fd_open(0, FD_LOG, "stdin");
1290 fd_open(1, FD_LOG, "stdout");
1291 fd_open(2, FD_LOG, "stderr");
1292 }
62e76326 1293
6c1962dd 1294#if USE_WIN32_SERVICE
1295
9b7292ce 1296 WIN32_svcstatusupdate(SERVICE_START_PENDING, 10000);
6c1962dd 1297
1298#endif
1299
9b7292ce 1300 mainInitialize();
4d64d74a 1301
6c1962dd 1302#if USE_WIN32_SERVICE
1303
9b7292ce 1304 WIN32_svcstatusupdate(SERVICE_RUNNING, 0);
6c1962dd 1305
1306#endif
1307
9b7292ce 1308 /* main loop */
a553a5a3 1309 EventLoop mainLoop;
62e76326 1310
a553a5a3 1311 SignalDispatcher signal_dispatcher(mainLoop);
6c1962dd 1312
a553a5a3 1313 mainLoop.registerDispatcher(&signal_dispatcher);
62e76326 1314
a553a5a3 1315 /* TODO: stop requiring the singleton here */
1316 mainLoop.registerDispatcher(EventDispatcher::GetInstance());
62e76326 1317
8ff3fa2e 1318 /* TODO: stop requiring the singleton here */
1319 mainLoop.registerEngine(EventScheduler::GetInstance());
62e76326 1320
8ff3fa2e 1321 StoreRootEngine store_engine;
615f9581 1322
8ff3fa2e 1323 mainLoop.registerEngine(&store_engine);
a774fd3f 1324
8ff3fa2e 1325 CommDispatcher comm_dispatcher;
c2e8186f 1326
8ff3fa2e 1327 mainLoop.registerDispatcher(&comm_dispatcher);
1328
1329 CommSelectEngine comm_engine;
1330
8ff3fa2e 1331 mainLoop.registerEngine(&comm_engine);
1332
bef81ea5 1333 mainLoop.setPrimaryEngine(&comm_engine);
1334
8ff3fa2e 1335 /* use the standard time service */
1336 TimeEngine time_engine;
1337
1338 mainLoop.setTimeService(&time_engine);
1339
1340 mainLoop.run();
1341
1342 if (mainLoop.errcount == 10)
1343 fatal_dump("Event loop exited with failure.");
1344
1345 /* shutdown squid now */
1346 SquidShutdown();
62e76326 1347
9b7292ce 1348 /* NOTREACHED */
9b7292ce 1349 return 0;
090089c4 1350}
7690e8eb 1351
b8d8561b 1352static void
0673c0ba 1353sendSignal(void)
7690e8eb 1354{
ff8d0ea6 1355 pid_t pid;
fedac7e5 1356 debug_log = stderr;
258ac4d7 1357
1358 if (strcmp(Config.pidFilename, "none") == 0) {
1359 debug(0, 1) ("No pid_filename specified. Trusting you know what you are doing.\n");
1360 }
1361
fedac7e5 1362 pid = readPidFile();
62e76326 1363
fedac7e5 1364 if (pid > 1) {
6c1962dd 1365#if USE_WIN32_SERVICE
1366
1367 if (opt_signal_service) {
1368 WIN32_sendSignal(opt_send_signal);
1369 exit(0);
1370 } else
1371#ifdef _SQUID_MSWIN_
1372 {
1373 fprintf(stderr, "%s: ERROR: Could not send ", appname);
1374 fprintf(stderr, "signal to Squid Service:\n");
1375 fprintf(stderr, "missing -n command line switch.\n");
1376 exit(1);
1377 }
1378
1379 /* NOTREACHED */
1380#endif
1381
1382#endif
1383
62e76326 1384 if (kill(pid, opt_send_signal) &&
1385 /* ignore permissions if just running check */
1386 !(opt_send_signal == 0 && errno == EPERM)) {
1387 fprintf(stderr, "%s: ERROR: Could not send ", appname);
1388 fprintf(stderr, "signal %d to process %d: %s\n",
1389 opt_send_signal, (int) pid, xstrerror());
1390 exit(1);
1391 }
fedac7e5 1392 } else {
62e76326 1393 fprintf(stderr, "%s: ERROR: No running copy\n", appname);
1394 exit(1);
7690e8eb 1395 }
62e76326 1396
fedac7e5 1397 /* signal successfully sent */
1398 exit(0);
1399}
f95b8144 1400
a50bfe93 1401#ifndef _SQUID_MSWIN_
e18d7fdc 1402/*
1403 * This function is run when Squid is in daemon mode, just
1404 * before the parent forks and starts up the child process.
1405 * It can be used for admin-specific tasks, such as notifying
1406 * someone that Squid is (re)started.
1407 */
1408static void
1409mainStartScript(const char *prog)
1410{
1411 char script[SQUID_MAXPATHLEN];
1412 char *t;
1413 size_t sl = 0;
1414 pid_t cpid;
1415 pid_t rpid;
1416 xstrncpy(script, prog, MAXPATHLEN);
62e76326 1417
e18d7fdc 1418 if ((t = strrchr(script, '/'))) {
62e76326 1419 *(++t) = '\0';
1420 sl = strlen(script);
e18d7fdc 1421 }
62e76326 1422
e18d7fdc 1423 xstrncpy(&script[sl], squid_start_script, MAXPATHLEN - sl);
62e76326 1424
e18d7fdc 1425 if ((cpid = fork()) == 0) {
62e76326 1426 /* child */
f75662c9 1427 execl(script, squid_start_script, (char *)NULL);
482aa790 1428 _exit(-1);
e18d7fdc 1429 } else {
62e76326 1430 do {
e18d7fdc 1431#ifdef _SQUID_NEXT_
62e76326 1432 union wait status;
1433 rpid = wait3(&status, 0, NULL);
e18d7fdc 1434#else
62e76326 1435
1436 int status;
1437 rpid = waitpid(-1, &status, 0);
e18d7fdc 1438#endif
62e76326 1439
1440 } while (rpid != cpid);
e18d7fdc 1441 }
1442}
1443
a50bfe93 1444#endif /* _SQUID_MSWIN_ */
1445
efd900cb 1446static int
1447checkRunningPid(void)
1448{
1449 pid_t pid;
e0077312 1450
1451 if (!debug_log)
1452 debug_log = stderr;
1453
efd900cb 1454 pid = readPidFile();
62e76326 1455
efd900cb 1456 if (pid < 2)
62e76326 1457 return 0;
1458
efd900cb 1459 if (kill(pid, 0) < 0)
62e76326 1460 return 0;
1461
cb7a4fcb 1462 debugs(0, 0, "Squid is already running! Process ID " << pid);
62e76326 1463
efd900cb 1464 return 1;
1465}
1466
f95b8144 1467static void
bbe199dc 1468watch_child(char *argv[])
f95b8144 1469{
a50bfe93 1470#ifndef _SQUID_MSWIN_
f95b8144 1471 char *prog;
f95b8144 1472 int failcount = 0;
1473 time_t start;
1474 time_t stop;
1475#ifdef _SQUID_NEXT_
62e76326 1476
f95b8144 1477 union wait status;
1478#else
62e76326 1479
f95b8144 1480 int status;
1481#endif
62e76326 1482
e3a3b845 1483 pid_t pid;
c99c5397 1484#ifdef TIOCNOTTY
1485
54f742e7 1486 int i;
c99c5397 1487#endif
1488
742724a4 1489 int nullfd;
62e76326 1490
f95b8144 1491 if (*(argv[0]) == '(')
62e76326 1492 return;
1493
54f742e7 1494 openlog(appname, LOG_PID | LOG_NDELAY | LOG_CONS, LOG_LOCAL4);
62e76326 1495
54f742e7 1496 if ((pid = fork()) < 0)
62e76326 1497 syslog(LOG_ALERT, "fork failed: %s", xstrerror());
54f742e7 1498 else if (pid > 0)
62e76326 1499 exit(0);
1500
54f742e7 1501 if (setsid() < 0)
62e76326 1502 syslog(LOG_ALERT, "setsid failed: %s", xstrerror());
1503
efd900cb 1504 closelog();
62e76326 1505
54f742e7 1506#ifdef TIOCNOTTY
62e76326 1507
c4aefe96 1508 if ((i = open("/dev/tty", O_RDWR | O_TEXT)) >= 0) {
62e76326 1509 ioctl(i, TIOCNOTTY, NULL);
1510 close(i);
54f742e7 1511 }
62e76326 1512
54f742e7 1513#endif
b05490a8 1514
7f6ffd15 1515 /*
1516 * RBCOLLINS - if cygwin stackdumps when squid is run without
1517 * -N, check the cygwin1.dll version, it needs to be AT LEAST
1518 * 1.1.3. execvp had a bit overflow error in a loop..
1519 */
742724a4 1520 /* Connect stdio to /dev/null in daemon mode */
4da086c4 1521 nullfd = open(_PATH_DEVNULL, O_RDWR | O_TEXT);
62e76326 1522
e4a1325e 1523 if (nullfd < 0)
4da086c4 1524 fatalf(_PATH_DEVNULL " %s\n", xstrerror());
e4a1325e 1525
742724a4 1526 dup2(nullfd, 0);
62e76326 1527
742724a4 1528 if (opt_debug_stderr < 0) {
62e76326 1529 dup2(nullfd, 1);
1530 dup2(nullfd, 2);
742724a4 1531 }
62e76326 1532
f95b8144 1533 for (;;) {
62e76326 1534 mainStartScript(argv[0]);
1535
1536 if ((pid = fork()) == 0) {
1537 /* child */
1538 openlog(appname, LOG_PID | LOG_NDELAY | LOG_CONS, LOG_LOCAL4);
1539 prog = xstrdup(argv[0]);
1540 argv[0] = xstrdup("(squid)");
1541 execvp(prog, argv);
1542 syslog(LOG_ALERT, "execvp failed: %s", xstrerror());
1543 }
1544
1545 /* parent */
1546 openlog(appname, LOG_PID | LOG_NDELAY | LOG_CONS, LOG_LOCAL4);
1547
1548 syslog(LOG_NOTICE, "Squid Parent: child process %d started", pid);
1549
1550 time(&start);
1551
1552 squid_signal(SIGINT, SIG_IGN, SA_RESTART);
1553
f95b8144 1554#ifdef _SQUID_NEXT_
62e76326 1555
1556 pid = wait3(&status, 0, NULL);
1557
f95b8144 1558#else
62e76326 1559
1560 pid = waitpid(-1, &status, 0);
1561
1562#endif
1563
1564 time(&stop);
1565
1566 if (WIFEXITED(status)) {
1567 syslog(LOG_NOTICE,
1568 "Squid Parent: child process %d exited with status %d",
1569 pid, WEXITSTATUS(status));
1570 } else if (WIFSIGNALED(status)) {
1571 syslog(LOG_NOTICE,
1572 "Squid Parent: child process %d exited due to signal %d",
1573 pid, WTERMSIG(status));
1574 } else {
1575 syslog(LOG_NOTICE, "Squid Parent: child process %d exited", pid);
1576 }
1577
1578 if (stop - start < 10)
1579 failcount++;
1580 else
1581 failcount = 0;
1582
1583 if (failcount == 5) {
1584 syslog(LOG_ALERT, "Exiting due to repeated, frequent failures");
1585 exit(1);
1586 }
1587
1588 if (WIFEXITED(status))
1589 if (WEXITSTATUS(status) == 0)
1590 exit(0);
1591
1592 if (WIFSIGNALED(status)) {
1593 switch (WTERMSIG(status)) {
1594
1595 case SIGKILL:
1596 exit(0);
1597 break;
1598
1599 default:
1600 break;
1601 }
1602 }
1603
1604 squid_signal(SIGINT, SIG_DFL, SA_RESTART);
1605 sleep(3);
f95b8144 1606 }
62e76326 1607
bbe199dc 1608 /* NOTREACHED */
a50bfe93 1609#endif /* _SQUID_MSWIN_ */
a572d8be 1610
f95b8144 1611}
fff6ad65 1612
9ec1a1dc 1613static void
8ff3fa2e 1614SquidShutdown()
fff6ad65 1615{
6c1962dd 1616#if USE_WIN32_SERVICE
1617 WIN32_svcstatusupdate(SERVICE_STOP_PENDING, 10000);
1618#endif
1619
fff6ad65 1620 debug(1, 1) ("Shutting down...\n");
95a83c22 1621#if USE_DNSSERVERS
1622
1623 dnsShutdown();
1624#else
1625
1626 idnsShutdown();
1627#endif
1628
1629 redirectShutdown();
1630 externalAclShutdown();
d723bf6b 1631 icpConnectionClose();
1632#if USE_HTCP
62e76326 1633
d723bf6b 1634 htcpSocketClose();
1635#endif
1636#ifdef SQUID_SNMP
62e76326 1637
d723bf6b 1638 snmpConnectionClose();
320e9f36 1639#endif
eb824054 1640#if USE_WCCP
62e76326 1641
320e9f36 1642 wccpConnectionClose();
d723bf6b 1643#endif
0b0cfcf2 1644#if USE_WCCPv2
1645
1646 wccp2ConnectionClose();
1647#endif
62e76326 1648
fff6ad65 1649 releaseServerSockets();
d723bf6b 1650 commCloseAllSockets();
515ec4dc 1651#if DELAY_POOLS
62e76326 1652
b67e2c8c 1653 DelayPools::FreePools();
515ec4dc 1654#endif
62e76326 1655
5dae8514 1656 authenticateShutdown();
a3d0a19d 1657#if USE_UNLINKD
62e76326 1658
fff6ad65 1659 unlinkdClose();
a3d0a19d 1660#endif
6c1962dd 1661#if USE_WIN32_SERVICE
1662
1663 WIN32_svcstatusupdate(SERVICE_STOP_PENDING, 10000);
1664#endif
62e76326 1665
c8f4eac4 1666 Store::Root().sync(); /* Flush pending object writes/unlinks */
fff6ad65 1667 storeDirWriteCleanLogs(0);
1668 PrintRusage();
1669 dumpMallocStats();
c8f4eac4 1670 Store::Root().sync(); /* Flush log writes */
fff6ad65 1671 storeLogClose();
1672 accessLogClose();
5b824235 1673 useragentLogClose();
c9b99797 1674 refererCloseLog();
225644d7 1675#if WIP_FWD_LOG
62e76326 1676
225644d7 1677 fwdUninit();
1678#endif
62e76326 1679
c8f4eac4 1680 Store::Root().sync(); /* Flush log close */
59b2d47f 1681 StoreFileSystem::FreeAllFs();
b9ae18aa 1682 DiskIOModule::FreeAllModules();
afec404b 1683#if LEAK_CHECK_MODE && 0 /* doesn't work at the moment */
62e76326 1684
fff6ad65 1685 configFreeMemory();
1686 storeFreeMemory();
33ab18e8 1687 /*stmemFreeMemory(); */
fff6ad65 1688 netdbFreeMemory();
1689 ipcacheFreeMemory();
1690 fqdncacheFreeMemory();
1691 asnFreeMemory();
26a369ba 1692 clientdbFreeMemory();
7021844c 1693 httpHeaderCleanModule();
d2db411c 1694 statFreeMemory();
f1fc2a8d 1695 eventFreeMemory();
c68e9c6b 1696 mimeFreeMemory();
1697 errorClean();
fff6ad65 1698#endif
26a369ba 1699#if !XMALLOC_TRACE
62e76326 1700
54f742e7 1701 if (opt_no_daemon) {
62e76326 1702 file_close(0);
1703 file_close(1);
1704 file_close(2);
54f742e7 1705 }
62e76326 1706
33ab18e8 1707#endif
fff6ad65 1708 fdDumpOpen();
62e76326 1709
fff6ad65 1710 fdFreeMemory();
62e76326 1711
ddb43c58 1712 memClean();
62e76326 1713
33ab18e8 1714#if XMALLOC_TRACE
62e76326 1715
26a369ba 1716 xmalloc_find_leaks();
62e76326 1717
26a369ba 1718 debug(1, 0) ("Memory used after shutdown: %d\n", xmalloc_total);
62e76326 1719
33ab18e8 1720#endif
36a97e19 1721#if MEM_GEN_TRACE
62e76326 1722
399e85ea 1723 log_trace_done();
62e76326 1724
36a97e19 1725#endif
62e76326 1726
ab50ee9e 1727 if (Config.pidFilename && strcmp(Config.pidFilename, "none") != 0) {
62e76326 1728 enter_suid();
1729 safeunlink(Config.pidFilename, 0);
1730 leave_suid();
ab50ee9e 1731 }
62e76326 1732
a60f7062 1733 debug(1, 1) ("Squid Cache (Version %s): Exiting normally.\n",
62e76326 1734 version_string);
1735
7e3ce7b9 1736 if (debug_log)
62e76326 1737 fclose(debug_log);
1738
ae1feb30 1739 exit(shutdown_status);
fff6ad65 1740}
bef81ea5 1741