X-Git-Url: https://jfr.im/git/irc/quakenet/newserv.git/blobdiff_plain/fc8419ff32b8224d6a1708f34964d8d8f3f9e41f..9172b03e94b4a23862c5ffeab84d2bcec001cb64:/fakeusers/fakeusers.c diff --git a/fakeusers/fakeusers.c b/fakeusers/fakeusers.c index 12918133..0e92560a 100644 --- a/fakeusers/fakeusers.c +++ b/fakeusers/fakeusers.c @@ -21,541 +21,290 @@ MODULE_VERSION(""); -/* #define SIT_CHANNEL "#qnet.fakeusers" */ #define KILL_WAIT 10 #define KILL_TIME 60 typedef struct fakeuser { - nick *user; - time_t lastkill; - struct fakeuser *next; -} fakeuser; - -typedef struct user_details { char nick[NICKLEN + 1]; char ident[USERLEN + 1]; char host[HOSTLEN + 1]; char realname[REALLEN + 1]; + nick *user; time_t lastkill; - struct user_details *next; - void *schedule; -} user_details; - -fakeuser *fakeuserlist = NULL; -user_details *killeduserlist = NULL; -int fakeusercount = 0; -int killedusercount = 0; - -void fakeuser_cleanup(); -int fakeuser_loaddb(); -void fakeusers_load(const DBAPIResult *res, void *arg); -void fakeuser_handler(nick *user, int command, void **params); -int fakeadd(void *sender, int cargc, char **cargv); -int fakelist(void *sender, int cargc, char **cargv); -int fakekill(void *sender, int cargc, char **cargv); -void reconnectfake(void *details); - -int db_loaded = 0; + struct fakeuser *next; +} fakeuser; + +static fakeuser *fakeuserlist; static DBAPIConn *nofudb; -void _init() { - if (!fakeuser_loaddb()) - { - Error("fakeuser", ERR_FATAL, "Cannot load database"); - return; - } - registercontrolhelpcmd("fakeuser", NO_OPER, 4, &fakeadd, "Usage: FAKEUSER nick \nCreates a fake user."); - registercontrolhelpcmd("fakelist", NO_OPER, 0, &fakelist, "Usage: FAKELIST\nLists all fake users."); - registercontrolhelpcmd("fakekill", NO_OPER, 2, &fakekill, "Usage: FAKEKILL nick \nRemoves a fake user"); -} +static void reconnectfakeuser(void *arg); -void _fini() { - fakeuser_cleanup(); - deregistercontrolcmd("fakeuser", &fakeadd); - deregistercontrolcmd("fakelist", &fakelist); - deregistercontrolcmd("fakekill", &fakekill); +static fakeuser *findfakeuserbynick(char *nick) { + fakeuser *fake; + + for (fake = fakeuserlist; fake; fake = fake->next) + if (!ircd_strcmp(nick, fake->nick)) + return fake; + + return NULL; } -void fakeuser_cleanup() -{ - fakeuser *fake; - user_details *killed; - void *next; - for (fake = fakeuserlist; fake; fake = next) - { +static void fake_free(fakeuser *fake) { + fakeuser **pnext; + + if (fake->user) deregisterlocaluser(fake->user, "Signing off"); - next = fake->next; - free(fake); - } - for (killed = killeduserlist; killed; killed = next) - { - deleteschedule(killed->schedule, &reconnectfake, killed); - next = killed->next; - free(killed); + + deleteschedule(NULL, &reconnectfakeuser, fake); + + for (pnext = &fakeuserlist; *pnext; pnext = &((*pnext)->next)) { + if (*pnext == fake) { + *pnext = fake->next; + break; + } } - fakeusercount = 0; - killedusercount = 0; - fakeuserlist = NULL; - killeduserlist = NULL; + + free(fake); } -int fakeuser_loaddb() -{ - if (!nofudb) { - nofudb = dbapi2open(DBAPI2_DEFAULT, "fakeusers"); - if(!nofudb) { - Error("fakeuser", ERR_STOP, "Could not connect to database."); - return 0; +static void fake_remove(fakeuser *fake) { + nofudb->squery(nofudb, "DELETE FROM ? WHERE nick = ?", "Ts", "fakeusers", fake->nick); + + fake_free(fake); +} + +static void fakeuser_handler(nick *user, int command, void **params) { + if (command == LU_KILLED) { + fakeuser *fake; + time_t timenow = time(NULL); + + fake = findfakeuserbynick(user->nick); + + if (!fake) { + controlwall(NO_OPER, NL_FAKEUSERS, "Error: A fakeuser was killed, but wasn't found in the list"); + Error("fakeuser", ERR_ERROR, "A fakeuser was killed, but wasn't found in the list"); + return; } - } - db_loaded = 1; + fake->user = NULL; - nofudb->createtable(nofudb, NULL, NULL, - "CREATE TABLE ? (" - "nick VARCHAR(?) NOT NULL," - "ident VARCHAR(?) NOT NULL," - "host VARCHAR(?) NOT NULL," - "realname VARCHAR(?) NOT NULL," - "PRIMARY KEY (nick))", "Tdddd", "fakeusers", NICKLEN, USERLEN, HOSTLEN, REALLEN); + if (timenow - fake->lastkill < KILL_TIME) { + controlwall(NO_OPER, NL_FAKEUSERS, "Fake user %s!%s@%s (%s) KILL'ed twice under in %d seconds. Removing.", + fake->nick, fake->ident, fake->host, fake->realname, KILL_TIME); + fake_remove(fake); + return; + } - nofudb->query(nofudb, fakeusers_load, NULL, - "SELECT nick, ident, host, realname FROM ?", "T", "fakeusers"); + fake->lastkill = timenow; - return 1; + scheduleoneshot(time(NULL) + KILL_WAIT, &reconnectfakeuser, fake); + } } -void fakeusers_load(const DBAPIResult *res, void *arg) { - user_details details; - - if(!res) +static void reconnectfakeuser(void *arg) { + fakeuser *fake = arg; + nick *user; + + if (fake->user) return; - if(!res->success) { - Error("fakeuser", ERR_ERROR, "Error loading fakeuser list."); - res->clear(res); + if ((user = getnickbynick(fake->nick)) && (IsOper(user) || IsService(user) || IsXOper(user))) { + fake_remove(fake); return; } - details.lastkill = 0; - details.schedule = NULL; - while(res->next(res)) { - strlcpy(details.nick, res->get(res, 0), NICKLEN + 1); - strlcpy(details.ident, res->get(res, 1), USERLEN + 1); - strlcpy(details.host, res->get(res, 2), HOSTLEN + 1); - strlcpy(details.realname, res->get(res, 3), REALLEN + 1); - reconnectfake(&details); - } - - res->clear(res); + fake->user = registerlocaluser(fake->nick, fake->ident, fake->host, fake->realname, + NULL, UMODE_INV | UMODE_DEAF, &fakeuser_handler); } -user_details *getdetails(nick *user) -{ - user_details *details; - details = malloc(sizeof(user_details)); - if (!details) - return NULL; - strlcpy(details->nick, user->nick, NICKLEN + 1); - strlcpy(details->ident, user->ident, USERLEN + 1); - strlcpy(details->host, user->host->name->content, HOSTLEN + 1); - strlcpy(details->realname, user->realname->name->content, REALLEN + 1); - details->schedule = NULL; - details->lastkill = 0; - return details; -} +static fakeuser *fake_add(const char *nick, const char *ident, const char *host, const char *realname) { + fakeuser *fake; -#define ERR_EXISTS 1 -#define ERR_MEM 2 -#define ERR_WONTKILL 3 -int err_code; + fake = malloc(sizeof(fakeuser)); -nick *register_fakeuser(user_details *details) -{ - nick *user; - if ((user = getnickbynick(details->nick)) && (IsOper(user) || IsService(user) || IsXOper(user))) { - err_code = ERR_WONTKILL; + if (!fake) return NULL; - } - err_code = ERR_MEM; - return registerlocaluser(details->nick, details->ident, details->host, details->realname, - NULL, UMODE_INV | UMODE_DEAF, &fakeuser_handler); -} + strlcpy(fake->nick, nick, NICKLEN + 1); + strlcpy(fake->ident, ident, USERLEN + 1); + strlcpy(fake->host, host, HOSTLEN + 1); + strlcpy(fake->realname, realname, REALLEN + 1); -fakeuser *ll_add(user_details *details) -// Adds to the (sorted) linked list -{ - fakeuser *fake, *newfake; - int cmp; - - if (fakeuserlist) - { - cmp = ircd_strcmp(details->nick, fakeuserlist->user->nick); - if (!cmp) - { - err_code = ERR_EXISTS; - return NULL; - } - } - else - cmp = -1; - if (cmp < 0) - { - newfake = malloc(sizeof(fakeuser)); - if (!newfake) - { - err_code = ERR_MEM; - return NULL; - } - newfake->user = register_fakeuser(details); - if (!newfake->user) - { - free(newfake); - return NULL; //errcode already set by register_fakeuser - } - newfake->lastkill = details->lastkill; - newfake->next = fakeuserlist; - fakeuserlist = newfake; - fakeusercount++; - return newfake; - } - for (fake = fakeuserlist; fake->next; fake = fake->next) - { - cmp = ircd_strcmp(details->nick, fake->next->user->nick); - if (!cmp) - { - err_code = ERR_EXISTS; - return NULL; - } - if (cmp < 0) - { - newfake = malloc(sizeof(fakeuser)); - if (!newfake) - { - err_code = ERR_MEM; - return NULL; - } - newfake->user = register_fakeuser(details); - if (!newfake->user) - { - free(newfake); - return NULL; //errcode already set by register_fakeuser - } - newfake->lastkill = details->lastkill; - newfake->next = fake->next; - fake->next = newfake; - fakeusercount++; - return newfake; - } - } - newfake = malloc(sizeof(fakeuser)); - if (!newfake) - { - err_code = ERR_MEM; - return NULL; - } - newfake->user = register_fakeuser(details); - if (!newfake->user) - { - free(newfake); - return NULL; //errcode already set by register_fakeuser - } - newfake->lastkill = details->lastkill; - newfake->next = NULL; - fake->next = newfake; - fakeusercount++; - return newfake; -} + fake->user = NULL; + fake->lastkill = 0; -void kll_add(user_details *details) -//Adds to the (sorted) linked list of killed users -{ - int cmp; - user_details *killed; + fake->next = fakeuserlist; + fakeuserlist = fake; - if (killeduserlist) - cmp = ircd_strcmp(details->nick, killeduserlist->nick); - else - cmp = -1; - if (cmp < 0) //Add to the start of the list - { - details->next = killeduserlist; - killeduserlist = details; - killedusercount++; - return; - } - for (killed = killeduserlist; killed->next; killed = killed->next) - { - cmp = ircd_strcmp(details->nick, killed->next->nick); - if (cmp < 0) - { - details->next = killed->next; - killed->next = details; - killedusercount++; - return; - } - } - details->next = NULL; - killed->next = details; - killedusercount++; - return; + scheduleoneshot(time(NULL) + 1, reconnectfakeuser, fake); + + return fake; } -fakeuser *ll_remove(char *nickname) -//Removes from the linked list -{ - fakeuser *fake, *rmfake; - int cmp; +static fakeuser *fake_create(const char *nick, const char *ident, const char *host, const char *realname) { + fakeuser *fake; + + fake = fake_add(nick, ident, host, realname); - if (!fakeuserlist) - return NULL; - cmp = ircd_strcmp(nickname, fakeuserlist->user->nick); - if (cmp < 0) + if (!fake) return NULL; - if (!cmp) - { - rmfake = fakeuserlist; - fakeuserlist = fakeuserlist->next; - fakeusercount--; - rmfake->next = NULL; - return rmfake; - } - for (fake = fakeuserlist; fake->next; fake = fake->next) - { - rmfake = fake->next; - cmp = ircd_strcmp(nickname, rmfake->user->nick); - if (cmp < 0) - return NULL; - if (!cmp) - { - fake->next = rmfake->next; - fakeusercount--; - rmfake->next = NULL; - return rmfake; - } - } - return NULL; + + nofudb->squery(nofudb, "INSERT INTO ? (nick, ident, host, realname) VALUES (?,?,?,?)", "Tssss", "fakeusers", + fake->nick, fake->ident, fake->host, fake->realname); + + return fake; } -user_details *kll_remove(char *nickname) //Removes from the killed user linked list -{ - user_details *details, *rmdetails; - int cmp; +static void fakeusers_load(const DBAPIResult *res, void *arg) { + if (!res) + return; - if (!killeduserlist) - return NULL; - cmp = ircd_strcmp(nickname, killeduserlist->nick); - if (cmp < 0) - return NULL; - if (!cmp) - { - rmdetails = killeduserlist; - killeduserlist = killeduserlist->next; - rmdetails->next = NULL; - killedusercount--; - return rmdetails; - } - for (details = killeduserlist; details->next; details = details->next) - { - rmdetails = details->next; - cmp = ircd_strcmp(nickname, rmdetails->nick); - if (cmp < 0) - return NULL; - if (!cmp) - { - details->next = rmdetails->next; - rmdetails->next = NULL; - killedusercount--; - return rmdetails; - } + if (!res->success) { + Error("fakeuser", ERR_ERROR, "Error loading fakeuser list."); + res->clear(res); + return; } - return NULL; + + while (res->next(res)) + fake_add(res->get(res, 0), res->get(res, 1), res->get(res, 2), res->get(res, 3)); + + res->clear(res); } -void fakeuser_handler(nick *user, int command, void **params) -{ - if (command == LU_KILLED) - { - user_details *details; - fakeuser *item; - time_t timenow = time(NULL); +static int fakeuser_loaddb() { + if (!nofudb) { + nofudb = dbapi2open(DBAPI2_DEFAULT, "fakeusers"); - details = getdetails(user); - item = ll_remove(details->nick); - if (!item) - { - controlwall(NO_OPER, NL_FAKEUSERS, "Error: A fakeuser was killed, but wasn't found in the list"); - Error("fakeuser", ERR_ERROR, "A fakeuser was killed, but wasn't found in the list"); - return; + if (!nofudb) { + Error("fakeuser", ERR_STOP, "Could not connect to database."); + return 0; } + } - details->lastkill = item->lastkill; - free(item); + nofudb->createtable(nofudb, NULL, NULL, + "CREATE TABLE ? (" + "nick VARCHAR(?) NOT NULL," + "ident VARCHAR(?) NOT NULL," + "host VARCHAR(?) NOT NULL," + "realname VARCHAR(?) NOT NULL," + "PRIMARY KEY (nick))", "Tdddd", "fakeusers", NICKLEN, USERLEN, HOSTLEN, REALLEN); - if (timenow - details->lastkill < KILL_TIME) { - controlwall(NO_OPER, NL_FAKEUSERS, "Fake user %s!%s@%s (%s) KILL'ed twice under in %d seconds. Removing.", details->nick, details->ident, details->host, details->realname, KILL_TIME); - nofudb->squery(nofudb, "DELETE FROM ? WHERE nick = ?", "Ts", "fakeusers", details->nick); - return; - } - details->lastkill = timenow; + nofudb->query(nofudb, fakeusers_load, NULL, + "SELECT nick, ident, host, realname FROM ?", "T", "fakeusers"); - details->schedule = scheduleoneshot(time(NULL) + KILL_WAIT, &reconnectfake, details); - if (!details->schedule) - { - Error("fakeuser", ERR_ERROR, "Couldn't reschedule fakeuser for reconnect"); - free(details); - return; - } - kll_add(details); - } + return 1; } -//Usage: FAKEUSER nick -int fakeadd(void *sender, int cargc, char **cargv) -{ - user_details details, *killed; - nick *newnick; - fakeuser *newfake; +static int fakeadd(void *source, int cargc, char **cargv) { + nick *sender = source; + fakeuser *fake; + char *nick, *ident, *realname; + char host[HOSTLEN + 1]; if (cargc == 0) return CMD_USAGE; - strlcpy(details.nick, cargv[0], NICKLEN + 1); - if (cargc < 4) - strlcpy(details.realname, cargv[0], REALLEN + 1); - else - strlcpy(details.realname, cargv[3], REALLEN + 1); - if (cargc < 3) - { - strlcpy(details.host, cargv[0], NICKLEN + 1); - strlcat(details.host, ".fakeusers.quakenet.org", HOSTLEN + 1); + + fake = findfakeuserbynick(cargv[0]); + + if (fake) { + controlreply(sender, "Fake User with nick %s already found", cargv[0]); + return CMD_ERROR; } + + nick = cargv[0]; + + if (cargc < 4) + realname = cargv[0]; else - strlcpy(details.host, cargv[2], HOSTLEN + 1); + realname = cargv[3]; + + if (cargc < 3) { + strlcpy(host, cargv[0], NICKLEN + 1); + strlcat(host, ".fakeusers.quakenet.org", HOSTLEN + 1); + } else + strlcpy(host, cargv[2], HOSTLEN + 1); + if (cargc < 2) - strlcpy(details.ident, cargv[0], USERLEN + 1); + ident = cargv[0]; else - strlcpy(details.ident, cargv[1], USERLEN + 1); - - details.lastkill = 0; - - newfake = ll_add(&details); - if (!newfake) - { - if (err_code == ERR_EXISTS) - controlreply(sender, "Error: fakeuser already exists"); - else if (err_code == ERR_MEM) - { - controlreply(sender, "Error: memory error!!"); - Error("fakeuser", ERR_STOP, "malloc error"); - } - else if (err_code == ERR_WONTKILL) - controlreply(sender, "Nick already exists and I won't kill it"); - else - { - controlreply(sender, "Unknown error when adding fakeuser"); - Error("fakeuser", ERR_ERROR, "Unknown error when adding fakeuser"); - } + ident = cargv[1]; + + fake = fake_create(nick, ident, host, realname); + + if (!fake) return CMD_ERROR; - } - newnick = newfake->user; - if ((killed = kll_remove(newnick->nick))) //Is this nickname scheduled to reconnect? - { - deleteschedule(killed->schedule, &reconnectfake, killed); - free(killed); - nofudb->squery(nofudb, "UPDATE ? SET ident=?, host=?, realname=? WHERE nick = ?", "Tssss", "fakeusers", newnick->ident, newnick->host->name->content, newnick->realname->name->content, newnick->nick); - } - else - nofudb->squery(nofudb, "INSERT INTO ? (nick, ident, host, realname) VALUES (?,?,?,?)", "Tssss", "fakeusers", newnick->nick, newnick->ident, newnick->host->name->content, newnick->realname->name->content); - controlreply(sender, "Added fake user %s", newnick->nick); - controlwall(NO_OPER, NL_FAKEUSERS, "Fake user %s!%s@%s (%s) added by %s/%s", newnick->nick, newnick->ident, - newnick->host->name->content, newnick->realname->name->content, ((nick*)sender)->nick, ((nick*)sender)->authname); -#ifdef SIT_CHANNEL - { - channel *sitchannel; - if (!(sitchannel = findchannel(SIT_CHANNEL))) - sitchannel = createchannel(SIT_CHANNEL); - localjoinchannel(newnick, sitchannel); - } -#endif + + controlreply(sender, "Added fake user %s", fake->nick); + controlwall(NO_OPER, NL_FAKEUSERS, "%s added fake user: %s!%s@%s (%s)", controlid(sender), + fake->nick, fake->ident, fake->host, fake->realname); + + scheduleoneshot(time(NULL) + 1, &reconnectfakeuser, fake); + return CMD_OK; } -//Usage: FAKELIST -int fakelist(void *sender, int cargc, char **cargv) -{ +static int fakelist(void *sender, int cargc, char **cargv) { fakeuser *fake; - if (fakeusercount == 1) - controlreply(sender, "1 fakeuser is currently connected"); - else - controlreply(sender, "%d fakeusers are currently connected", fakeusercount); - for(fake = fakeuserlist; fake; fake = fake->next) - controlreply(sender, "%s!%s@%s (%s)", fake->user->nick, fake->user->ident, - fake->user->host->name->content, fake->user->realname->name->content); - if (killeduserlist) - { - user_details *k_fake; - if (fakeusercount == 1) - controlreply(sender, "1 fakeuser is currently waiting to reconnect"); + int fakeusercount = 0; + + for (fake = fakeuserlist; fake; fake = fake->next) { + if (!fake->user) + controlreply(sender, "%s!%s@%s (%s) - RECONNECTING", fake->nick, fake->ident, + fake->host, fake->realname); else - controlreply(sender, "%d fakeusers are currently waiting to reconnect", killedusercount); - for(k_fake = killeduserlist; k_fake; k_fake = k_fake->next) - controlreply(sender, "%s!%s@%s (%s)", k_fake->nick, k_fake->ident, k_fake->host, k_fake->realname); + controlreply(sender, "%s!%s@%s (%s)", fake->nick, fake->ident, + fake->host, fake->realname); + + fakeusercount++; } + + controlreply(sender, "%d fakeusers are currently connected", fakeusercount); + return CMD_OK; } -//Usage: FAKEKILL nick -int fakekill(void *sender, int cargc, char **cargv) -{ +static int fakekill(void *sender, int cargc, char **cargv) { fakeuser *fake; - user_details *k_fake; + if (cargc == 0) return CMD_USAGE; - if ((fake = ll_remove(cargv[0]))) - { - nofudb->squery(nofudb, "DELETE FROM ? WHERE nick = ?", "Ts", "fakeusers", fake->user->nick); - controlreply(sender, "Killed fake user %s", fake->user->nick); - controlwall(NO_OPER, NL_FAKEUSERS, "Fake user %s!%s@%s (%s) removed by %s/%s", fake->user->nick, fake->user->ident, - fake->user->host->name->content, fake->user->realname->name->content, ((nick*)sender)->nick, ((nick*)sender)->authname); - if (cargc > 1) - deregisterlocaluser(fake->user, cargv[1]); - else - deregisterlocaluser(fake->user, "Signing off"); - free(fake); - return CMD_OK; - } - if ((k_fake = kll_remove(cargv[0]))) //Fakeuser might be waiting to rejoin - { - nofudb->squery(nofudb, "DELETE FROM ? WHERE nick = ?", "Ts", "fakeusers", k_fake->nick); - controlreply(sender, "Killed fake user %s", k_fake->nick); - controlwall(NO_OPER, NL_FAKEUSERS, "Fake user %s!%s@%s (%s) removed by %s/%s", k_fake->nick, - k_fake->ident, k_fake->host, k_fake->realname, ((nick*)sender)->nick, ((nick*)sender)->authname); - free(k_fake); - return CMD_OK; + + fake = findfakeuserbynick(cargv[0]); + + if (!fake) { + controlreply(sender, "No Fake User with nick %s found", cargv[0]); + return CMD_ERROR; } - controlreply(sender, "No fakeuser with that nick exists"); - return CMD_ERROR; + + controlreply(sender, "Killed fake user %s", fake->nick); + controlwall(NO_OPER, NL_FAKEUSERS, "Fake user %s!%s@%s (%s) removed by %s/%s", fake->nick, fake->ident, + fake->host, fake->realname, ((nick *)sender)->nick, ((nick *)sender)->authname); + + fake_remove(fake); + + return CMD_OK; } -void reconnectfake(void *details) -//Called after the timeout period has expired since a fakeuser was killed, or on load -{ - fakeuser *fake; - user_details *u_details = details; - if (u_details->schedule) - kll_remove(u_details->nick); //Fakeuser was /kill'd - fake = ll_add(u_details); - if (u_details->schedule) - free(u_details); - if (!fake) +void _init() { + if (!fakeuser_loaddb()) { + Error("fakeuser", ERR_FATAL, "Cannot load database"); return; -#ifdef SIT_CHANNEL - { - channel *sitchannel; - if (!(sitchannel = findchannel(SIT_CHANNEL))) - sitchannel = createchannel(SIT_CHANNEL); - localjoinchannel(fake->user, sitchannel); } -#endif + + registercontrolhelpcmd("fakeuser", NO_OPER, 4, &fakeadd, "Usage: FAKEUSER nick \nCreates a fake user."); + registercontrolhelpcmd("fakelist", NO_OPER, 0, &fakelist, "Usage: FAKELIST\nLists all fake users."); + registercontrolhelpcmd("fakekill", NO_OPER, 2, &fakekill, "Usage: FAKEKILL nick\nRemoves a fake user"); +} + +void _fini() { + fakeuser *fake, *next; + + for (fake = fakeuserlist; fake; fake = next) { + next = fake->next; + fake_free(fake); + } + + deregistercontrolcmd("fakeuser", &fakeadd); + deregistercontrolcmd("fakelist", &fakelist); + deregistercontrolcmd("fakekill", &fakekill); }