freshclam/freshclam.c
e3aaff8e
 /*
c442ca9c
  *  Copyright (C) 2013-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
  *  Copyright (C) 2007-2013 Sourcefire, Inc.
  *  Copyright (C) 2002-2007 Tomasz Kojm <tkojm@clamav.net>
e3aaff8e
  *
  *  This program is free software; you can redistribute it and/or modify
bb34cb31
  *  it under the terms of the GNU General Public License version 2 as
  *  published by the Free Software Foundation.
e3aaff8e
  *
  *  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
48b7b4a7
  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  *  MA 02110-1301, USA.
e3aaff8e
  */
5ca6034b
 
6d6e8271
 #if HAVE_CONFIG_H
 #include "clamav-config.h"
 #endif
 
e3aaff8e
 #include <stdio.h>
 #include <stdlib.h>
97eb9786
 #ifdef	HAVE_UNISTD_H
e3aaff8e
 #include <unistd.h>
97eb9786
 #endif
e3aaff8e
 #include <string.h>
dd95cc2d
 #include <errno.h>
5ca6034b
 #include <signal.h>
8000d078
 #include <time.h>
e3aaff8e
 #include <sys/types.h>
4cd80898
 #ifndef	_WIN32
5f0d9945
 #include <sys/wait.h>
97eb9786
 #endif
e3aaff8e
 #include <sys/stat.h>
 #include <fcntl.h>
081f6473
 #ifdef	HAVE_PWD_H
e3aaff8e
 #include <pwd.h>
081f6473
 #endif
 #ifdef HAVE_GRP_H
e3aaff8e
 #include <grp.h>
97eb9786
 #endif
e3aaff8e
 
afb48b28
 #if defined(USE_SYSLOG) && !defined(C_AIX)
fb787a06
 #include <syslog.h>
 #endif
 
cc71d7c2
 #include "target.h"
a889f40e
 #include "clamav.h"
b35baf68
 #include "freshclamcodes.h"
a889f40e
 
c57aae32
 #include "libclamav/others.h"
8bf6e781
 #include "libclamav/str.h"
c57aae32
 
3f7802c9
 #include "shared/optparser.h"
a889f40e
 #include "shared/output.h"
 #include "shared/misc.h"
 
5f0d9945
 #include "execute.h"
a889f40e
 #include "manager.h"
376307a0
 #include "mirman.h"
e3aaff8e
 
dd95cc2d
 static short terminate = 0;
5f0d9945
 extern int active_children;
dd95cc2d
 
b68375fd
 static short foreground = -1;
54bf9b46
 char updtmpdir[512], dbdir[512];
536cf542
 int sigchld_wait = 1;
7f659671
 const char *pidfile = NULL;
b7485a22
 char hostid[37];
0ae41a2d
 
b7485a22
 char *get_hostid(void *cbdata);
6df13d04
 int is_valid_hostid(void);
dbc6d4b2
 
6df88f29
 static void
 sighandler (int sig)
 {
dd95cc2d
 
6df88f29
     switch (sig)
     {
97eb9786
 #ifdef	SIGCHLD
6df88f29
     case SIGCHLD:
         if (sigchld_wait)
             waitpid (-1, NULL, WNOHANG);
         active_children--;
         break;
97eb9786
 #endif
5f0d9945
 
536cf542
 #ifdef SIGPIPE
6df88f29
     case SIGPIPE:
         /* no action, app will get EPIPE */
         break;
536cf542
 #endif
 
97eb9786
 #ifdef	SIGALRM
6df88f29
     case SIGALRM:
         terminate = -1;
         break;
97eb9786
 #endif
 #ifdef	SIGUSR1
6df88f29
     case SIGUSR1:
         terminate = -1;
         break;
97eb9786
 #endif
dd95cc2d
 
97eb9786
 #ifdef	SIGHUP
6df88f29
     case SIGHUP:
         terminate = -2;
         break;
97eb9786
 #endif
dd95cc2d
 
6df88f29
     default:
         if (*updtmpdir)
             cli_rmdirs (updtmpdir);
         if (pidfile)
             unlink (pidfile);
         logg ("Update process terminated\n");
b68375fd
         exit (0);
dd95cc2d
     }
e3eaadd0
 
dd95cc2d
     return;
 }
 
