--- /dev/null
+.PHONY: all
+all: splitlist.so splitlist_commands.so
+
+splitlist.so: splitlist.o
+ ld -shared -Bdynamic -o $@ $^
+
+splitlist_commands.so: splitlist_commands.o
+ ld -shared -Bdynamic -o $@ $^
--- /dev/null
+/* shroud's splitlist */
+
+#include <string.h>
+#include "../irc/irc.h"
+#include "splitlist.h"
+#include "../core/hooks.h"
+
+array splitlist;
+
+void sphook_newserver(int hook, void *arg);
+void sphook_lostserver(int hook, void *arg);
+
+void _init(void) {
+ registerhook(HOOK_SERVER_NEWSERVER, &sphook_newserver);
+ registerhook(HOOK_SERVER_LOSTSERVER, &sphook_lostserver);
+
+ array_init(&splitlist, sizeof(splitserver));
+ array_setlim1(&splitlist, 5);
+ array_setlim2(&splitlist, 5);
+
+ sp_addsplit("default.split.quakenet.org", getnettime());
+}
+
+void _fini(void) {
+ int i;
+
+ deregisterhook(HOOK_SERVER_NEWSERVER, &sphook_newserver);
+ deregisterhook(HOOK_SERVER_LOSTSERVER, &sphook_lostserver);
+
+ for (i = 0; i < splitlist.cursi; i++) {
+ freesstring(((splitserver*)splitlist.content)[i].name);
+ }
+
+ array_free(&splitlist);
+}
+
+void sphook_newserver(int hook, void *arg) {
+ sp_deletesplit(serverlist[(int)arg].name->content);
+}
+
+void sphook_lostserver(int hook, void *arg) {
+ sp_addsplit(serverlist[(int)arg].name->content, getnettime());
+}
+
+int sp_countsplitservers(void) {
+ return splitlist.cursi;
+}
+
+int sp_issplitserver(const char *name) {
+ int i;
+
+ for (i = 0; i < splitlist.cursi; i++) {
+ if (strcmp(name, ((splitserver*)splitlist.content)[i].name->content) == 0)
+ return 1;
+ }
+
+ return 0;
+}
+
+void sp_deletesplit(const char *name) {
+ int i;
+
+ if (splitlist.cursi == 0)
+ return;
+
+ for (i = splitlist.cursi - 1; i >= 0; i--) {
+ if (strcmp(name, ((splitserver*)splitlist.content)[i].name->content) == 0) {
+ freesstring(((splitserver*)splitlist.content)[i].name);
+ array_delslot(&splitlist, i);
+ }
+ }
+}
+
+void sp_addsplit(const char *name, time_t ts) {
+ int slot;
+ splitserver *srv;
+
+ slot = array_getfreeslot(&splitlist);
+
+ srv = &(((splitserver*)splitlist.content)[slot]);
+
+ srv->name = getsstring(name, HOSTLEN);
+ srv->ts = ts;
+}
--- /dev/null
+#ifndef __SPLITLIST_H
+#define __SPLITLIST_H
+
+#include <time.h>
+#include "../server/server.h"
+#include "../lib/array.h"
+
+typedef struct {
+ sstring *name; /* name of the server */
+ time_t ts; /* timestamp of the split */
+} splitserver;
+
+extern array splitlist;
+
+int sp_countsplitservers(void);
+int sp_issplitserver(const char *name);
+void sp_deletesplit(const char *name);
+void sp_addsplit(const char *name, time_t ts);
+
+#endif /* __SPLITLIST_H */
--- /dev/null
+/* oper commands for the splitlist */
+
+#include "../lib/irc_string.h"
+#include "../irc/irc.h"
+#include "../splitlist/splitlist.h"
+#include "../control/control.h"
+
+int spcmd_splitlist(void *source, int cargc, char **cargv);
+int spcmd_splitdel(void *source, int cargc, char **cargv);
+
+void _init(void) {
+ registercontrolcmd("splitlist", 10, 0, &spcmd_splitlist);
+ registercontrolcmd("splitdel", 10, 1, &spcmd_splitdel);
+}
+
+void _fini(void) {
+ deregistercontrolcmd("splitlist", &spcmd_splitlist);
+ deregistercontrolcmd("splitdel", &spcmd_splitdel);
+}
+
+/* todo: add RELINK status */
+int spcmd_splitlist(void *source, int cargc, char **cargv) {
+ nick *np = (nick*)source;
+ int i;
+ splitserver srv;
+
+ if (splitlist.cursi == 0) {
+ controlreply(np, "There currently aren't any registered splits.");
+
+ return CMD_OK;
+ }
+
+ controlreply(np, "Server Status Split for");
+
+ for (i = 0; i < splitlist.cursi; i++) {
+ srv = ((splitserver*)splitlist.content)[i];
+
+ controlreply(np, "%s M.I.A. %s", srv.name->content, longtoduration(getnettime() - srv.ts, 1));
+ }
+
+ controlreply(np, "--- End of splitlist");
+
+ return CMD_OK;
+}
+
+int spcmd_splitdel(void *source, int cargc, char **cargv) {
+ nick *np = (nick*)source;
+ int i, count;
+ splitserver srv;
+
+ if (cargc < 1) {
+ controlreply(np, "Syntax: splitdel <pattern>");
+
+ return CMD_ERROR;
+ }
+
+ count = 0;
+
+ for (i = splitlist.cursi - 1; i >= 0; i--) {
+ srv = ((splitserver*)splitlist.content)[i];
+
+ if (match2strings(cargv[0], srv.name->content)) {
+ sp_deletesplit(srv.name->content); /* inefficient .. but it doesn't matter */
+ count++;
+ }
+ }
+
+ controlreply(np, "%d %s deleted.", count, count != 1 ? "splits" : "split");
+
+ return CMD_OK;
+}