Public feed #723859

Untitled

public text v1 · immutable
Raw Edit
·published 2007-10-03 02:36 UTC
rendered paste body
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <sys/types.h>
#include <fcntl.h>
#include <pthread.h>
#include <netinet/in.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <GeoIP.h>
#include <arpa/inet.h>

#include <string>
#include <iostream> 
#include <fstream> 
#include <list>
#include <vector>
#include <sstream>

#ifndef O_NONBLOCK
#define O_NONBLOCK O_NDELAY
#endif
using namespace std;

class logfile_class
{
private:
public:
int fd;
string name;
unsigned long ino;
};

logfile_class logfile;

GeoIP *gi;
int parse(string line);

int listenfd, len, status,dsize=0,connfd;;
fd_set rfd,c_rfd;


pthread_mutex_t mut,read_mut;
pthread_t serverside_id,readlog_id;

/********************************************************************************/

vector<string> split(const string& str, const string& delimiters)
{
	vector<string> tokens;
    	string::size_type lastpos = str.find_first_not_of(delimiters, 0);
    	string::size_type pos = str.find_first_of(delimiters, lastpos);

    	while (string::npos != pos || string::npos != lastpos)
    	{
			tokens.push_back(str.substr(lastpos, pos - lastpos));
			lastpos = str.find_first_not_of(delimiters, pos);
			pos = str.find_first_of(delimiters, lastpos);
    	}

	return tokens;
}
/********************************************************************************/

int recheck()
{
int fd=0;
struct stat stats;
if((fd=open(logfile.name.c_str(),O_RDONLY))==-1)  return 0; 
fstat(fd,&stats);
if(stats.st_ino!=logfile.ino) { close(fd); return 0; }
close(fd);
return 1;
}

int reopen()
{
struct stat stats;
close(logfile.fd);
if((logfile.fd=open(logfile.name.c_str(),O_RDONLY))==-1) { printf("Error Opening File.. %s\n",logfile.name.c_str());return 0; }
fstat(logfile.fd,&stats);
logfile.ino=stats.st_ino;
return 1;
}

void *read_log(void *parm)
{
int oldflags=0;
struct stat stats;
char tmpchar[1];

string buffer;

if((logfile.fd=open(logfile.name.c_str(),O_RDONLY))==-1) { printf("Error Opening File.. %s\n",logfile.name.c_str());exit(0); }
fstat(logfile.fd,&stats);
logfile.ino=stats.st_ino;

oldflags=fcntl(logfile.fd,F_GETFL,0);
if(oldflags<0) printf("Something Failed Trying to read fcntl\n");
if(fcntl(logfile.fd,F_SETFL,oldflags & ~O_NONBLOCK)==-1) { printf("Something Broke Setting Block Mode\n"); exit(0); }

//goto end of file.
lseek(logfile.fd,0,SEEK_END);

//pthread_join(serverside_id,NULL);
gi=GeoIP_open("/usr/share/GeoIP/GeoIP.dat",0);
printf("got here and reading..\n");

while(1)
	{
	if(read(logfile.fd,tmpchar,1))
	{	
		if(tmpchar[0]!='\n')	buffer+=tmpchar[0];
		else
			{	
				parse(buffer); buffer="";
			}
	}
	else
		{
		usleep(10000);
		if(!recheck()) { sleep(1); printf("Failed To Read From File..\n"); reopen(); }
		}
	}

pthread_exit(0);
}

/********************************************************************************/

int parse(string line)
{
int i=0;
string oBuf;
stringstream tmpoBuf;
//Rejected RBL
	if(strstr(line.c_str(),"NOQUEUE:"))
	{
		vector<string> result=split(line," ");		
		result=split(result[9],"[");
		result=split(result[1],"]");
		// stupid const pointer in GeoIP_country_name_by_addr
		// 45mins wondering wtf was wrong	
		if(GeoIP_country_name_by_addr(gi,result[0].c_str())==NULL)
			tmpoBuf << "SPAM:" << result[0] << ":" <<  "(null)\n";
		else
			tmpoBuf << "SPAM:" << result[0] << ":" << GeoIP_country_name_by_addr(gi,result[0].c_str()) << "\n";	
		oBuf=tmpoBuf.str();
		tmpoBuf.str("");	
		
		for(i=0;i<dsize;i++)
		if(i!=listenfd && FD_ISSET(i,&c_rfd))
		{
			if(send(i,oBuf.c_str(),strlen(oBuf.c_str()),MSG_NOSIGNAL)==-1)
			{
				close(i);
				FD_CLR(i,&rfd);	
			}		
		}
 	}

	
	if(strstr(line.c_str(),"client=") && !strstr(line.c_str(),"localhost"))
	{
		vector<string> result=split(line," ");	
		result=split(result[6],"[");
		result=split(result[1],"]");
		
		if(GeoIP_country_name_by_addr(gi,result[0].c_str())==NULL)
			tmpoBuf << "OK:" << result[0] << ":" <<  "(null)\n";		
		else
			tmpoBuf << "OK:" << result[0] << ":" << GeoIP_country_name_by_addr(gi,result[0].c_str()) << "\n";	
		oBuf=tmpoBuf.str();
		tmpoBuf.str("");	
		for(i=0;i<dsize;i++)
		if(i!=listenfd && FD_ISSET(i,&c_rfd))
		{
			if(send(i,oBuf.c_str(),strlen(oBuf.c_str()),MSG_NOSIGNAL)==-1)
			{
				close(i);
				FD_CLR(i,&rfd);
			}		
		}	
	}
return 1;
}


/********************************************************************************/

int main()
{
int i=0;
socklen_t len;
struct sockaddr_in servaddr, cliaddr;


logfile.name="/var/log/maillog";
listenfd = socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr("192.168.164.147");
//servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
servaddr.sin_port = htons(8898);

bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr));
listen(listenfd,3);
len = sizeof(cliaddr);
dsize=getdtablesize();
for(i=4;i<dsize;i++) if(i!=listenfd) close(i);

pthread_mutex_init(&read_mut,NULL);
pthread_mutex_init(&mut,NULL);
printf("Creating Thread..\n");
pthread_create(&readlog_id,NULL,read_log,NULL);

FD_ZERO(&rfd);
FD_SET(listenfd,&rfd);
printf("Going into loop\n");
	for(;;) 
	{
		c_rfd=rfd;
		select(dsize,&c_rfd,NULL,NULL,(struct timeval *)NULL);
		if(FD_ISSET(listenfd,&c_rfd))
		{
			connfd=accept(listenfd, (struct sockaddr *) &cliaddr, &len);
			//printf("** Connection Accepted From: [%s:%d]\n",inet_ntoa(cliaddr.sin_addr.s_addr), ntohs(cliaddr.sin_port));
			FD_SET(connfd,&rfd);
		}
	}
	
pthread_mutex_destroy(&mut);
pthread_mutex_destroy(&read_mut);
}