6df88f29
 static void
 writepid (const char *pidfile)
a889f40e
 {
6df88f29
     FILE *fd;
     int old_umask;
     old_umask = umask (0006);
     if ((fd = fopen (pidfile, "w")) == NULL)
     {
         logg ("!Can't save PID to file %s: %s\n", pidfile, strerror (errno));
     }
     else
     {
3a670267
         fprintf (fd, "%d\n", (int) getpid ());
6df88f29
         fclose (fd);
dd95cc2d
     }
6df88f29
     umask (old_umask);
dd95cc2d
 }
 
6df88f29
 static void
 help (void)
a889f40e
 {
     mprintf_stdout = 1;
 
e098cdc5
     mprintf("\n");
     mprintf("                      Clam AntiVirus: Database Updater %s\n", get_version());
964a1e73
     mprintf("           By The ClamAV Team: https://www.clamav.net/about.html#credits\n");
c442ca9c
     mprintf("           (C) 2019 Cisco Systems, Inc.\n");
e098cdc5
     mprintf("\n");
     mprintf("    freshclam [options]\n");
     mprintf("\n");
     mprintf("    --help               -h              Show this help\n");
     mprintf("    --version            -V              Print version number and exit\n");
     mprintf("    --verbose            -v              Be verbose\n");
     mprintf("    --debug                              Enable debug messages\n");
     mprintf("    --quiet                              Only output error messages\n");
     mprintf("    --no-warnings                        Don't print and log warnings\n");
     mprintf("    --stdout                             Write to stdout instead of stderr\n");
     mprintf("    --show-progress                      Show download progress percentage\n");
     mprintf("\n");
     mprintf("    --config-file=FILE                   Read configuration from FILE.\n");
     mprintf("    --log=FILE           -l FILE         Log into FILE\n");
be4bf7f4
 #ifndef _WIN32
e098cdc5
     mprintf("    --daemon             -d              Run in daemon mode\n");
     mprintf("    --pid=FILE           -p FILE         Save daemon's pid in FILE\n");
     mprintf("    --user=USER          -u USER         Run as USER\n");
be4bf7f4
 #endif
e098cdc5
     mprintf("    --no-dns                             Force old non-DNS verification method\n");
     mprintf("    --checks=#n          -c #n           Number of checks per day, 1 <= n <= 50\n");
     mprintf("    --datadir=DIRECTORY                  Download new databases into DIRECTORY\n");
a889f40e
 #ifdef BUILD_CLAMD
e098cdc5
     mprintf("    --daemon-notify[=/path/clamd.conf]   Send RELOAD command to clamd\n");
a889f40e
 #endif
e098cdc5
     mprintf("    --local-address=IP   -a IP           Bind to IP for HTTP downloads\n");
     mprintf("    --on-update-execute=COMMAND          Execute COMMAND after successful update\n");
     mprintf("    --on-error-execute=COMMAND           Execute COMMAND if errors occurred\n");
     mprintf("    --on-outdated-execute=COMMAND        Execute COMMAND when software is outdated\n");
     mprintf("    --list-mirrors                       Print mirrors from mirrors.dat\n");
     mprintf("    --update-db=DBNAME                   Only update database DBNAME\n");
6df88f29
     mprintf ("\n");
a889f40e
 }
 
6df88f29
 static int
 download (const struct optstruct *opts, const char *cfgfile)
