/*
        IRC User count output for MRTG
        By: Sean West (chu@g33ks.net)

        Fairly simple program to grab the local/global user counts
        on servers specified in bot.conf in the same dir as the
        executable file. In the file, just put a server on its own
        line. Make sure you edit the #define SERVER below.. I think
        thats it ;] Good luck, and if you need help, email me!
*/

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdarg.h>
#include <time.h>
#include <signal.h>

#define SERVER		"irc2.rptn.net"
#define NICK		"usercount"
#define REALN		"counting users!"
#define CONFNAME	"usercount.conf"
#define TIMEOUT		10

#define MAXRECVLEN	2000

/* #define DEBUG */

struct servers {
	int users;
	char server[256];
};

int count=0,glob=0,globc=0,Socket;
struct servers servList[20];

int init_client() {
	struct sockaddr_in sin;
	struct hostent *hp;
	int sock;

	sin.sin_family = AF_INET;
	sin.sin_port = htons(6667);
	hp = gethostbyname(SERVER);
	if (!hp) {
		printf("Connect Error: Unknown host %s\n", SERVER);
		return(-1);
	}
	if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
		printf("Connect Error: Cannot create socket!\n");
		return(-1);
	}

	bcopy(hp->h_addr, &sin.sin_addr, hp->h_length);
	connect(sock, (struct sockaddr *) &sin, sizeof(sin));

	return(sock);
}

void sendtosock(int sock, char *format,...) {
	static char output[1024];
	static char input[1024];
	va_list args;
	va_start(args, format);
	vsprintf(input, format, args);
	va_end(args);
	snprintf(output, 1024, "%s\n", input);
	send(sock, output, strlen(output), 0);
#ifdef DEBUG  
	printf("< %s",output);
#endif
}

void parse(int s,char *raw) {
	char *tmp[7],msg[256];
	FILE *file;
	int i,ii;
#ifdef DEBUG
	printf("> %s\n",raw);
#endif
	tmp[0] = strtok(raw, " ");
	tmp[1] = strtok(NULL, " ");
	tmp[2] = strtok(NULL, " ");
	tmp[3] = strtok(NULL, " ");
	tmp[4] = strtok(NULL, " ");
	tmp[5] = strtok(NULL, " ");
	tmp[6] = strtok(NULL, " ");
	if (!strcmp(tmp[0],"PING"))
		sendtosock(s,"PONG %s",tmp[1]);

	switch(atoi(tmp[1])) {
		case 001:
			printf("Reading conf (%s)\n",CONFNAME);
			file = fopen(CONFNAME,"r");
			for (ii=0;!feof(file) && fgets(msg,256,file);ii++) {
				for (i=strlen(msg)-1;i>=0;i--)
				{
					if (msg[i] == ' ' || msg[i] == '\n')
						msg[i] = NULL;
					else break;
				}
				sendtosock(s,"USERS :%s",msg);
			}
			fclose(file);
			break;

		case 265:
			if (globc == 0) break;
			strcpy(servList[count].server,&tmp[0][1]);
			servList[count].users = atoi(tmp[6]);
			count++;
			break;

		case 266:
			if (glob < atoi(tmp[6])) glob = atoi(tmp[6]);
			globc=1;
			break;

		case 402:
			strcpy(servList[count].server,tmp[3]);
			servList[count].users = 0;
			count++;
			break;
	}
}
int ReadSocket(int TheSocket, char *Buffer)
{
	int c;
	int i;
	static char remainder[MAXRECVLEN+10] = "";
	char LineString[MAXRECVLEN+10];
	int rsize;
	char *newline;
	char *doneline;
	
	memset(Buffer, '\0', MAXRECVLEN+1);
	rsize = 0;
	if (*remainder) {
		rsize = strlen(remainder);
		memcpy(Buffer, remainder, rsize);
	}
	c = recv(TheSocket, &Buffer[rsize], MAXRECVLEN-rsize, 0);
	if (c <= 0) {
		remainder[0] = '\0';
		return -1;
	}
	newline = Buffer;
	c = c+rsize;
	Buffer[c] = '\0';
	for (i=0; i<c; i++) {
		if (Buffer[i] == '\n') {
			Buffer[i] = '\0';
			memcpy(LineString, newline, strlen(newline)+1);
			parse(TheSocket,LineString);
			doneline = newline;
			newline = &Buffer[i+1]; 
		}
		if (Buffer[i] == '\r')
			Buffer[i] = '\0';
	}
	if (*newline)
		strcpy(remainder, newline);
	else
		memset(remainder, '\0', MAXRECVLEN);
	return 0;
}

void sendquit() {
	sendtosock(Socket,"quit");
}
int main() {
	int sock,i;
	char path[257];
	time_t ts=time(NULL);
	FILE *file;
	char Buffer[MAXRECVLEN+10];

	if ((sock = init_client()) == -1)
		exit(-1);
	Socket = sock;
	sendtosock(sock,"USER %s 0 0 :%s",NICK,REALN);
	sendtosock(sock,"NICK %s",NICK);
	alarm(TIMEOUT);
	signal(SIGALRM, sendquit);
	while (ReadSocket(sock, Buffer) != -1)
		continue;
	for (i=0;i<count;i++) {
		sprintf(path,"%s",servList[i].server);
		file = fopen(path,"wt");
		fprintf(file,"%i\n",servList[i].users);
		fprintf(file,"%i\n",glob);
		fprintf(file,"0\n");
		fprintf(file,"0\n");
		fclose(file);
		printf("Wrote out %s (%i users)\n",servList[i].server,servList[i].users);
	}
	printf("Done!\n");
	return 1;
}
