]> git.ipfire.org Git - thirdparty/squid.git/blame - src/main.cc
fix swapfileno wierdness with 'SwapOutStartComplete', just set
[thirdparty/squid.git] / src / main.cc
CommitLineData
30a4f2a8 1/*
0d90407c 2 * $Id: main.cc,v 1.147 1997/05/15 23:33:43 wessels Exp $
30a4f2a8 3 *
4 * DEBUG: section 1 Startup and Main Loop
5 * AUTHOR: Harvest Derived
6 *
42c04c16 7 * SQUID Internet Object Cache http://squid.nlanr.net/Squid/
30a4f2a8 8 * --------------------------------------------------------
9 *
10 * Squid is the result of efforts by numerous individuals from the
11 * Internet community. Development is led by Duane Wessels of the
12 * National Laboratory for Applied Network Research and funded by
13 * the National Science Foundation.
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 *
29 */
30
31/*
32 * Copyright (c) 1994, 1995. All rights reserved.
33 *
34 * The Harvest software was developed by the Internet Research Task
35 * Force Research Group on Resource Discovery (IRTF-RD):
36 *
37 * Mic Bowman of Transarc Corporation.
38 * Peter Danzig of the University of Southern California.
39 * Darren R. Hardy of the University of Colorado at Boulder.
40 * Udi Manber of the University of Arizona.
41 * Michael F. Schwartz of the University of Colorado at Boulder.
42 * Duane Wessels of the University of Colorado at Boulder.
43 *
44 * This copyright notice applies to software in the Harvest
45 * ``src/'' directory only. Users should consult the individual
46 * copyright notices in the ``components/'' subdirectories for
47 * copyright information about other software bundled with the
48 * Harvest source code distribution.
49 *
50 * TERMS OF USE
51 *
52 * The Harvest software may be used and re-distributed without
53 * charge, provided that the software origin and research team are
54 * cited in any use of the system. Most commonly this is
55 * accomplished by including a link to the Harvest Home Page
56 * (http://harvest.cs.colorado.edu/) from the query page of any
57 * Broker you deploy, as well as in the query result pages. These
58 * links are generated automatically by the standard Broker
59 * software distribution.
60 *
61 * The Harvest software is provided ``as is'', without express or
62 * implied warranty, and with no support nor obligation to assist
63 * in its use, correction, modification or enhancement. We assume
64 * no liability with respect to the infringement of copyrights,
65 * trade secrets, or any patents, and are not responsible for
66 * consequential damages. Proper use of the Harvest software is
67 * entirely the responsibility of the user.
68 *
69 * DERIVATIVE WORKS
70 *
71 * Users may make derivative works from the Harvest software, subject
72 * to the following constraints:
73 *
74 * - You must include the above copyright notice and these
75 * accompanying paragraphs in all forms of derivative works,
76 * and any documentation and other materials related to such
77 * distribution and use acknowledge that the software was
78 * developed at the above institutions.
79 *
80 * - You must notify IRTF-RD regarding your distribution of
81 * the derivative work.
82 *
83 * - You must clearly notify users that your are distributing
84 * a modified version and not the original Harvest software.
85 *
86 * - Any derivative product is also subject to these copyright
87 * and use restrictions.
88 *
89 * Note that the Harvest software is NOT in the public domain. We
90 * retain copyright, as specified above.
91 *
92 * HISTORY OF FREE SOFTWARE STATUS
93 *
94 * Originally we required sites to license the software in cases
95 * where they were going to build commercial products/services
96 * around Harvest. In June 1995 we changed this policy. We now
97 * allow people to use the core Harvest software (the code found in
98 * the Harvest ``src/'' directory) for free. We made this change
99 * in the interest of encouraging the widest possible deployment of
100 * the technology. The Harvest software is really a reference
101 * implementation of a set of protocols and formats, some of which
102 * we intend to standardize. We encourage commercial
103 * re-implementations of code complying to this set of standards.
104 */
44a47c6e 105
106#include "squid.h"
107
b8de7ebe 108time_t squid_starttime = 0;
812ed90c 109int HttpSockets[MAXHTTPPORTS];
110int NHttpSockets = 0;
30a4f2a8 111int theInIcpConnection = -1;
112int theOutIcpConnection = -1;
9d4b2981 113int vizSock = -1;
090089c4 114int do_reuse = 1;
30a4f2a8 115int opt_reload_hit_only = 0; /* only UDP_HIT during store relaod */
1758c627 116int opt_catch_signals = 1;
30a4f2a8 117int opt_dns_tests = 1;
118int opt_foreground_rebuild = 0;
b6f794d6 119int opt_zap_disk_store = 0;
6e40f263 120int opt_syslog_enable = 0; /* disabled by default */
1758c627 121int opt_no_ipcache = 0; /* use ipcache by default */
fedac7e5 122static int opt_send_signal = -1; /* no signal to send */
c62bf0f1 123int opt_udp_hit_obj = 0; /* ask for HIT_OBJ's */
caebbe00 124int opt_mem_pools = 1;
125int opt_forwarded_for = 1;
0dc8ff75 126int opt_accel_uses_host = 0;
0d90407c 127int opt_debug_stderr = 0;
090089c4 128int vhost_mode = 0;
e83892e9 129int Squid_MaxFD = SQUID_MAXFD;
429fdbec 130int Biggest_FD = -1;
131int select_loops = 0; /* how many times thru select loop */
235c7b49 132volatile int unbuffered_logs = 1; /* debug and hierarchy unbuffered by default */
133volatile int shutdown_pending = 0; /* set by SIGTERM handler (shut_down()) */
134volatile int reread_pending = 0; /* set by SIGHUP handler */
0ee4272b 135const char *const version_string = SQUID_VERSION;
136const char *const appname = "squid";
137const char *const localhost = "127.0.0.1";
30a4f2a8 138struct in_addr local_addr;
28070024 139struct in_addr no_addr;
48f44632 140struct in_addr theOutICPAddr;
0ee4272b 141const char *const dash_str = "-";
142const char *const null_string = "";
d99cc93b 143const char *const w_space = " \t\n\r";
8e81a68a 144char ThisCache[SQUIDHOSTNAMELEN << 1];
30a4f2a8 145
146/* for error reporting from xmalloc and friends */
0ee4272b 147extern void (*failure_notify) _PARAMS((const char *));
30a4f2a8 148
67508012 149static volatile int rotate_pending = 0; /* set by SIGUSR1 handler */
30a4f2a8 150static int httpPortNumOverride = 1;
151static int icpPortNumOverride = 1; /* Want to detect "-u 0" */
e924600d 152static struct in_addr any_addr;
30a4f2a8 153#if MALLOC_DBG
4d64d74a 154static int malloc_debug_level = 0;
30a4f2a8 155#endif
4d7add01 156
67508012 157static void rotate_logs _PARAMS((int));
158static void reconfigure _PARAMS((int));
159static void mainInitialize _PARAMS((void));
160static void mainReinitialize _PARAMS((void));
67508012 161static void usage _PARAMS((void));
162static void mainParseOptions _PARAMS((int, char **));
163static void sendSignal _PARAMS((void));
24382924 164static void serverConnectionsOpen _PARAMS((void));
b8d8561b 165
166static void
0673c0ba 167usage(void)
ccff9601 168{
0ee4272b 169 fprintf(stderr,
170 "Usage: %s [-hsvzCDFRUVY] [-f config-file] [-[au] port] [-k signal]\n"
171 " -a port Specify ASCII port number (default: %d).\n"
429fdbec 172 " -b Buffer log output (default is unbuffered).\n"
0d90407c 173 " -d Write debugging to stderr also.\n"
0ee4272b 174 " -f file Use given config-file instead of\n"
175 " %s\n"
176 " -h Print help message.\n"
177 " -i Disable IP caching.\n"
178 " -k reconfigure|rotate|shutdown|interrupt|kill|debug|check\n"
179 " Send signal to running copy and exit.\n"
180 " -s Enable logging to syslog.\n"
181 " -u port Specify ICP port number (default: %d), disable with 0.\n"
182 " -v Print version.\n"
183 " -z Zap disk storage -- deletes all objects in disk cache.\n"
184 " -C Do not catch fatal signals.\n"
185 " -D Disable initial DNS tests.\n"
186 " -F Foreground fast store rebuild.\n"
187 " -R Do not set REUSEADDR on port.\n"
188 " -U Unlink expired objects on reload.\n"
189 " -V Virtual host httpd-accelerator.\n"
429fdbec 190 " -Y Only return UDP_HIT or UDP_MISS_NOFETCH during fast reload.\n",
30a4f2a8 191 appname, CACHE_HTTP_PORT, DefaultConfigFile, CACHE_ICP_PORT);
77ffc99f 192 exit(1);
ccff9601 193}
194
b8d8561b 195static void
196mainParseOptions(int argc, char *argv[])
090089c4 197{
090089c4 198 extern char *optarg;
4d64d74a 199 int c;
090089c4 200
0d90407c 201 while ((c = getopt(argc, argv, "CDFRVYXa:bdf:hik:m:su:vz?")) != -1) {
090089c4 202 switch (c) {
090089c4 203 case 'C':
1758c627 204 opt_catch_signals = 0;
090089c4 205 break;
206 case 'D':
30a4f2a8 207 opt_dns_tests = 0;
090089c4 208 break;
30a4f2a8 209 case 'F':
210 opt_foreground_rebuild = 1;
090089c4 211 break;
090089c4 212 case 'R':
213 do_reuse = 0;
214 break;
30a4f2a8 215 case 'V':
216 vhost_mode = 1;
217 break;
e924600d 218 case 'X':
219 /* force full debugging */
220 sigusr2_handle(SIGUSR2);
221 break;
30a4f2a8 222 case 'Y':
223 opt_reload_hit_only = 1;
224 break;
225 case 'a':
226 httpPortNumOverride = atoi(optarg);
227 break;
228 case 'b':
229 unbuffered_logs = 0;
230 break;
0d90407c 231 case 'd':
232 opt_debug_stderr = 1;
233 break;
090089c4 234 case 'f':
00fac1f8 235 xfree(ConfigFile);
236 ConfigFile = xstrdup(optarg);
090089c4 237 break;
30a4f2a8 238 case 'h':
239 usage();
090089c4 240 break;
1758c627 241 case 'i':
242 opt_no_ipcache = 1;
243 break;
7690e8eb 244 case 'k':
24382924 245 if ((int) strlen(optarg) < 1)
7690e8eb 246 usage();
247 if (!strncmp(optarg, "reconfigure", strlen(optarg)))
248 opt_send_signal = SIGHUP;
249 else if (!strncmp(optarg, "rotate", strlen(optarg)))
250 opt_send_signal = SIGUSR1;
251 else if (!strncmp(optarg, "debug", strlen(optarg)))
252 opt_send_signal = SIGUSR2;
253 else if (!strncmp(optarg, "shutdown", strlen(optarg)))
254 opt_send_signal = SIGTERM;
6759a5fb 255 else if (!strncmp(optarg, "interrupt", strlen(optarg)))
256 opt_send_signal = SIGINT;
7690e8eb 257 else if (!strncmp(optarg, "kill", strlen(optarg)))
258 opt_send_signal = SIGKILL;
259 else if (!strncmp(optarg, "check", strlen(optarg)))
fedac7e5 260 opt_send_signal = 0; /* SIGNULL */
7690e8eb 261 else
262 usage();
263 break;
090089c4 264 case 'm':
30a4f2a8 265#if MALLOC_DBG
090089c4 266 malloc_debug_level = atoi(optarg);
34c54bb6 267 /* NOTREACHED */
090089c4 268 break;
30a4f2a8 269#else
270 fatal("Need to add -DMALLOC_DBG when compiling to use -m option");
24382924 271 /* NOTREACHED */
30a4f2a8 272#endif
273 case 's':
6e40f263 274 opt_syslog_enable = 1;
30a4f2a8 275 break;
276 case 'u':
277 icpPortNumOverride = atoi(optarg);
278 if (icpPortNumOverride < 0)
279 icpPortNumOverride = 0;
280 break;
281 case 'v':
282 printf("Squid Cache: Version %s\n", version_string);
283 exit(0);
284 /* NOTREACHED */
090089c4 285 case 'z':
b6f794d6 286 opt_zap_disk_store = 1;
090089c4 287 break;
288 case '?':
090089c4 289 default:
ccff9601 290 usage();
090089c4 291 break;
292 }
090089c4 293 }
4d64d74a 294}
090089c4 295
b8d8561b 296static void
297rotate_logs(int sig)
30a4f2a8 298{
cadc2d55 299 debug(1, 1, "rotate_logs: SIGUSR1 received.\n");
30a4f2a8 300 rotate_pending = 1;
301#if !HAVE_SIGACTION
302 signal(sig, rotate_logs);
303#endif
304}
305
b8d8561b 306static void
307reconfigure(int sig)
30a4f2a8 308{
cadc2d55 309 debug(1, 1, "reconfigure: SIGHUP received\n");
310 debug(1, 1, "Waiting %d seconds for active connections to finish\n",
5c5783a2 311 Config.shutdownLifetime);
30a4f2a8 312 reread_pending = 1;
313#if !HAVE_SIGACTION
314 signal(sig, reconfigure);
315#endif
316}
317
b8d8561b 318void
319shut_down(int sig)
30a4f2a8 320{
f3753518 321 shutdown_pending = sig == SIGINT ? -1 : 1;
cadc2d55 322 debug(1, 1, "Preparing for shutdown after %d connections\n",
30a4f2a8 323 ntcpconn + nudpconn);
cadc2d55 324 debug(1, 1, "Waiting %d seconds for active connections to finish\n",
5c5783a2 325 shutdown_pending > 0 ? Config.shutdownLifetime : 0);
cadc2d55 326#ifdef KILL_PARENT_OPT
327 debug(1, 1, "Killing RunCache, pid %d\n", getppid());
328 kill(getppid(), sig);
329#endif
6e40f263 330#if SA_RESETHAND == 0
331 signal(SIGTERM, SIG_DFL);
332 signal(SIGINT, SIG_DFL);
333#endif
30a4f2a8 334}
335
24382924 336static void
0673c0ba 337serverConnectionsOpen(void)
4d64d74a 338{
30a4f2a8 339 struct in_addr addr;
651ca9d8 340 struct sockaddr_in xaddr;
30a4f2a8 341 u_short port;
48f44632 342 int len;
343 int x;
812ed90c 344 int fd;
0d90407c 345 for (x = 0; x < Config.Port.n_http; x++) {
346 enter_suid();
347 fd = comm_open(SOCK_STREAM,
812ed90c 348 0,
349 Config.Addrs.tcp_incoming,
350 Config.Port.http[x],
351 COMM_NONBLOCKING,
352 "HTTP Socket");
0d90407c 353 leave_suid();
812ed90c 354 if (fd < 0)
0d90407c 355 continue;
356 comm_listen(fd);
357 commSetSelect(fd, COMM_SELECT_READ, httpAccept, NULL, 0);
358 debug(1, 1, "Accepting HTTP connections on port %d, FD %d.\n",
359 (int) Config.Port.http[x], fd);
812ed90c 360 HttpSockets[NHttpSockets++] = fd;
090089c4 361 }
812ed90c 362 if (NHttpSockets < 1)
363 fatal("Cannot open HTTP Port");
b6f794d6 364 if (!httpd_accel_mode || Config.Accel.withProxy) {
7690e8eb 365 if ((port = Config.Port.icp) > (u_short) 0) {
328d1c43 366 enter_suid();
16b204c4 367 theInIcpConnection = comm_open(SOCK_DGRAM,
368 0,
b6f794d6 369 Config.Addrs.udp_incoming,
30a4f2a8 370 port,
16b204c4 371 COMM_NONBLOCKING,
30a4f2a8 372 "ICP Port");
328d1c43 373 leave_suid();
30a4f2a8 374 if (theInIcpConnection < 0)
375 fatal("Cannot open ICP Port");
376 fd_note(theInIcpConnection, "ICP socket");
b177367b 377 commSetSelect(theInIcpConnection,
090089c4 378 COMM_SELECT_READ,
379 icpHandleUdp,
b177367b 380 NULL, 0);
e90100aa 381 comm_join_mcast_groups(theInIcpConnection);
f990cccc 382 debug(1, 1, "Accepting ICP connections on port %d, FD %d.\n",
383 (int) port, theInIcpConnection);
30a4f2a8 384
429fdbec 385 if ((addr = Config.Addrs.udp_outgoing).s_addr != no_addr.s_addr) {
328d1c43 386 enter_suid();
16b204c4 387 theOutIcpConnection = comm_open(SOCK_DGRAM,
cc6a9d2e 388 0,
30a4f2a8 389 addr,
390 port,
cc6a9d2e 391 COMM_NONBLOCKING,
30a4f2a8 392 "ICP Port");
9d90e665 393 leave_suid();
30a4f2a8 394 if (theOutIcpConnection < 0)
395 fatal("Cannot open Outgoing ICP Port");
b177367b 396 commSetSelect(theOutIcpConnection,
30a4f2a8 397 COMM_SELECT_READ,
398 icpHandleUdp,
b177367b 399 NULL, 0);
0d90407c 400 debug(1, 1, "Accepting ICP connections on port %d, FD %d.\n",
401 (int) port, theInIcpConnection);
30a4f2a8 402 fd_note(theOutIcpConnection, "Outgoing ICP socket");
403 fd_note(theInIcpConnection, "Incoming ICP socket");
404 } else {
405 theOutIcpConnection = theInIcpConnection;
406 }
651ca9d8 407 memset(&theOutICPAddr, '\0', sizeof(struct in_addr));
48f44632 408 len = sizeof(struct sockaddr_in);
651ca9d8 409 memset(&xaddr, '\0', len);
48f44632 410 x = getsockname(theOutIcpConnection,
651ca9d8 411 (struct sockaddr *) &xaddr, &len);
48f44632 412 if (x < 0)
881f7a6c 413 debug(50, 1, "theOutIcpConnection FD %d: getsockname: %s\n",
48f44632 414 theOutIcpConnection, xstrerror());
651ca9d8 415 else
416 theOutICPAddr = xaddr.sin_addr;
090089c4 417 }
418 }
9d4b2981 419 if (Config.vizHack.port) {
420 vizSock = comm_open(SOCK_DGRAM,
421 0,
422 any_addr,
423 0,
424 COMM_NONBLOCKING,
425 "VizHack Port");
426 if (vizSock < 0)
427 fatal("Could not open Viz Socket");
428#if defined(IP_ADD_MEMBERSHIP) && defined(IP_MULTICAST_TTL)
429 if (Config.vizHack.addr.s_addr > inet_addr("224.0.0.0")) {
430 struct ip_mreq mr;
5f72f9c4 431 char ttl = (char) Config.vizHack.mcast_ttl;
e924600d 432 memset(&mr, '\0', sizeof(struct ip_mreq));
9d4b2981 433 mr.imr_multiaddr.s_addr = Config.vizHack.addr.s_addr;
434 mr.imr_interface.s_addr = INADDR_ANY;
435 x = setsockopt(vizSock,
436 IPPROTO_IP,
437 IP_ADD_MEMBERSHIP,
438 (char *) &mr,
439 sizeof(struct ip_mreq));
440 if (x < 0)
5f72f9c4 441 debug(50, 1, "IP_ADD_MEMBERSHIP: FD %d, addr %s: %s\n",
9d4b2981 442 vizSock, inet_ntoa(Config.vizHack.addr), xstrerror());
5f72f9c4 443 x = setsockopt(vizSock,
444 IPPROTO_IP,
445 IP_MULTICAST_TTL,
446 &ttl,
447 sizeof(char));
448 if (x < 0)
449 debug(50, 1, "IP_MULTICAST_TTL: FD %d, TTL %d: %s\n",
9d4b2981 450 vizSock, Config.vizHack.mcast_ttl, xstrerror());
5f72f9c4 451 ttl = 0;
452 x = sizeof(char);
453 getsockopt(vizSock, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, &x);
a7011ca4 454 debug(1, 0, "vizSock on FD %d, ttl=%d\n", vizSock, (int) ttl);
9d4b2981 455 }
5f72f9c4 456#else
ca98227c 457 debug(1, 0, "vizSock: Could not join multicast group\n");
9d4b2981 458#endif
e924600d 459 memset(&Config.vizHack.S, '\0', sizeof(struct sockaddr_in));
9d4b2981 460 Config.vizHack.S.sin_family = AF_INET;
461 Config.vizHack.S.sin_addr = Config.vizHack.addr;
462 Config.vizHack.S.sin_port = htons(Config.vizHack.port);
463 }
5ecceaa4 464 clientdbInit();
16b204c4 465 icmpOpen();
67508012 466 netdbInit();
85034133 467 peerSelectInit();
5f3f8d0e 468}
469
b8d8561b 470void
0673c0ba 471serverConnectionsClose(void)
5f3f8d0e 472{
30a4f2a8 473 /* NOTE, this function will be called repeatedly while shutdown
474 * is pending */
812ed90c 475 int i;
0d90407c 476 for (i = 0; i < NHttpSockets; i++) {
477 if (HttpSockets[i] >= 0) {
812ed90c 478 debug(1, 1, "FD %d Closing HTTP connection\n", HttpSockets[i]);
479 comm_close(HttpSockets[i]);
812ed90c 480 HttpSockets[i] = -1;
481 }
090089c4 482 }
0d90407c 483 NHttpSockets = 0;
30a4f2a8 484 if (theInIcpConnection >= 0) {
485 /* NOTE, don't close outgoing ICP connection, we need to write to
486 * it during shutdown */
cadc2d55 487 debug(1, 1, "FD %d Closing ICP connection\n",
30a4f2a8 488 theInIcpConnection);
489 if (theInIcpConnection != theOutIcpConnection)
490 comm_close(theInIcpConnection);
b177367b 491 commSetSelect(theInIcpConnection,
5f3f8d0e 492 COMM_SELECT_READ,
493 NULL,
b177367b 494 NULL, 0);
30a4f2a8 495 if (theInIcpConnection != theOutIcpConnection)
b177367b 496 commSetSelect(theOutIcpConnection,
30a4f2a8 497 COMM_SELECT_READ,
498 NULL,
b177367b 499 NULL, 0);
30a4f2a8 500 theInIcpConnection = -1;
5f3f8d0e 501 }
c7433536 502 if (icmp_sock > -1)
f6610c4e 503 icmpClose();
5f3f8d0e 504}
505
b8d8561b 506static void
0673c0ba 507mainReinitialize(void)
5f3f8d0e 508{
ad6272a1 509 debug(1, 0, "Restarting Squid Cache (version %s)...\n", version_string);
0ffd22bc 510 /* Already called serverConnectionsClose and ipcacheShutdownServers() */
5f3f8d0e 511 neighborsDestroy();
00fac1f8 512 parseConfigFile(ConfigFile);
b6f794d6 513 _db_init(Config.Log.log, Config.debugOptions);
429fdbec 514 ipcache_restart(); /* clear stuck entries */
515 fqdncache_restart(); /* sigh, fqdncache too */
f88bb09c 516 dnsOpenServers();
d2af9477 517 redirectOpenServers();
0ffd22bc 518 serverConnectionsOpen();
234967c9 519 (void) ftpInitialize();
b6f794d6 520 if (theOutIcpConnection >= 0 && (!httpd_accel_mode || Config.Accel.withProxy))
30a4f2a8 521 neighbors_open(theOutIcpConnection);
0ffd22bc 522 debug(1, 0, "Ready to serve requests.\n");
5f3f8d0e 523}
524
b8d8561b 525static void
0673c0ba 526mainInitialize(void)
5f3f8d0e 527{
528 static int first_time = 1;
1758c627 529 if (opt_catch_signals) {
30a4f2a8 530 squid_signal(SIGSEGV, death, SA_NODEFER | SA_RESETHAND);
531 squid_signal(SIGBUS, death, SA_NODEFER | SA_RESETHAND);
44f99671 532 }
30a4f2a8 533 squid_signal(SIGPIPE, SIG_IGN, SA_RESTART);
534 squid_signal(SIGCHLD, sig_child, SA_NODEFER | SA_RESTART);
44f99671 535
00fac1f8 536 if (ConfigFile == NULL)
537 ConfigFile = xstrdup(DefaultConfigFile);
538 parseConfigFile(ConfigFile);
5f3f8d0e 539
30a4f2a8 540 leave_suid(); /* Run as non privilegied user */
d41a5e15 541 if (geteuid() == 0) {
0c77d853 542 debug(0, 0, "Squid is not safe to run as root! If you must\n");
543 debug(0, 0, "start Squid as root, then you must configure\n");
544 debug(0, 0, "it to run as a non-priveledged user with the\n");
545 debug(0, 0, "'cache_effective_user' option in the config file.\n");
d41a5e15 546 fatal("Don't run Squid as root, set 'cache_effective_user'!");
547 }
30a4f2a8 548 if (httpPortNumOverride != 1)
812ed90c 549 Config.Port.http[0] = (u_short) httpPortNumOverride;
30a4f2a8 550 if (icpPortNumOverride != 1)
f2052513 551 Config.Port.icp = (u_short) icpPortNumOverride;
30a4f2a8 552
b6f794d6 553 _db_init(Config.Log.log, Config.debugOptions);
5c5783a2 554 fd_open(fileno(debug_log), FD_LOG, Config.Log.log);
5f3f8d0e 555
30a4f2a8 556 debug(1, 0, "Starting Squid Cache version %s for %s...\n",
557 version_string,
558 CONFIG_HOST_TYPE);
e83892e9 559 debug(1, 1, "With %d file descriptors available\n", Squid_MaxFD);
5f3f8d0e 560
850c4ead 561 if (first_time) {
94e891ea 562 stmemInit(); /* stmem must go before at least redirect */
234967c9 563 disk_init(); /* disk_init must go before ipcache_init() */
850c4ead 564 }
5f3f8d0e 565 ipcache_init();
f88bb09c 566 fqdncache_init();
567 dnsOpenServers();
d2af9477 568 redirectOpenServers();
b012353a 569 useragentOpenLog();
234967c9 570 (void) ftpInitialize();
5f3f8d0e 571
30a4f2a8 572#if MALLOC_DBG
5f3f8d0e 573 malloc_debug(0, malloc_debug_level);
574#endif
575
a26bdc75 576 if (first_time) {
429fdbec 577 unlinkdInit();
5f3f8d0e 578 /* module initialization */
7111c86a 579 urlInitialize();
a528eb87 580 stat_init(&HTTPCacheInfo, Config.Log.access);
581 stat_init(&ICPCacheInfo, NULL);
5f3f8d0e 582 storeInit();
090089c4 583
b6f794d6 584 if (Config.effectiveUser) {
234967c9 585 /* we were probably started as root, so cd to a swap
586 * directory in case we dump core */
641941c0 587 if (chdir(storeSwapDir(0)) < 0) {
588 debug(50, 0, "%s: %s\n", storeSwapDir(0), xstrerror());
234967c9 589 fatal_dump("Cannot cd to swap directory?");
590 }
591 }
5f3f8d0e 592 /* after this point we want to see the mallinfo() output */
593 do_mallinfo = 1;
812ed90c 594 mimeInit(Config.mimeTablePathname);
5f3f8d0e 595 }
2285407f 596 serverConnectionsOpen();
b6f794d6 597 if (theOutIcpConnection >= 0 && (!httpd_accel_mode || Config.Accel.withProxy))
30a4f2a8 598 neighbors_open(theOutIcpConnection);
599
0a5b9b32 600 if (first_time)
601 writePidFile(); /* write PID file */
602
30a4f2a8 603 squid_signal(SIGUSR1, rotate_logs, SA_RESTART);
604 squid_signal(SIGUSR2, sigusr2_handle, SA_RESTART);
605 squid_signal(SIGHUP, reconfigure, SA_RESTART);
606 squid_signal(SIGTERM, shut_down, SA_NODEFER | SA_RESETHAND | SA_RESTART);
607 squid_signal(SIGINT, shut_down, SA_NODEFER | SA_RESETHAND | SA_RESTART);
5f3f8d0e 608 debug(1, 0, "Ready to serve requests.\n");
4d7add01 609
610 if (first_time) {
48f44632 611 eventAdd("storePurgeOld", storePurgeOld, NULL, Config.cleanRate);
612 eventAdd("storeMaintain", storeMaintainSwapSpace, NULL, 1);
613 eventAdd("storeDirClean", storeDirClean, NULL, 15);
28070024 614 if (Config.Announce.on)
e924600d 615 eventAdd("start_announce", start_announce, NULL, 3600);
582b6456 616 eventAdd("ipcache_purgelru", ipcache_purgelru, NULL, 10);
4d7add01 617 }
0a5b9b32 618 first_time = 0;
4d64d74a 619}
620
b8d8561b 621int
622main(int argc, char **argv)
4d64d74a 623{
624 int errcount = 0;
4d64d74a 625 int n; /* # of GC'd objects */
bc528c78 626 time_t loop_delay;
4d64d74a 627
e83892e9 628 if (FD_SETSIZE < Squid_MaxFD)
629 Squid_MaxFD = FD_SETSIZE;
630
7328e889 631 /* call mallopt() before anything else */
0b29fe44 632#if HAVE_MALLOPT
7328e889 633#ifdef M_GRAIN
634 /* Round up all sizes to a multiple of this */
635 mallopt(M_GRAIN, 16);
636#endif
637#ifdef M_MXFAST
638 /* biggest size that is considered a small block */
639 mallopt(M_MXFAST, 256);
640#endif
641#ifdef M_NBLKS
642 /* allocate this many small blocks at once */
643 mallopt(M_NLBLKS, 32);
644#endif
645#endif /* HAVE_MALLOPT */
646
30a4f2a8 647 memset(&local_addr, '\0', sizeof(struct in_addr));
429fdbec 648 safe_inet_addr(localhost, &local_addr);
28070024 649 memset(&any_addr, '\0', sizeof(struct in_addr));
429fdbec 650 safe_inet_addr("0.0.0.0", &any_addr);
28070024 651 memset(&no_addr, '\0', sizeof(struct in_addr));
429fdbec 652 safe_inet_addr("255.255.255.255", &no_addr);
30a4f2a8 653
cb6ae8c3 654#if HAVE_SRANDOM
655 srandom(time(NULL));
656#elif HAVE_SRAND48
940d6096 657 srand48(time(NULL));
cb6ae8c3 658#else
659 srand(time(NULL));
660#endif
661
4d64d74a 662 errorInitialize();
663
b8de7ebe 664 squid_starttime = getCurrentTime();
4d64d74a 665 failure_notify = fatal_dump;
666
667 mainParseOptions(argc, argv);
668
7690e8eb 669 /* send signal to running copy and exit */
670 if (opt_send_signal != -1) {
671 sendSignal();
672 /* NOTREACHED */
673 }
4d64d74a 674 setMaxFD();
675
1758c627 676 if (opt_catch_signals)
e83892e9 677 for (n = Squid_MaxFD; n > 2; n--)
30a4f2a8 678 close(n);
4d64d74a 679
4d64d74a 680 /*init comm module */
681 comm_init();
682
683 /* we have to init fdstat here. */
429fdbec 684 fdstat_init();
5c5783a2 685 fd_open(0, FD_LOG, "stdin");
686 fd_open(1, FD_LOG, "stdout");
687 fd_open(2, FD_LOG, "stderr");
4d64d74a 688
4d64d74a 689 /* preinit for debug module */
690 debug_log = stderr;
691 hash_init(0);
692
4d64d74a 693 mainInitialize();
694
090089c4 695 /* main loop */
983061ed 696 for (;;) {
30a4f2a8 697 if (rotate_pending) {
698 ftpServerClose();
e97f40f4 699 icmpClose();
30a4f2a8 700 _db_rotate_log(); /* cache.log */
5608850b 701 storeWriteCleanLogs();
30a4f2a8 702 storeRotateLog(); /* store.log */
30a4f2a8 703 stat_rotate_log(); /* access.log */
b012353a 704 useragentRotateLog(); /* useragent.log */
30a4f2a8 705 (void) ftpInitialize();
e97f40f4 706 icmpOpen();
30a4f2a8 707 rotate_pending = 0;
708 }
48f44632 709 eventRun();
710 if ((loop_delay = eventNextTime()) < 0)
4d7add01 711 loop_delay = 0;
812ed90c 712#if HAVE_POLL
713 switch (comm_poll(loop_delay)) {
714#else
9ca89c5a 715 switch (comm_select(loop_delay)) {
812ed90c 716#endif
090089c4 717 case COMM_OK:
234967c9 718 errcount = 0; /* reset if successful */
090089c4 719 break;
720 case COMM_ERROR:
721 errcount++;
234967c9 722 debug(1, 0, "Select loop Error. Retry %d\n", errcount);
090089c4 723 if (errcount == 10)
4d64d74a 724 fatal_dump("Select Loop failed!");
090089c4 725 break;
4d64d74a 726 case COMM_SHUTDOWN:
43030d00 727 /* delayed close so we can transmit while shutdown pending */
30a4f2a8 728 if (theOutIcpConnection > 0) {
729 comm_close(theOutIcpConnection);
730 theOutIcpConnection = -1;
43030d00 731 }
5f3f8d0e 732 if (shutdown_pending) {
733 normal_shutdown();
5f3f8d0e 734 } else if (reread_pending) {
0ffd22bc 735 mainReinitialize();
5f3f8d0e 736 reread_pending = 0; /* reset */
737 } else {
738 fatal_dump("MAIN: SHUTDOWN from comm_select, but nothing pending.");
739 }
0ffd22bc 740 break;
9ca89c5a 741 case COMM_TIMEOUT:
6c93e119 742 break;
090089c4 743 default:
6eb42cae 744 fatal_dump("MAIN: Internal error -- this should never happen.");
090089c4 745 break;
746 }
747 }
748 /* NOTREACHED */
983061ed 749 return 0;
090089c4 750}
7690e8eb 751
b8d8561b 752static void
0673c0ba 753sendSignal(void)
7690e8eb 754{
ff8d0ea6 755 pid_t pid;
fedac7e5 756 debug_log = stderr;
757 if (ConfigFile == NULL)
758 ConfigFile = xstrdup(DefaultConfigFile);
759 parseConfigFile(ConfigFile);
760 pid = readPidFile();
761 if (pid > 1) {
762 if (kill(pid, opt_send_signal) &&
763 /* ignore permissions if just running check */
764 !(opt_send_signal == 0 && errno == EPERM)) {
765 fprintf(stderr, "%s: ERROR: Could not send ", appname);
766 fprintf(stderr, "signal %d to process %d: %s\n",
41d30aa8 767 opt_send_signal, (int) pid, xstrerror());
7690e8eb 768 exit(1);
769 }
fedac7e5 770 } else {
771 fprintf(stderr, "%s: ERROR: No running copy\n", appname);
772 exit(1);
7690e8eb 773 }
fedac7e5 774 /* signal successfully sent */
775 exit(0);
776}