/* $Id: exact.c,v 1.18 2004/03/27 13:05:10 doug Exp $
*
* This file is part of EXACT.
*
* EXACT 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.
*
* EXACT 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 EXACT; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <regex.h>
#include <assert.h>
#include <unistd.h>
#include <signal.h>
#include <sys/stat.h>
#include <string.h>
#ifdef HAVE_GETOPT_H
#include <getopt.h>
#else
#include "getopt.h"
#endif
#include "tail.h"
#include "logger.h"
#include "match.h"
#include "conffile.h"
#include "auth.h"
#include "daemon.h"
#include "errno.h"
typedef struct {
int foreground;
int sleep;
int debug;
int preserve;
int tables;
} command_line;
command_line cmd;
int onepass() {
int i;
int start=0;
match_login *l;
tail_read();
for(i=0;i<tail_bufflen;i++) {
if(tail_buff[i]=='\n' || tail_buff[i]=='\0') {
tail_buff[i]='\0';
l=match_line(tail_buff+start);
if(l) auth_add(l->username, l->hostname);
start=i+1;
}
}
return 0;
}
void usage() {
fprintf(stderr,"Usage: exact [-h] [-d] [-f] [-p] [-c filename]\n");
fprintf(stderr," -h | --help show this usage information\n");
fprintf(stderr," -d | --debug more than you ever want to know\n");
fprintf(stderr," -f | --foreground don't background\n");
fprintf(stderr," -p | --preserve don't remove the relay file on exit\n");
fprintf(stderr," -c | --config configuration filename\n");
fprintf(stderr," -V | --version print the version of exact and exit\n");
fprintf(stderr," (default %s)\n", conffile_name());
fprintf(stderr,"see the manual page exact(8) for more information\n");
}
void version() {
fprintf(stderr, "Exact Version 1.41 (c) 2004, Doug Winter\n");
}
void cmdline(int argc, char *argv[]) {
int c;
cmd.foreground=0;
cmd.sleep=0;
cmd.debug=0;
cmd.preserve=0;
while(1) {
int option_index=0;
static struct option long_options[] = {
{"help", 0, NULL, 'h'},
{"foreground", 0, NULL, 'f'},
{"sleep", 0, NULL, 's'},
{"debug", 0, NULL, 'd'},
{"preserver", 0, NULL, 'p'},
{"config", 1, NULL, 'c'},
{"version", 0, NULL, 'V'},
{0,0,0,0}
};
c=getopt_long(argc,argv,"phsfdc:V",long_options, &option_index);
if(c==-1)
break;
switch(c) {
case 'h':
usage();
exit(0);
case 'V':
version();
exit(0);
case 'f':
cmd.foreground=1;
break;
case 's':
cmd.sleep=1;
break;
case 'd':
cmd.debug=1;
break;
case 'p':
cmd.preserve=1;
break;
case 'c':
conffile_setname(optarg);
break;
default:
fprintf(stderr, "Unknown argument: %c\n",c);
usage();
exit(40);
break;
}
}
}
void checkpid() {
FILE *f;
f=fopen(conffile_param("pidfile"),"r");
if(f) {
int opid=0;
fscanf(f,"%d",&opid);
fclose(f);
if(opid) {
int kr=kill(opid,0);
if(kr != -1) {
logger(LOG_ERR, "Exact is already running, with pid %d\n", opid);
exit(41);
}
}
}
logger(LOG_DEBUG, "exact is not already running\n");
}
void writepid() {
FILE *f=fopen(conffile_param("pidfile"),"w");
if(!f) {
logger(LOG_ERR, "Cannot write to pid file %s\n", conffile_param("pidfile"));
exit(42);
}
chmod(conffile_param("pidfile"),0640);
logger(LOG_DEBUG, "Writing pid to %s\n", conffile_param("pidfile"));
fprintf(f,"%d",(int)getpid());
fclose(f);
}
void exit_handler(int s) {
unlink(conffile_param("pidfile"));
auth_exit();
if(!cmd.preserve)
unlink(conffile_param("authfile"));
logger(LOG_ERR, "terminated\n");
exit(0);
}
int main(int argc, char *argv[]) {
int use_syslog=0;
cmdline(argc,argv);
logger_init(0,cmd.debug,NULL);
conffile_read();
conffile_check();
checkpid();
match_init();
daemonize(cmd.foreground, cmd.sleep);
auth_init();
if(!strcmp("syslog",conffile_param("logging")))
use_syslog=1;
else {
if(!strcmp("internal",conffile_param("logging")))
use_syslog=0;
else {
logger(LOG_ERR, "logging parameter is neither syslog nor internal\n");
exit(100);
}
}
if(cmd.foreground) {
logger_init(0,cmd.debug,NULL); // use stderr
} else {
// never debug using syslog, because you might
// get a loop
logger_init(use_syslog,!use_syslog && cmd.debug,conffile_param("logfile"));
logger(LOG_DEBUG, "Daemonized\n");
}
writepid();
signal(1,conffile_reload);
signal(10,auth_dump);
signal(15,exit_handler);
if(!tail_open()) {
logger(LOG_ERR,"open of %s failed. Quitting.\n", conffile_param("maillog"));
return 2;
}
logger(LOG_NOTICE, "running\n");
while(1) {
onepass();
}
assert(0);
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1