/*
- * DEBUG: section 01 Startup and Main Loop
- * AUTHOR: Harvest Derived
- *
- * SQUID Web Proxy Cache http://www.squid-cache.org/
- * ----------------------------------------------------------
- *
- * Squid is the result of efforts by numerous individuals from
- * the Internet community; see the CONTRIBUTORS file for full
- * details. Many organizations have provided support for Squid's
- * development; see the SPONSORS file for full details. Squid is
- * Copyrighted (C) 2001 by the Regents of the University of
- * California; see the COPYRIGHT file for full details. Squid
- * incorporates software developed and/or copyrighted by other
- * sources; see the CREDITS file for full details.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
+ * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
*
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
*/
+/* DEBUG: section 01 Startup and Main Loop */
+
#include "squid.h"
#include "AccessLogEntry.h"
#include "acl/Acl.h"
#include "ipc/Kids.h"
#include "ipc/Strand.h"
#include "ipcache.h"
-#include "Mem.h"
-#include "MemPool.h"
#include "mime.h"
#include "neighbors.h"
+#include "parser/Tokenizer.h"
#include "pconn.h"
#include "peer_sourcehash.h"
#include "peer_userhash.h"
#include "snmp_core.h"
#endif
+#include <cerrno>
+#if HAVE_GETOPT_H
+#include <getopt.h>
+#endif
#if HAVE_PATHS_H
#include <paths.h>
#endif
#if HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
-#if HAVE_ERRNO_H
-#include <errno.h>
-#endif
#if USE_WIN32_SERVICE
#include <process.h>
static int opt_signal_service = FALSE;
static char *opt_syslog_facility = NULL;
-static int icpPortNumOverride = 1; /* Want to detect "-u 0" */
+static int icpPortNumOverride = 1; /* Want to detect "-u 0" */
static int configured_once = 0;
#if MALLOC_DBG
static int malloc_debug_level = 0;
{
public:
- int checkEvents(int timeout) {
+ int checkEvents(int) {
Store::Root().callback();
return EVENT_IDLE;
};
};
int
-SignalEngine::checkEvents(int timeout)
+SignalEngine::checkEvents(int)
{
PROF_start(SignalEngine_checkEvents);
usage(void)
{
fprintf(stderr,
- "Usage: %s [-cdhvzCFNRVYX] [-n name] [-s | -l facility] [-f config-file] [-[au] port] [-k signal]"
+ "Usage: %s [-cdzCFNRVYX] [-n name] [-s | -l facility] [-f config-file] [-[au] port] [-k signal]"
#if USE_WIN32_SERVICE
"[-ir] [-O CommandLine]"
#endif
+ "\n"
+ " -h | --help Print help message.\n"
+ " -v | --version Print version details.\n"
"\n"
" -a port Specify HTTP port number (default: %d).\n"
" -d level Write debugging to stderr also.\n"
" -f file Use given config-file instead of\n"
" %s\n"
- " -h Print help message.\n"
#if USE_WIN32_SERVICE
" -i Installs as a Windows Service (see -n option).\n"
#endif
" -s | -l facility\n"
" Enable logging to syslog.\n"
" -u port Specify ICP port number (default: %d), disable with 0.\n"
- " -v Print version.\n"
" -z Create missing swap directories and then exit.\n"
" -C Do not catch fatal signals.\n"
" -D OBSOLETE. Scheduled for removal.\n"
/**
* Parse the parameters received via command line interface.
*
- \param argc Number of options received on command line
- \param argv List of parameters received on command line
+ * \param argc Number of options received on command line
+ * \param argv List of parameters received on command line
*/
static void
mainParseOptions(int argc, char *argv[])
{
- extern char *optarg;
- int c;
+ int optIndex = 0;
+ // short options
+ const char *shortOpStr =
#if USE_WIN32_SERVICE
- while ((c = getopt(argc, argv, "CDFNO:RSVYXa:d:f:hik:m::n:rsl:u:vz?")) != -1)
-#else
- while ((c = getopt(argc, argv, "CDFNRSYXa:d:f:hk:m::n:sl:u:vz?")) != -1)
+ "O:Vir"
#endif
- {
+ "CDFNRSYXa:d:f:hk:m::n:sl:u:vz?";
+
+ // long options
+ static struct option squidOptions[] = {
+ {"help", no_argument, 0, 'h'},
+ {"version", no_argument, 0, 'v'},
+ {0, 0, 0, 0}
+ };
+
+ int c;
+ while ((c = getopt_long(argc, argv, shortOpStr, squidOptions, &optIndex)) != -1) {
switch (c) {
case 'd':
/** \par d
- * Set global option Debug::log_stderr to the number given follwoign the option */
+ * Set global option Debug::log_stderr to the number given following the option */
Debug::log_stderr = atoi(optarg);
break;
else if (!strncmp(optarg, "check", strlen(optarg)))
/** \li On check send 0 / SIGNULL. */
- opt_send_signal = 0; /* SIGNULL */
+ opt_send_signal = 0; /* SIGNULL */
else if (!strncmp(optarg, "parse", strlen(optarg)))
/** \li On parse set global flag to re-parse the config file only. */
opt_parse_cfg_only = 1;
/** \par n
* Set global option opt_signal_service (to true).
* Stores the additional parameter given in global service_name */
- // XXX: verify that the new name has ONLY alphanumeric characters
- xfree(service_name);
- service_name = xstrdup(optarg);
- opt_signal_service = true;
+ if (optarg && *optarg != '\0') {
+ const SBuf t(optarg);
+ ::Parser::Tokenizer tok(t);
+ const CharacterSet chr = CharacterSet::ALPHA+CharacterSet::DIGIT;
+ if (!tok.prefix(service_name, chr))
+ fatalf("Expected alphanumeric service name for the -n option but got: %s", optarg);
+ if (!tok.atEnd())
+ fatalf("Garbage after alphanumeric service name in the -n option value: %s", optarg);
+ if (service_name.length() > 32)
+ fatalf("Service name (-n option) must be limited to 32 characters but got %u", service_name.length());
+ opt_signal_service = true;
+ } else {
+ fatal("A service name is required for the -n option");
+ }
break;
#if USE_WIN32_SERVICE
/** \par v
* Display squid version and build information. Then exit. */
printf("Squid Cache: Version %s\n" ,version_string);
- printf("Service Name: %s\n", service_name);
+ printf("Service Name: " SQUIDSBUFPH "\n", SQUIDSBUFPRINT(service_name));
if (strlen(SQUID_BUILD_INFO))
printf("%s\n",SQUID_BUILD_INFO);
printf( "configure options: %s\n", SQUID_CONFIGURE_OPTIONS);
exit(0);
- /* NOTREACHED */
+ /* NOTREACHED */
case 'z':
/** \par z
{
do_shutdown = sig == SIGINT ? -1 : 1;
ShutdownSignal = sig;
-#ifdef SIGTTIN
-
+#if defined(SIGTTIN)
if (SIGTTIN == sig)
shutdown_status = 1;
-
#endif
+#if !_SQUID_WINDOWS_
const pid_t ppid = getppid();
if (!IamMasterProcess() && ppid > 1) {
" pid " << ppid << ": " << xstrerror());
}
-#if !_SQUID_WINDOWS_
#if KILL_PARENT_OPT
-
if (!IamMasterProcess() && ppid > 1) {
debugs(1, DBG_IMPORTANT, "Killing master process, pid " << ppid);
if (kill(ppid, sig) < 0)
debugs(1, DBG_IMPORTANT, "kill " << ppid << ": " << xstrerror());
}
-
#endif /* KILL_PARENT_OPT */
+
#if SA_RESETHAND == 0
signal(SIGTERM, SIG_DFL);
#endif
}
if (IamWorkerProcess()) {
- clientHttpConnectionsClose();
+ clientConnectionsClose();
icpConnectionShutdown();
#if USE_HTCP
htcpSocketShutdown();
debugs(1, 3, "finishing reconfiguring");
errorClean();
- enter_suid(); /* root to read config file */
+ enter_suid(); /* root to read config file */
// we may have disabled the need for PURGE
if (Config2.onoff.enable_purge)
Mem::Report();
setEffectiveUser();
_db_init(Debug::cache_log, Debug::debugOptions);
- ipcache_restart(); /* clear stuck entries */
- fqdncache_restart(); /* sigh, fqdncache too */
+ ipcache_restart(); /* clear stuck entries */
+ fqdncache_restart(); /* sigh, fqdncache too */
parseEtcHosts();
- errorInitialize(); /* reload error pages */
+ errorInitialize(); /* reload error pages */
accessLogInit();
#if USE_LOADABLE_MODULES
eventDelete(start_announce, NULL);
}
- writePidFile(); /* write PID file */
+ writePidFile(); /* write PID file */
reconfiguring = 0;
}
#endif
externalAclShutdown();
- _db_rotate_log(); /* cache.log */
+ _db_rotate_log(); /* cache.log */
storeDirWriteCleanLogs(1);
- storeLogRotate(); /* store.log */
- accessLogRotate(); /* access.log */
+ storeLogRotate(); /* store.log */
+ accessLogRotate(); /* access.log */
#if ICAP_CLIENT
icapLogRotate(); /*icap.log*/
#endif
setEffectiveUser(void)
{
keepCapabilities();
- leave_suid(); /* Run as non privilegied user */
+ leave_suid(); /* Run as non privilegied user */
#if _SQUID_OS2_
return;
#endif
if (!configured_once)
- disk_init(); /* disk_init must go before ipcache_init() */
+ disk_init(); /* disk_init must go before ipcache_init() */
ipcache_init();
#endif
externalAclInit();
- httpHeaderInitModule(); /* must go before any header processing (e.g. the one in errorInitialize) */
+ httpHeaderInitModule(); /* must go before any header processing (e.g. the one in errorInitialize) */
- httpReplyInitModule(); /* must go before accepting replies */
+ httpReplyInitModule(); /* must go before accepting replies */
errorInitialize();
no_suid();
if (!configured_once)
- writePidFile(); /* write PID file */
+ writePidFile(); /* write PID file */
#if defined(_SQUID_LINUX_THREADS_)
static int SquidMainSafe(int argc, char **argv);
#if USE_WIN32_SERVICE
-/* When USE_WIN32_SERVICE is defined, the main function is placed in win32.cc */
+/* Entry point for Windows services */
extern "C" void WINAPI
SquidWinSvcMain(int argc, char **argv)
{
SquidMainSafe(argc, argv);
}
-#else
+#endif
+
int
main(int argc, char **argv)
{
+#if USE_WIN32_SERVICE
+ SetErrorMode(SEM_NOGPFAULTERRORBOX);
+ if ((argc == 2) && strstr(argv[1], _WIN_SQUID_SERVICE_OPTION))
+ return WIN32_StartService(argc, argv);
+ else {
+ WIN32_run_mode = _WIN_SQUID_RUN_MODE_INTERACTIVE;
+ opt_no_daemon = 1;
+ }
+#endif
+
return SquidMainSafe(argc, argv);
}
-#endif
static int
SquidMainSafe(int argc, char **argv)
Mem::Init();
- storeFsInit(); /* required for config parsing */
+ storeFsInit(); /* required for config parsing */
/* TODO: call the FS::Clean() in shutdown to do Fs cleanups */
Fs::Init();
Store::Root().sync(); /* Flush pending object writes/unlinks */
- unlinkdClose(); /* after sync/flush. NOP if !USE_UNLINKD */
+ unlinkdClose(); /* after sync/flush. NOP if !USE_UNLINKD */
storeDirWriteCleanLogs(0);
PrintRusage();
dumpMallocStats();
- Store::Root().sync(); /* Flush log writes */
+ Store::Root().sync(); /* Flush log writes */
storeLogClose();
accessLogClose();
- Store::Root().sync(); /* Flush log close */
+ Store::Root().sync(); /* Flush log close */
StoreFileSystem::FreeAllFs();
DiskIOModule::FreeAllModules();
#if LEAK_CHECK_MODE && 0 /* doesn't work at the moment */