a889f40e
 {
dd8a6b10
     time_t currtime;
6df88f29
     int ret = 0, try = 1, maxattempts = 0;
     const struct optstruct *opt;
a889f40e
 
dd8a6b10
     time(&currtime);
     logg("ClamAV update process started at %s", ctime(&currtime));
     logg("*Using IPv6 aware code\n");
a889f40e
 
6df88f29
     maxattempts = optget (opts, "MaxAttempts")->numarg;
     logg ("*Max retries == %d\n", maxattempts);
a889f40e
 
6df88f29
     if (!(opt = optget (opts, "DatabaseMirror"))->enabled)
     {
         logg ("^You must specify at least one database mirror in %s\n",
               cfgfile);
b35baf68
         return FCE_CONFIG;
6df88f29
     }
     else
     {
         while (opt)
         {
             ret = downloadmanager (opts, opt->strarg, try);
f7c0a571
 #ifndef _WIN32
6df88f29
             alarm (0);
f7c0a571
 #endif
b35baf68
             if (ret == FCE_CONNECTION || ret == FCE_BADCVD
                 || ret == FCE_FAILEDGET || ret == FCE_MIRRORNOTSYNC)
6df88f29
             {
                 if (try < maxattempts)
                 {
                     logg ("Trying again in 5 secs...\n");
                     try++;
                     sleep (5);
                     continue;
                 }
                 else
                 {
                     logg ("Giving up on %s...\n", opt->strarg);
                     opt = (struct optstruct *) opt->nextarg;
                     if (!opt)
                     {
964a1e73
                         logg ("Update failed. Your network may be down or none of the mirrors listed in %s is working. Check https://www.clamav.net/documents/official-mirror-faq for possible reasons.\n", cfgfile);
6df88f29
                     }
dd8a6b10
                     try = 1;
6df88f29
                 }
 
             }
             else
             {
                 return ret;
             }
         }
a889f40e
     }
 
     return ret;
 }
 
6df88f29
 static void
 msg_callback (enum cl_msg severity, const char *fullmsg, const char *msg,
               void *ctx)
6bbbf1cc
 {
6df13d04
     UNUSEDPARAM(fullmsg);
     UNUSEDPARAM(ctx);
 
6df88f29
     switch (severity)
     {
     case CL_MSG_ERROR:
         logg ("^[LibClamAV] %s", msg);
         break;
     case CL_MSG_WARN:
         logg ("~[LibClamAV] %s", msg);
fc94f1e3
 	break;
6df88f29
     default:
         logg ("*[LibClamAV] %s", msg);
         break;
6bbbf1cc
     }
 }
 
6df88f29
 int
 main (int argc, char **argv)
