00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #define MODULE_NAME "assoc"
00027 #define MAKING_ASSOC
00028
00029 #include "src/mod/module.h"
00030 #include "src/tandem.h"
00031 #include <stdlib.h>
00032 #include "assoc.h"
00033
00034 #undef global
00035 static Function *global = NULL;
00036
00037
00038 typedef struct assoc_t_ {
00039 char name[21];
00040 unsigned int channel;
00041 struct assoc_t_ *next;
00042 } assoc_t;
00043
00044
00045 static assoc_t *assoc;
00046
00047 static void botnet_send_assoc(int idx, int chan, char *nick, char *buf)
00048 {
00049 char x[1024];
00050 int idx2;
00051
00052 simple_sprintf(x, "assoc %D %s %s", chan, nick, buf);
00053 for (idx2 = 0; idx2 < dcc_total; idx2++)
00054 if ((dcc[idx2].type == &DCC_BOT) && (idx2 != idx) &&
00055 (b_numver(idx2) >= NEAT_BOTNET) &&
00056 !(bot_flags(dcc[idx2].user) & BOT_ISOLATE))
00057 botnet_send_zapf(idx2, botnetnick, dcc[idx2].nick, x);
00058 }
00059
00060 static int assoc_expmem()
00061 {
00062 assoc_t *a;
00063 int size = 0;
00064
00065 for (a = assoc; a; a = a->next)
00066 size += sizeof(assoc_t);
00067 return size;
00068 }
00069
00070 static void link_assoc(char *bot, char *via)
00071 {
00072 char x[1024];
00073
00074 if (!egg_strcasecmp(via, botnetnick)) {
00075 int idx = nextbot(bot);
00076 assoc_t *a;
00077
00078 if (!(bot_flags(dcc[idx].user) & BOT_ISOLATE)) {
00079 for (a = assoc; a && a->name[0]; a = a->next) {
00080 simple_sprintf(x, "assoc %D %s %s", (int) a->channel, botnetnick,
00081 a->name);
00082 botnet_send_zapf(idx, botnetnick, dcc[idx].nick, x);
00083 }
00084 }
00085 }
00086 }
00087
00088 static void kill_assoc(int chan)
00089 {
00090 assoc_t *a = assoc, *last = NULL;
00091
00092 while (a) {
00093 if (a->channel == chan) {
00094 if (last != NULL)
00095 last->next = a->next;
00096 else
00097 assoc = a->next;
00098 nfree(a);
00099 a = NULL;
00100 } else {
00101 last = a;
00102 a = a->next;
00103 }
00104 }
00105 }
00106
00107 static void kill_all_assoc()
00108 {
00109 assoc_t *a, *x;
00110
00111 for (a = assoc; a; a = x) {
00112 x = a->next;
00113 nfree(a);
00114 }
00115 assoc = NULL;
00116 }
00117
00118 static void add_assoc(char *name, int chan)
00119 {
00120 assoc_t *a, *b, *old = NULL;
00121
00122 for (a = assoc; a; a = a->next) {
00123 if (name[0] != 0 && !egg_strcasecmp(a->name, name)) {
00124 kill_assoc(a->channel);
00125 add_assoc(name, chan);
00126 return;
00127 }
00128 if (a->channel == chan) {
00129 strncpyz(a->name, name, sizeof a->name);
00130 return;
00131 }
00132 }
00133
00134 for (a = assoc; a; old = a, a = a->next) {
00135 if (a->channel > chan) {
00136 b = nmalloc(sizeof *b);
00137 b->next = a;
00138 b->channel = chan;
00139 strncpyz(b->name, name, sizeof b->name);
00140 if (old == NULL)
00141 assoc = b;
00142 else
00143 old->next = b;
00144 return;
00145 }
00146 }
00147
00148 b = nmalloc(sizeof *b);
00149 b->next = NULL;
00150 b->channel = chan;
00151 strncpyz(b->name, name, sizeof b->name);
00152 if (old == NULL)
00153 assoc = b;
00154 else
00155 old->next = b;
00156 }
00157
00158 static int get_assoc(char *name)
00159 {
00160 assoc_t *a;
00161
00162 for (a = assoc; a; a = a->next)
00163 if (!egg_strcasecmp(a->name, name))
00164 return a->channel;
00165 return -1;
00166 }
00167
00168 static char *get_assoc_name(int chan)
00169 {
00170 assoc_t *a;
00171
00172 for (a = assoc; a; a = a->next)
00173 if (a->channel == chan)
00174 return a->name;
00175 return NULL;
00176 }
00177
00178 static void dump_assoc(int idx)
00179 {
00180 assoc_t *a = assoc;
00181
00182 if (a == NULL) {
00183 dprintf(idx, "%s\n", ASSOC_NOCHNAMES);
00184 return;
00185 }
00186 dprintf(idx, " %s %s\n", ASSOC_CHAN, ASSOC_NAME);
00187 for (; a && a->name[0]; a = a->next)
00188 dprintf(idx, "%c%5d %s\n", (a->channel < GLOBAL_CHANS) ? ' ' : '*',
00189 a->channel % GLOBAL_CHANS, a->name);
00190 return;
00191 }
00192
00193 static int cmd_assoc(struct userrec *u, int idx, char *par)
00194 {
00195 char *num;
00196 int chan;
00197
00198 if (!par[0]) {
00199 putlog(LOG_CMDS, "*", "#%s# assoc", dcc[idx].nick);
00200 dump_assoc(idx);
00201 } else if (!u || !(u->flags & USER_BOTMAST))
00202 dprintf(idx, "%s", MISC_NOSUCHCMD);
00203 else {
00204 num = newsplit(&par);
00205 if (num[0] == '*') {
00206 chan = GLOBAL_CHANS + atoi(num + 1);
00207 if ((chan < GLOBAL_CHANS) || (chan > 199999)) {
00208 dprintf(idx, "%s\n", ASSOC_LCHAN_RANGE);
00209 return 0;
00210 }
00211 } else {
00212 chan = atoi(num);
00213 if (chan == 0) {
00214 dprintf(idx, "%s\n", ASSOC_PARTYLINE);
00215 return 0;
00216 } else if ((chan < 1) || (chan >= GLOBAL_CHANS)) {
00217 dprintf(idx, "%s\n", ASSOC_CHAN_RANGE);
00218 return 0;
00219 }
00220 }
00221 if (!par[0]) {
00222
00223 if (get_assoc_name(chan) == NULL) {
00224 dprintf(idx, ASSOC_NONAME_CHAN, (chan < GLOBAL_CHANS) ? "" : "*",
00225 chan % GLOBAL_CHANS);
00226 return 0;
00227 }
00228 kill_assoc(chan);
00229 putlog(LOG_CMDS, "*", "#%s# assoc %d", dcc[idx].nick, chan);
00230 dprintf(idx, ASSOC_REMNAME_CHAN, (chan < GLOBAL_CHANS) ? "" : "*",
00231 chan % GLOBAL_CHANS);
00232 chanout_but(-1, chan, ASSOC_REMOUT_CHAN, dcc[idx].nick);
00233 if (chan < GLOBAL_CHANS)
00234 botnet_send_assoc(-1, chan, dcc[idx].nick, "0");
00235 return 0;
00236 }
00237 if (strlen(par) > 20) {
00238 dprintf(idx, "%s\n", ASSOC_CHNAME_TOOLONG);
00239 return 0;
00240 }
00241 if ((par[0] >= '0') && (par[0] <= '9')) {
00242 dprintf(idx, "%s\n", ASSOC_CHNAME_FIRSTCHAR);
00243 return 0;
00244 }
00245 add_assoc(par, chan);
00246 putlog(LOG_CMDS, "*", "#%s# assoc %d %s", dcc[idx].nick, chan, par);
00247 dprintf(idx, ASSOC_NEWNAME_CHAN, (chan < GLOBAL_CHANS) ? "" : "*",
00248 chan % GLOBAL_CHANS, par);
00249 chanout_but(-1, chan, ASSOC_NEWOUT_CHAN, dcc[idx].nick, par);
00250 if (chan < GLOBAL_CHANS)
00251 botnet_send_assoc(-1, chan, dcc[idx].nick, par);
00252 }
00253 return 0;
00254 }
00255
00256 static int tcl_killassoc STDVAR
00257 {
00258 int chan;
00259
00260 BADARGS(2, 2, " chan");
00261
00262 if (argv[1][0] == '&')
00263 kill_all_assoc();
00264 else {
00265 chan = atoi(argv[1]);
00266 if ((chan < 1) || (chan > 199999)) {
00267 Tcl_AppendResult(irp, "invalid channel #", NULL);
00268 return TCL_ERROR;
00269 }
00270 kill_assoc(chan);
00271
00272 botnet_send_assoc(-1, chan, "*script*", "0");
00273 }
00274 return TCL_OK;
00275 }
00276
00277 static int tcl_assoc STDVAR
00278 {
00279 int chan;
00280 char name[21], *p;
00281
00282 BADARGS(2, 3, " chan ?name?");
00283
00284 if ((argc == 2) && ((argv[1][0] < '0') || (argv[1][0] > '9'))) {
00285 chan = get_assoc(argv[1]);
00286 if (chan == -1)
00287 Tcl_AppendResult(irp, "", NULL);
00288 else {
00289 simple_sprintf(name, "%d", chan);
00290 Tcl_AppendResult(irp, name, NULL);
00291 }
00292 return TCL_OK;
00293 }
00294 chan = atoi(argv[1]);
00295 if ((chan < 1) || (chan > 199999)) {
00296 Tcl_AppendResult(irp, "invalid channel #", NULL);
00297 return TCL_ERROR;
00298 }
00299 if (argc == 3) {
00300 strncpy(name, argv[2], 20);
00301 name[20] = 0;
00302 add_assoc(name, chan);
00303 botnet_send_assoc(-1, chan, "*script*", name);
00304 }
00305 p = get_assoc_name(chan);
00306 if (p == NULL)
00307 name[0] = 0;
00308 else
00309 strcpy(name, p);
00310 Tcl_AppendResult(irp, name, NULL);
00311 return TCL_OK;
00312 }
00313
00314 static void zapf_assoc(char *botnick, char *code, char *par)
00315 {
00316 int idx = nextbot(botnick);
00317 char *s, *s1, *nick;
00318 int linking = 0, chan;
00319
00320 if ((idx >= 0) && !(bot_flags(dcc[idx].user) & BOT_ISOLATE)) {
00321 if (!egg_strcasecmp(dcc[idx].nick, botnick))
00322 linking = b_status(idx) & STAT_LINKING;
00323 s = newsplit(&par);
00324 chan = base64_to_int(s);
00325 if ((chan > 0) || (chan < GLOBAL_CHANS)) {
00326 nick = newsplit(&par);
00327 s1 = get_assoc_name(chan);
00328 if (linking && ((s1 == NULL) || (s1[0] == 0) ||
00329 (((intptr_t) get_user(find_entry_type("BOTFL"),
00330 dcc[idx].user) & BOT_HUB)))) {
00331 add_assoc(par, chan);
00332 botnet_send_assoc(idx, chan, nick, par);
00333 chanout_but(-1, chan, ASSOC_CHNAME_NAMED, nick, par);
00334 } else if (par[0] == '0') {
00335 kill_assoc(chan);
00336 chanout_but(-1, chan, ASSOC_CHNAME_REM, botnick, nick);
00337 } else if (get_assoc(par) != chan) {
00338
00339 s1 = get_assoc_name(chan);
00340 add_assoc(par, chan);
00341 chanout_but(-1, chan, ASSOC_CHNAME_NAMED2, botnick, nick, par);
00342 }
00343 }
00344 }
00345 }
00346
00347 static void assoc_report(int idx, int details)
00348 {
00349 if (details) {
00350 assoc_t *a;
00351 int size = 0, count = 0;
00352
00353 for (a = assoc; a; a = a->next) {
00354 count++;
00355 size += sizeof(assoc_t);
00356 }
00357
00358 dprintf(idx, " %d current association%s\n", count,
00359 (count != 1) ? "s" : "");
00360 dprintf(idx, " Using %d byte%s of memory\n", size,
00361 (size != 1) ? "s" : "");
00362 }
00363 }
00364
00365 static cmd_t mydcc[] = {
00366 {"assoc", "", cmd_assoc, NULL},
00367 {NULL, NULL, NULL, NULL}
00368 };
00369
00370 static cmd_t mybot[] = {
00371 {"assoc", "", (IntFunc) zapf_assoc, NULL},
00372 {NULL, NULL, NULL, NULL}
00373 };
00374
00375 static cmd_t mylink[] = {
00376 {"*", "", (IntFunc) link_assoc, "assoc"},
00377 {NULL, NULL, NULL, NULL}
00378 };
00379
00380 static tcl_cmds mytcl[] = {
00381 {"assoc", tcl_assoc},
00382 {"killassoc", tcl_killassoc},
00383 {NULL, NULL}
00384 };
00385
00386 static char *assoc_close()
00387 {
00388 kill_all_assoc();
00389 rem_builtins(H_dcc, mydcc);
00390 rem_builtins(H_bot, mybot);
00391 rem_builtins(H_link, mylink);
00392 rem_tcl_commands(mytcl);
00393 rem_help_reference("assoc.help");
00394 del_lang_section("assoc");
00395 module_undepend(MODULE_NAME);
00396 return NULL;
00397 }
00398
00399 EXPORT_SCOPE char *assoc_start();
00400
00401 static Function assoc_table[] = {
00402 (Function) assoc_start,
00403 (Function) assoc_close,
00404 (Function) assoc_expmem,
00405 (Function) assoc_report,
00406 };
00407
00408 char *assoc_start(Function *global_funcs)
00409 {
00410 global = global_funcs;
00411
00412 module_register(MODULE_NAME, assoc_table, 2, 0);
00413 if (!module_depend(MODULE_NAME, "eggdrop", 106, 0)) {
00414 module_undepend(MODULE_NAME);
00415 return "This module requires Eggdrop 1.6.0 or later.";
00416 }
00417 assoc = NULL;
00418 add_builtins(H_dcc, mydcc);
00419 add_builtins(H_bot, mybot);
00420 add_builtins(H_link, mylink);
00421 add_lang_section("assoc");
00422 add_tcl_commands(mytcl);
00423 add_help_reference("assoc.help");
00424 return NULL;
00425 }