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