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