]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - src/main.cc
SourceFormat Enforcement
[thirdparty/squid.git] / src / main.cc
index ba13a2eec38de70f0d0ff676b4b7d76d18a6a97a..84358522db401982b4fa39d9a750e40bbfdef520 100644 (file)
@@ -1,35 +1,13 @@
 /*
- * 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>
@@ -164,7 +142,7 @@ void WINAPI WIN32_svcHandler(DWORD);
 
 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;
@@ -207,7 +185,7 @@ class StoreRootEngine : public AsyncEngine
 {
 
 public:
-    int checkEvents(int timeout) {
+    int checkEvents(int) {
         Store::Root().callback();
         return EVENT_IDLE;
     };
@@ -229,7 +207,7 @@ private:
 };
 
 int
-SignalEngine::checkEvents(int timeout)
+SignalEngine::checkEvents(int)
 {
     PROF_start(SignalEngine_checkEvents);
 
@@ -279,16 +257,18 @@ static void
 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
@@ -307,7 +287,6 @@ usage(void)
             "       -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"
@@ -328,21 +307,30 @@ usage(void)
 /**
  * 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) {
 
@@ -423,7 +411,7 @@ mainParseOptions(int argc, char *argv[])
 
         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;
 
@@ -481,7 +469,7 @@ mainParseOptions(int argc, char *argv[])
 
             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;
@@ -508,10 +496,20 @@ mainParseOptions(int argc, char *argv[])
             /** \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
@@ -563,7 +561,7 @@ mainParseOptions(int argc, char *argv[])
             /** \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);
@@ -576,7 +574,7 @@ mainParseOptions(int argc, char *argv[])
 
             exit(0);
 
-            /* NOTREACHED */
+        /* NOTREACHED */
 
         case 'z':
             /** \par z
@@ -633,13 +631,12 @@ shut_down(int sig)
 {
     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) {
@@ -649,17 +646,15 @@ shut_down(int sig)
                    " 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);
 
@@ -723,7 +718,7 @@ serverConnectionsClose(void)
 #endif
     }
     if (IamWorkerProcess()) {
-        clientHttpConnectionsClose();
+        clientConnectionsClose();
         icpConnectionShutdown();
 #if USE_HTCP
         htcpSocketShutdown();
@@ -781,7 +776,7 @@ mainReconfigureFinish(void *)
     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)
@@ -810,10 +805,10 @@ mainReconfigureFinish(void *)
     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
@@ -886,7 +881,7 @@ mainReconfigureFinish(void *)
             eventDelete(start_announce, NULL);
     }
 
-    writePidFile();            /* write PID file */
+    writePidFile();     /* write PID file */
 
     reconfiguring = 0;
 }
@@ -901,10 +896,10 @@ mainRotate(void)
 #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
@@ -920,7 +915,7 @@ static void
 setEffectiveUser(void)
 {
     keepCapabilities();
-    leave_suid();              /* Run as non privilegied user */
+    leave_suid();       /* Run as non privilegied user */
 #if _SQUID_OS2_
 
     return;
@@ -1032,7 +1027,7 @@ mainInitialize(void)
 #endif
 
     if (!configured_once)
-        disk_init();           /* disk_init must go before ipcache_init() */
+        disk_init();        /* disk_init must go before ipcache_init() */
 
     ipcache_init();
 
@@ -1060,9 +1055,9 @@ mainInitialize(void)
 #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();
 
@@ -1138,7 +1133,7 @@ mainInitialize(void)
         no_suid();
 
     if (!configured_once)
-        writePidFile();                /* write PID file */
+        writePidFile();     /* write PID file */
 
 #if defined(_SQUID_LINUX_THREADS_)
 
@@ -1225,19 +1220,29 @@ int SquidMain(int argc, char **argv);
 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)
@@ -1371,7 +1376,7 @@ SquidMain(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();
@@ -1877,15 +1882,15 @@ SquidShutdown()
 
     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 */