e3aaff8e
 {
b35baf68
     int ret = FCE_CONNECTION, retcl;
6df88f29
     const char *cfgfile, *arg = NULL;
     char *pt;
     struct optstruct *opts;
     const struct optstruct *opt;
f7c0a571
 #ifndef	_WIN32
6df88f29
     struct sigaction sigact;
     struct sigaction oldact;
97eb9786
 #endif
4cd80898
 #ifdef HAVE_PWD_H
6df88f29
     const char *dbowner;
     struct passwd *user;
95d401c4
 #endif
6df88f29
     STATBUF statbuf;
     struct mirdat mdat;
b68375fd
 	int j;
3f7802c9
 
6df88f29
     if (check_flevel ())
b35baf68
         exit (FCE_INIT);
3f7802c9
 
6df88f29
     if ((retcl = cl_init (CL_INIT_DEFAULT)))
     {
         mprintf ("!Can't initialize libclamav: %s\n", cl_strerror (retcl));
b35baf68
         return FCE_INIT;
af38c8ae
     }
 
6df88f29
     if ((opts =
          optparse (NULL, argc, argv, 1, OPT_FRESHCLAM, 0, NULL)) == NULL)
     {
         mprintf ("!Can't parse command line options\n");
b35baf68
         return FCE_INIT;
7b8edc5c
     }
e3aaff8e
 
6df88f29
     if (optget (opts, "help")->enabled)
     {
         help ();
         optfree (opts);
dd8a6b10
         return FC_SUCCESS;
a889f40e
     }
 
b68375fd
     /* check foreground option from command line to override config file */
     for(j = 0; j < argc; j += 1)
     {
         if ((memcmp(argv[j], "--foreground", 12) == 0) || (memcmp(argv[j], "-F", 2) == 0))
         {
             /* found */
             break;
         }
     }
 
 	if (j < argc) {
 		if(optget(opts, "Foreground")->enabled) {
 			foreground = 1;
 		}
 		else {
 			foreground = 0;
 		}
 	}
 
95d401c4
     /* parse the config file */
6df88f29
     cfgfile = optget (opts, "config-file")->strarg;
     pt = strdup (cfgfile);
     if ((opts =
          optparse (cfgfile, 0, NULL, 1, OPT_FRESHCLAM, 0, opts)) == NULL)
     {
         fprintf (stderr, "ERROR: Can't open/parse the config file %s\n", pt);
         free (pt);
b35baf68
         return FCE_INIT;
95d401c4
     }
6df88f29
     free (pt);
95d401c4
 
6df88f29
     if (optget (opts, "version")->enabled)
     {
         print_version (optget (opts, "DatabaseDirectory")->strarg);
         optfree (opts);
dd8a6b10
         return FC_SUCCESS;
0aa3ba06
     }
 
6df88f29
     if (optget (opts, "HTTPProxyPassword")->enabled)
     {
d9b6b8c7
         if (CLAMSTAT (cfgfile, &statbuf) == -1)
6df88f29
         {
             logg ("^Can't stat %s (critical error)\n", cfgfile);
             optfree (opts);
b35baf68
             return FCE_CONFIG;
6df88f29
         }
97eb9786
 
be4bf7f4
 #ifndef _WIN32
6df88f29
         if (statbuf.
             st_mode & (S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH |
                        S_IXOTH))
         {
             logg ("^Insecure permissions (for HTTPProxyPassword): %s must have no more than 0700 permissions.\n", cfgfile);
             optfree (opts);
b35baf68
             return FCE_CONFIG;
6df88f29
         }
b782aece
 #endif
c2a3cdf9
     }
af22ece1
 
4cd80898
 #ifdef HAVE_PWD_H
c2a3cdf9
     /* freshclam shouldn't work with root privileges */
6df88f29
     dbowner = optget (opts, "DatabaseOwner")->strarg;
 
     if (!geteuid ())
     {
         if ((user = getpwnam (dbowner)) == NULL)
         {
             logg ("^Can't get information about user %s.\n", dbowner);
             optfree (opts);
b35baf68
             return FCE_USERINFO;
6df88f29
         }
e3aaff8e
 
fdeade2a
 #ifdef HAVE_INITGROUPS
2ea4230d
 	if (initgroups(dbowner, user->pw_gid)) {
 		logg ("^initgroups() failed.\n");
17d1e36d
                 optfree (opts);
2ea4230d
 		return FCE_USERORGROUP;
 	}
 #elif HAVE_SETGROUPS
 	if (setgroups(1, &user->pw_gid)) {
 		logg ("^setgroups() failed.\n");
17d1e36d
                 optfree (opts);
2ea4230d
 		return FCE_USERORGROUP;
 	}
a7d9bef2
 #endif
6df88f29
 
         if (setgid (user->pw_gid))
         {
             logg ("^setgid(%d) failed.\n", (int) user->pw_gid);
             optfree (opts);
b35baf68
             return FCE_USERORGROUP;
6df88f29
         }
 
         if (setuid (user->pw_uid))
         {
             logg ("^setuid(%d) failed.\n", (int) user->pw_uid);
             optfree (opts);
b35baf68
             return FCE_USERORGROUP;
6df88f29
         }
e3aaff8e
     }
f7c0a571
 #endif /* HAVE_PWD_H */
e3aaff8e
 
     /* initialize some important variables */
 
6df88f29
     if (optget (opts, "Debug")->enabled || optget (opts, "debug")->enabled)
         cl_debug ();
e4ae7726
 
6df88f29
     if (optget (opts, "verbose")->enabled)
         mprintf_verbose = 1;
e3aaff8e
 
6df88f29
     if (optget (opts, "quiet")->enabled)
         mprintf_quiet = 1;
e3aaff8e
 
6df88f29
     if (optget (opts, "no-warnings")->enabled)
     {
         mprintf_nowarn = 1;
         logg_nowarn = 1;
bcbe6ad7
     }
 
6df88f29
     if (optget (opts, "stdout")->enabled)
         mprintf_stdout = 1;
e3aaff8e
 
92e8a9ed
     if (optget (opts, "show-progress")->enabled)
         mprintf_progress = 1;
 
e3aaff8e
     /* initialize logger */
6df88f29
     logg_verbose = mprintf_verbose ? 1 : optget (opts, "LogVerbose")->enabled;
     logg_time = optget (opts, "LogTime")->enabled;
     logg_size = optget (opts, "LogFileMaxSize")->numarg;
42ccf9c2
     if (logg_size)
         logg_rotate = optget(opts, "LogRotate")->enabled;
6df88f29
 
     if ((opt = optget (opts, "UpdateLogFile"))->enabled)
     {
         logg_file = opt->strarg;
         if (logg ("#--------------------------------------\n"))
         {
             mprintf ("!Problem with internal logger (UpdateLogFile = %s).\n",
                      logg_file);
             optfree (opts);
b35baf68
             return FCE_LOGGING;
6df88f29
         }
     }
     else
         logg_file = NULL;
e3aaff8e
 
afb48b28
 #if defined(USE_SYSLOG) && !defined(C_AIX)
6df88f29
     if (optget (opts, "LogSyslog")->enabled)
     {
         int fac = LOG_LOCAL6;
 
         if ((opt = optget (opts, "LogFacility"))->enabled)
         {
             if ((fac = logg_facility (opt->strarg)) == -1)
             {
                 mprintf ("!LogFacility: %s: No such facility.\n",
                          opt->strarg);
                 optfree (opts);
b35baf68
                 return FCE_LOGGING;
6df88f29
             }
         }
 
         openlog ("freshclam", LOG_PID, fac);
         logg_syslog = 1;
58bcf502
     }
fb787a06
 #endif
 
6df88f29
     cl_set_clcb_msg (msg_callback);
95d401c4
     /* change the current working directory */
6df88f29
     if (chdir (optget (opts, "DatabaseDirectory")->strarg))
     {
         logg ("!Can't change dir to %s\n",
               optget (opts, "DatabaseDirectory")->strarg);
         optfree (opts);
b35baf68
         return FCE_DIRECTORY;
6df88f29
     }
     else
     {
         if (!getcwd (dbdir, sizeof (dbdir)))
         {
             logg ("!getcwd() failed\n");
             optfree (opts);
b35baf68
             return FCE_DIRECTORY;
6df88f29
         }
         logg ("*Current working dir is %s\n", dbdir);
92e22a60
     }
e3aaff8e
 
376307a0
 
6df88f29
     if (optget (opts, "list-mirrors")->enabled)
     {
dd8a6b10
         if (mirman_read("mirrors.dat", &mdat, 1) != FC_SUCCESS)
6df88f29
         {
             printf ("Can't read mirrors.dat\n");
             optfree (opts);
b35baf68
             return FCE_FILE;
6df88f29
         }
         mirman_list (&mdat);
         mirman_free (&mdat);
         optfree (opts);
dd8a6b10
         return FC_SUCCESS;
376307a0
     }
 
6df88f29
     if ((opt = optget (opts, "PrivateMirror"))->enabled)
     {
         struct optstruct *dbm, *opth;
 
         dbm = (struct optstruct *) optget (opts, "DatabaseMirror");
         dbm->active = dbm->enabled = 1;
         do
         {
             if (cli_strbcasestr (opt->strarg, ".clamav.net"))
             {
                 logg ("!PrivateMirror: *.clamav.net is not allowed in this mode\n");
                 optfree (opts);
b35baf68
                 return FCE_PRIVATEMIRROR;
6df88f29
             }
 
             if (dbm->strarg)
                 free (dbm->strarg);
             dbm->strarg = strdup (opt->strarg);
             if (!dbm->strarg)
             {
                 logg ("!strdup() failed\n");
                 optfree (opts);
b35baf68
                 return FCE_MEM;
6df88f29
             }
             if (!dbm->nextarg)
             {
                 dbm->nextarg =
                     (struct optstruct *) calloc (1,
                                                  sizeof (struct optstruct));
                 if (!dbm->nextarg)
                 {
                     logg ("!calloc() failed\n");
                     optfree (opts);
b35baf68
                     return FCE_MEM;
6df88f29
                 }
             }
             opth = dbm;
             dbm = dbm->nextarg;
         }
         while ((opt = opt->nextarg));
 
         opth->nextarg = NULL;
         while (dbm)
         {
             free (dbm->name);
             free (dbm->cmd);
             free (dbm->strarg);
             opth = dbm;
             dbm = dbm->nextarg;
             free (opth);
         }
 
         /* disable DNS db checks */
         opth = (struct optstruct *) optget (opts, "no-dns");
         opth->active = opth->enabled = 1;
 
         /* disable scripted updates */
         opth = (struct optstruct *) optget (opts, "ScriptedUpdates");
         opth->active = opth->enabled = 0;
cc590e07
     }
 
af38c8ae
     *updtmpdir = 0;
 
 #ifdef _WIN32
6df88f29
     signal (SIGINT, sighandler);
af38c8ae
 #else
6df88f29
     memset (&sigact, 0, sizeof (struct sigaction));
af38c8ae
     sigact.sa_handler = sighandler;
6df88f29
     sigaction (SIGINT, &sigact, NULL);
     sigaction (SIGPIPE, &sigact, NULL);
af38c8ae
 #endif
6df88f29
     if (optget (opts, "daemon")->enabled)
     {
         int bigsleep, checks;
f7c0a571
 #ifndef	_WIN32
6df88f29
         time_t now, wakeup;
e3aaff8e
 
6df88f29
         sigaction (SIGTERM, &sigact, NULL);
         sigaction (SIGHUP, &sigact, NULL);
         sigaction (SIGCHLD, &sigact, NULL);
97eb9786
 #endif
af22ece1
 
6df88f29
         checks = optget (opts, "Checks")->numarg;
e3aaff8e
 
6df88f29
         if (checks <= 0)
         {
             logg ("^Number of checks must be a positive integer.\n");
             optfree (opts);
b35baf68
             return FCE_CHECKS;
6df88f29
         }
e3aaff8e
 
6df88f29
         if (!optget (opts, "DNSDatabaseInfo")->enabled
             || optget (opts, "no-dns")->enabled)
         {
             if (checks > 50)
             {
                 logg ("^Number of checks must be between 1 and 50.\n");
                 optfree (opts);
b35baf68
                 return FCE_CHECKS;
6df88f29
             }
         }
3e92581e
 
6df88f29
         bigsleep = 24 * 3600 / checks;
5951212c
 
b2354dc1
 #ifndef _WIN32
b68375fd
         /* fork into background */
         if (foreground == -1)
         {
             if (optget(opts, "Foreground")->enabled)
             {
                 foreground = 1;
             }
             else
             {
                 foreground = 0;
             }
         }
         if(foreground == 0)
6df88f29
         {
             if (daemonize () == -1)
             {
                 logg ("!daemonize() failed\n");
                 optfree (opts);
b35baf68
                 return FCE_FAILEDUPDATE;
6df88f29
             }
             mprintf_disabled = 1;
0ae41a2d
         }
b500915b
 #endif
5951212c
 
6df88f29
         if ((opt = optget (opts, "PidFile"))->enabled)
         {
             pidfile = opt->strarg;
             writepid (pidfile);
         }
cc71d7c2
 
6df88f29
         active_children = 0;
5f0d9945
 
6df88f29
         logg ("#freshclam daemon %s (OS: " TARGET_OS_TYPE ", ARCH: "
               TARGET_ARCH_TYPE ", CPU: " TARGET_CPU_TYPE ")\n",
               get_version ());
e3aaff8e
 
6df88f29
         while (!terminate)
         {
             ret = download (opts, cfgfile);
af22ece1
 
ecd859c1
             if (ret > 1)
6df88f29
             {
                 if ((opt = optget (opts, "OnErrorExecute"))->enabled)
                     arg = opt->strarg;
af22ece1
 
6df88f29
                 if (arg)
                     execute ("OnErrorExecute", arg, opts);
770fb166
 
6df88f29
                 arg = NULL;
             }
e3aaff8e
 
6df88f29
             logg ("#--------------------------------------\n");
97eb9786
 #ifdef	SIGALRM
6df88f29
             sigaction (SIGALRM, &sigact, &oldact);
97eb9786
 #endif
 #ifdef	SIGUSR1
6df88f29
             sigaction (SIGUSR1, &sigact, &oldact);
97eb9786
 #endif
 
be4bf7f4
 #ifdef	_WIN32
6df88f29
             sleep (bigsleep);
 #else
             time (&wakeup);
             wakeup += bigsleep;
             alarm (bigsleep);
             do
             {
                 pause ();
                 time (&now);
             }
             while (!terminate && now < wakeup);
 
             if (terminate == -1)
             {
                 logg ("Received signal: wake up\n");
                 terminate = 0;
             }
             else if (terminate == -2)
             {
                 logg ("Received signal: re-opening log file\n");
                 terminate = 0;
                 logg_close ();
             }
97eb9786
 #endif
e3eaadd0
 
97eb9786
 #ifdef	SIGALRM
6df88f29
             sigaction (SIGALRM, &oldact, NULL);
97eb9786
 #endif
 #ifdef	SIGUSR1
6df88f29
             sigaction (SIGUSR1, &oldact, NULL);
 #endif
         }
 
     }
     else
     {
ecd859c1
         ret = download (opts, cfgfile);
64fd0bfc
     }
e3aaff8e
 
6df88f29
     if (ret > 1)
     {
         if ((opt = optget (opts, "OnErrorExecute"))->enabled)
             execute ("OnErrorExecute", opt->strarg, opts);
af22ece1
     }
770fb166
 
6df88f29
     if (pidfile)
     {
         unlink (pidfile);
dd95cc2d
     }
e3aaff8e
 
6df88f29
     optfree (opts);
97eb9786
 
f010300a
     cl_cleanup_crypto();
 
ef8f1754
     return ret > 1 ? ret : 0;
e3aaff8e
 }
dbc6d4b2
 
b7485a22
 int is_valid_hostid(void)
 {
     int count, i;
 
     if (strlen(hostid) != 36)
         return 0;
 
     count=0;
     for (i=0; i < 36; i++)
         if (hostid[i] == '-')
             count++;
 
     if (count != 4)
         return 0;
 
     if (hostid[8] != '-' || hostid[13] != '-' || hostid[18] != '-' || hostid[23] != '-')
         return 0;
 
     return 1;
 }
 
 char *get_hostid(void *cbdata)
 {
6df13d04
     UNUSEDPARAM(cbdata);
 
b7485a22
     if (!strcmp(hostid, "none"))
         return NULL;
 
     if (!is_valid_hostid())
         return strdup(STATS_ANON_UUID);
 
     logg("HostID is valid: %s\n", hostid);
 
     return strdup(hostid);
 }