Enhance config file format.
[inoclam.git] / src / inoclam.cxx
blob115b978dbcaafacbf2080ed30b9439085e169814
1 /*
2 * inoclam - Inotify+ClamAV virus scanner
3 * Copyright (C) 2007 Vermont Department of Taxes
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 * Contributor(s):
20 * Tom Cort <tom.cort@state.vt.us>
21 * Matt Gagne <matt.gagne@state.vt.us>
24 #include <list>
25 #include <iterator>
26 #include <errno.h>
27 #include <getopt.h>
28 #include <iostream>
29 #include <libdaemon/dlog.h>
30 #include <libdaemon/dpid.h>
31 #include <signal.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <fcntl.h>
38 #include "config.hxx"
39 #include "clam.hxx"
40 #include "inoclam.hxx"
41 #include "inotify.hxx"
42 #include "monitor.hxx"
43 #include "signal.hxx"
44 #include "smtp.hxx"
46 /**
47 * Determines if gatewayavd should run in the background (daemonized) or
48 * not. If daemonize is 1, then gatewayavd should run in the background.
50 int daemonize;
52 /**
53 * Determines if our process killed a running inoclam process successfully.
55 int killed;
57 /**
58 * Displays some version and copyright information upon request (-v or --version).
60 void display_version()
62 daemon_log(LOG_INFO, "inoclam v%s (%s)", VERSION, CODENAME);
63 daemon_log(LOG_INFO, "Copyright (C) 2007 Vermont Department of Taxes");
64 daemon_log(LOG_INFO, "This is free software; see the source for copying conditions. There is NO");
65 daemon_log(LOG_INFO, "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.");
68 /**
69 * Displays some usage information, command line parameters and whatnot.
70 * @param program the name of the program.
72 void display_help(char *program)
74 daemon_log(LOG_INFO, "Usage: %s [options]", program);
75 daemon_log(LOG_INFO, "Options:");
76 daemon_log(LOG_INFO, " -h --help Show this help message");
77 daemon_log(LOG_INFO, " -v --version Show version information");
78 daemon_log(LOG_INFO, " -k --kill Kill the running instance");
79 daemon_log(LOG_INFO, " -f --foreground Run in the foreground");
82 /**
83 * A command line parser using getopts.
84 * @param argc The number of command line arguments coming in argv.
85 * @param argv The command line arguments.
86 * @return Returns 0 on success and non-zero when we want the program to terminate.
88 int parse_args(int argc, char **argv)
90 int option_index;
91 int done;
93 static struct option long_options[] = {
94 {"help", no_argument, 0, 'h'},
95 {"version", no_argument, 0, 'v'},
96 {"kill", no_argument, 0, 'k'},
97 {"foreground", no_argument, 0, 'f'},
98 {0, 0, 0, 0}
101 option_index = 0;
102 done = 0;
104 while (!done) {
105 int c;
106 int ret;
108 c = getopt_long(argc, argv, "hvkf", long_options, &option_index);
109 if (c < 0) {
110 break;
113 switch (c) {
114 case 'h':
115 display_help(argv[0]);
116 done = 1;
117 break;
118 case 'v':
119 display_version();
120 done = 1;
121 break;
122 case 'k':
123 ret = daemon_pid_file_kill_wait(SIGQUIT, 30);
124 if (ret < 0) {
125 daemon_log(LOG_ERR, "Daemon not killed: (%s)", strerror(errno));
126 } else {
127 killed = 1;
129 done = 1;
130 break;
131 case 'f':
132 daemonize = 0;
133 break;
134 default:
135 daemon_log(LOG_ERR, "Unsupported option");
136 done = 1;
137 break;
141 return done;
144 int main(int argc, char *argv[], char *envp[])
146 int fd;
147 int ret;
148 pid_t pid;
150 /* Default Values for Global Variables */
151 daemonize = 1;
152 killed = 0;
153 exit_now = 0;
155 /* Sanity Checks */
156 if (argc < 1 || !argv || !argv[0]) {
157 daemon_log(LOG_ERR, "(%u:%s) Cannot determine program name from argv[0]\n");
158 return 1;
161 daemon_pid_file_ident = daemon_log_ident = daemon_ident_from_argv0(argv[0]);
163 if (geteuid() != 0) {
164 daemon_log(LOG_ERR, "You need root privileges to run this application.");
165 return 1;
168 /* Command Line Arguements */
169 ret = parse_args(argc, argv);
170 if (ret) {
171 return (killed ? 0 : ret);
174 pid = daemon_pid_file_is_running();
175 if (pid > 0) {
176 daemon_log(LOG_ERR, "%s is already running (PID => %u)", argv[0], daemon_log_ident, pid);
177 daemon_log(LOG_INFO, "Use `%s -k` to kill the running instance", daemon_log_ident);
178 return 1;
181 /* Daemonize */
182 if (daemonize) {
183 /* Configure Logging */
184 daemon_log_use = DAEMON_LOG_SYSLOG;
186 umask(0);
188 pid = fork();
189 if (pid < 0) {
190 return 1;
191 } else if (pid > 0) {
192 return 0;
195 setsid();
197 pid = fork();
198 if (pid < 0) {
199 return 1;
200 } else if (pid > 0) {
201 return 0;
204 ret = chdir("/");
205 if (ret < 0) {
206 daemon_log(LOG_ERR, "Could not chdir() to '/': %s", strerror(errno));
207 return 1;
210 /* close open file descriptors */
211 for (fd = 0; fd < getdtablesize(); fd++) {
212 ret = close(fd);
213 if (ret == -1 && errno != EBADF) {
214 daemon_log(LOG_ERR, "Could not close fd #%d: %s", fd, strerror(errno));
215 return 1;
219 /* re-open stdin, stdout, stderr */
220 fd = open("/dev/null", O_RDONLY);
221 fd = open("/dev/null", O_WRONLY);
222 fd = open("/dev/null", O_WRONLY);
225 ret = daemon_pid_file_create();
226 if (ret < 0) {
227 daemon_log(LOG_ERR, "Could not create PID file: %s", strerror(errno));
228 return 1;
231 /* this must run before any threads are created */
232 monitor_init();
234 /* Configure */
235 std::list<config::config*> *conf;
236 conf = config_parse();
238 /* Install Signal Handlers */
239 install_signal_handlers();
241 /* Initialize Virus Detection Engine and Load Virus Definitions */
242 clam *clamav;
243 clamav = new clam();
245 std::list<config::config*>::iterator itr = conf->begin();
247 /* Begin Monitoring watch_dir for Viruses */
248 inotify_main(*itr, clamav);
250 /* Free resources used by libclamav */
251 delete clamav;
253 monitor_wait(); /* thread cleanup */
255 delete *itr;
256 delete conf;
257 daemon_pid_file_remove();
259 daemon_log(LOG_INFO, "Exiting...");
260 return 0;