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