Fruit's git repositories f00f / arglozer server.c
arglozer

Tree @arglozer (Download .tar.gz)

server.c @arglozerraw · history · blame

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>

#include <avl.h>
#include <postgresql/libpq-fe.h>

#include "f00f.h"

static void serv_SQUIT(int argc, byte **argv) {
	if(!strcasecmp(argv[2], f00fhost)) {
		fflush(stdout);
		xerror("Received SQUIT from %s", argv[0]);
	}
}

static void serv_PING(int argc, byte **argv) {
	if(argc < 2)
		return;
	servcmd("PONG :%s\n", argv[1]);
}

static void serv_NICK(int argc, byte **argv) {
	irc_nick_t *k;
	irc_user_t *u;
	avl_node_t *n;
	PGresult *res = NULL;
	pg_trans_t *pg = NULL;
	int fd;
	struct stat st;
	void *pw;
	splitbuf_t *q;

	if(service) {
		if(argc < 9)
			return;
		unc_lockwrite();
		k = newnick(argv[1], argv[8]);
		if(k) {
			if(!strcasecmp(argv[1], "Vinnie") && !strcasecmp(argv[6], "services.glines.org")) {
				if(f00f_debug > 2)
					eprintf("Vinnie detected! Subscribing...\n");
				fd = open(F00F_VINNIEPW, O_RDONLY);
				if(fd == -1) {
					perror("open("F00F_VINNIEPW")");
				} else {
					if(fstat(fd,&st) == -1) {
						perror("stat("F00F_VINNIEPW")");
					} else {
						pw = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
						if(pw == MAP_FAILED) {
							perror("mmap("F00F_VINNIEPW")");
						} else {
							q = qnew();
							qstrcat(q, "auth ");
							splitbuf(q, pw, st.st_size);
							munmap(pw, st.st_size);
							qstrcat(q, "\n");
							setuser(k, newuser(argv[1]));
							k->cred = AUTH_CERTAIN;

							for(n = nicks->head; n; n = n->next) {
								k = subnick(n);
								if(k->vinnie && k->vinniecred >= AUTH_CERTAIN)
									qprintf(q, "userauth %s %s\n", (byte *)k->nick.item, k->vinnie);
							}
							qstrcat(q, "auth_subscribe\n");
							sayq("Vinnie", q);
							qfree(q);
						}
					}
					close(fd);
				}
			} else {
				u = getuser(argv[1]);
				if(u) {
					setuser(k, u);
				} else {
					pg = pg_begin();
					if(pg) {
						res = pg_query(pg,
							"SELECT 1 FROM users WHERE lower(nick) = lower('%?')", argv[1]);
						if(res && PQntuples(res)) {
							setuser(k, newuser(argv[1]));
							pg_commit(pg);
						} else {
							pg_rollback(pg);
						}
					}
				}
			}
		}
		unc_unlockwrite();
	} else {
		if(argc < 2)
			return;
		if(f00fnick)
			free(f00fnick);
		f00fnick = xstrdup(argv[1]);
	}
}

static commandtab_t const servercmds[] = {
	{"SQUIT", serv_SQUIT},
	{"NICK", serv_NICK},
	{"PING", serv_PING},
	{NULL, NULL}
};

void servercommand(int argc, byte **argv) {
	int i;

	if(argc < 1)
		return;

	for(i = 0; servercmds[i].cmd; i++)
		if(!strcasecmp(argv[0], servercmds[i].cmd))
			servercmds[i].proc(argc,argv);
}