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 version 2 as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 * Tom Cort <tom.cort@state.vt.us>
20 * Matt Gagne <matt.gagne@state.vt.us>
28 #include <libdaemon/dlog.h>
29 #include <libdaemon/dpid.h>
33 #include <sys/types.h>
39 #include "inoclam.hxx"
40 #include "inotify.hxx"
41 #include "monitor.hxx"
46 * Determines if gatewayavd should run in the background (daemonized) or
47 * not. If daemonize is 1, then gatewayavd should run in the background.
52 * Determines if our process killed a running inoclam process successfully.
57 * Displays some version and copyright information upon request (-v or --version).
59 void display_version()
61 daemon_log(LOG_INFO
, "inoclam v%s (%s)", VERSION
, CODENAME
);
62 daemon_log(LOG_INFO
, "Copyright (C) 2007 Vermont Department of Taxes");
63 daemon_log(LOG_INFO
, "This is free software; see the source for copying conditions. There is NO");
64 daemon_log(LOG_INFO
, "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.");
68 * Displays some usage information, command line parameters and whatnot.
69 * @param program the name of the program.
71 void display_help(char *program
)
73 daemon_log(LOG_INFO
, "Usage: %s [options]", program
);
74 daemon_log(LOG_INFO
, "Options:");
75 daemon_log(LOG_INFO
, " -c --config=[FILE] Specifiy an alternate config location");
76 daemon_log(LOG_INFO
, " -f --foreground Run in the foreground");
77 daemon_log(LOG_INFO
, " -h --help Show this help message");
78 daemon_log(LOG_INFO
, " -k --kill Kill the running instance");
79 daemon_log(LOG_INFO
, " -v --version Show version information");
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
)
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 {"config", required_argument
, 0, 'c'},
109 c
= getopt_long(argc
, argv
, "hvkfc:", long_options
, &option_index
);
120 configfile
= strdup(optarg
);
123 display_help(argv
[0]);
131 ret
= daemon_pid_file_kill_wait(SIGQUIT
, 30);
133 daemon_log(LOG_ERR
, "Daemon not killed: (%s)", strerror(errno
));
143 daemon_log(LOG_ERR
, "Unsupported option");
152 int main(int argc
, char *argv
[], char *envp
[])
157 pthread_t watch_thread
;
158 pthread_attr_t watch_thread_attr
;
160 /* Default Values for Global Variables */
164 configfile
= strdup(DEFAULT_CONFIGFILE
);
167 if (argc
< 1 || !argv
|| !argv
[0]) {
168 daemon_log(LOG_ERR
, "(%u:%s) Cannot determine program name from argv[0]\n");
172 daemon_pid_file_ident
= daemon_log_ident
= daemon_ident_from_argv0(argv
[0]);
174 if (geteuid() != 0) {
175 daemon_log(LOG_ERR
, "You need root privileges to run this application.");
179 /* Command Line Arguements */
180 ret
= parse_args(argc
, argv
);
182 return (killed
? 0 : ret
);
185 pid
= daemon_pid_file_is_running();
187 daemon_log(LOG_ERR
, "%s is already running (PID => %u)", argv
[0], daemon_log_ident
, pid
);
188 daemon_log(LOG_INFO
, "Use `%s -k` to kill the running instance", daemon_log_ident
);
194 /* Configure Logging */
195 daemon_log_use
= DAEMON_LOG_SYSLOG
;
202 } else if (pid
> 0) {
211 } else if (pid
> 0) {
217 daemon_log(LOG_ERR
, "Could not chdir() to '/': %s", strerror(errno
));
221 /* close open file descriptors */
222 for (fd
= 0; fd
< getdtablesize(); fd
++) {
224 if (ret
== -1 && errno
!= EBADF
) {
225 daemon_log(LOG_ERR
, "Could not close fd #%d: %s", fd
, strerror(errno
));
230 /* re-open stdin, stdout, stderr */
231 fd
= open("/dev/null", O_RDONLY
);
232 fd
= open("/dev/null", O_WRONLY
);
233 fd
= open("/dev/null", O_WRONLY
);
236 ret
= daemon_pid_file_create();
238 daemon_log(LOG_ERR
, "Could not create PID file: %s", strerror(errno
));
242 /* this must run before any threads are created */
246 std::list
< config::config
* >*conf
;
247 conf
= config_parse();
253 /* Install Signal Handlers */
254 install_signal_handlers();
256 /* Initialize Virus Detection Engine and Load Virus Definitions */
260 pthread_attr_init(&watch_thread_attr
);
261 pthread_attr_setdetachstate(&watch_thread_attr
, PTHREAD_CREATE_DETACHED
);
263 for (std::list
< config::config
* >::iterator itr
= conf
->begin(); itr
!= conf
->end(); ++itr
) {
265 inotify_main_args_t
*args
;
266 args
= (inotify_main_args_t
*) malloc(sizeof(inotify_main_args_t
));
268 daemon_log(LOG_ERR
, "MALLOC FAILED!");
272 args
->clamav
= clamav
;
275 ret
= pthread_create(&watch_thread
, &watch_thread_attr
, inotify_main
, (void *) args
);
278 daemon_log(LOG_ERR
, "Can't create watch thread: %s", strerror(errno
));
289 monitor_wait(); /* thread cleanup */
291 /* Free resources used by libclamav */
294 for (std::list
< config::config
* >::iterator itr
= conf
->begin(); itr
!= conf
->end(); ++itr
) {
299 daemon_pid_file_remove();
301 daemon_log(LOG_INFO
, "Exiting...");