static int tcl_boot(ClientData cd, Tcl_Interp *irp, int argc, char *argv[]) { char who[NOTENAMELEN + 1]; int i, ok = 0; BADARGS(2, 3, " user@bot ?reason?"); strncpyz(who, argv[1], sizeof who); if (strchr(who, '@') != NULL) { char whonick[HANDLEN + 1]; splitc(whonick, who, '@'); whonick[HANDLEN] = 0; if (!egg_strcasecmp(who, botnetnick)) strncpyz(who, whonick, sizeof who); else if (remote_boots > 0) { i = nextbot(who); if (i < 0) return TCL_OK; botnet_send_reject(i, botnetnick, NULL, whonick, who, argv[2] ? argv[2] : ""); } else return TCL_OK; } for (i = 0; i < dcc_total; i++) if (!ok && (dcc[i].type->flags & DCT_CANBOOT) && !egg_strcasecmp(dcc[i].nick, who)) { do_boot(i, botnetnick, argv[2] ? argv[2] : ""); ok = 1; } return TCL_OK; }
/* traced <to@bot> <chain:chain..> */ static void bot_traced(int idx, char *par) { char *to, *p; int i, sock; to = newsplit(&par); p = strchr(to, '@'); if (p == NULL) p = to; else { *p = 0; p++; } if (!egg_strcasecmp(p, botnetnick)) { time_t t = 0; char *p = par, *ss = TBUF; splitc(ss, to, ':'); if (ss[0]) sock = atoi(ss); else sock = -1; if (par[0] == ':') { t = atoi(par + 1); p = strchr(par + 1, ':'); if (p) p++; else p = par + 1; } for (i = 0; i < dcc_total; i++) if ((dcc[i].type->flags & DCT_CHAT) && (!egg_strcasecmp(dcc[i].nick, to)) && ((sock == -1) || (sock == dcc[i].sock))) { if (t) { int j = 0; { register char *c = p; for (; *c != '\0'; c++) if (*c == ':') j++; } dprintf(i, "%s -> %s (%lu secs, %d hop%s)\n", BOT_TRACERESULT, p, now - t, j, (j != 1) ? "s" : ""); } else dprintf(i, "%s -> %s\n", BOT_TRACERESULT, p); } } else { i = nextbot(p); if (p != to) *--p = '@'; if (i >= 0) botnet_send_traced(i, to, par); } }
static void wordshift(char *first, char *rest) { char *p, *q = rest; do { p = newsplit(&q); strcpy(first, p); strcpy(rest, q); } while (!egg_strcasecmp(first, "and") || !egg_strcasecmp(first, "or")); }
static intptr_t ngetudef(char *name, char *chan) { struct udef_struct *l; struct udef_chans *ll; for (l = udef; l; l = l->next) if (!egg_strcasecmp(l->name, name)) { for (ll = l->values; ll; ll = ll->next) if (!egg_strcasecmp(ll->chan, chan)) return ll->value; break; } return 0; }
int deflag_translate(const char *buf) { if (str_isdigit(buf)) return (atoi(buf)); if (!egg_strcasecmp(buf, "ignore")) return P_IGNORE; else if (!egg_strcasecmp(buf, "deop")) return P_DEOP; else if (!egg_strcasecmp(buf, "kick")) return P_KICK; else if (!egg_strcasecmp(buf, "delete") || !egg_strcasecmp(buf, "remove")) return P_DELETE; return P_IGNORE; }
/* link <from@bot> <who> <to-whom> */ static void bot_link(int idx, char *par) { char *from, *bot, *rfrom; int i; from = newsplit(&par); bot = newsplit(&par); if (!egg_strcasecmp(bot, botnetnick)) { if ((rfrom = strchr(from, ':'))) rfrom++; else rfrom = from; putlog(LOG_CMDS, "*", "#%s# link %s", rfrom, par); if (botlink(from, -1, par)) botnet_send_priv(idx, botnetnick, from, NULL, "%s %s ...", BOT_LINKATTEMPT, par); else botnet_send_priv(idx, botnetnick, from, NULL, "%s.", BOT_CANTLINKTHERE); } else { i = nextbot(bot); if (i >= 0) botnet_send_link(i, from, bot, par); } }
/* who <from@bot> <tobot> <chan#> */ static void bot_who(int idx, char *par) { char *from, *to, *p; int i, chan; from = newsplit(&par); p = strchr(from, '@'); if (!p) { sprintf(TBUF, "%s@%s", from, dcc[idx].nick); from = TBUF; } to = newsplit(&par); if (!egg_strcasecmp(to, botnetnick)) to[0] = 0; #ifndef NO_OLD_BOTNET if (dcc[idx].u.bot->numver < NEAT_BOTNET) chan = atoi(par); else #endif chan = base64_to_int(par); if (to[0]) { i = nextbot(to); if (i >= 0) botnet_send_who(i, from, to, chan); } else remote_tell_who(idx, from, chan); }
/* filereq <sock:nick@bot> <bot:file> */ static void bot_filereq(int idx, char *tobot) { char *from, *path; int i; from = newsplit(&tobot); if ((path = strchr(tobot, ':'))) { *path++ = 0; if (!egg_strcasecmp(tobot, botnetnick)) { /* For me! */ /* Process this */ module_entry *fs = module_find("filesys", 0, 0); if (fs == NULL) botnet_send_priv(idx, botnetnick, from, NULL, MOD_NOFILESYSMOD); else { Function f = fs->funcs[FILESYS_REMOTE_REQ]; f(idx, from, path); } } else { /* Pass it on */ i = nextbot(tobot); if (i >= 0) botnet_send_filereq(i, from, tobot, path); } } }
/* These are still here, so that they will pass the relevant * requests through even if no filesys is loaded. * * filereject <bot:filepath> <sock:nick@bot> <reason...> */ static void bot_filereject(int idx, char *par) { char *path, *to, *tobot, *p; int i; path = newsplit(&par); to = newsplit(&par); if ((tobot = strchr(to, '@'))) tobot++; else tobot = to; /* Bot wants a file?! :) */ if (egg_strcasecmp(tobot, botnetnick)) { /* for me! */ p = strchr(to, ':'); if (p != NULL) { *p = 0; for (i = 0; i < dcc_total; i++) { if (dcc[i].sock == atoi(to)) dprintf(i, "%s (%s): %s\n", BOT_XFERREJECTED, path, par); } *p = ':'; } /* No ':'? malformed */ putlog(LOG_FILES, "*", "%s %s: %s", path, MISC_REJECTED, par); } else { /* Pass it on */ i = nextbot(tobot); if (i >= 0) botnet_send_filereject(i, path, to, par); } }
static void initudef(int type, char *name, int defined) { struct udef_struct *ul, *ul_last = NULL; if (strlen(name) < 1) return; for (ul = udef; ul; ul_last = ul, ul = ul->next) if (ul->name && !egg_strcasecmp(ul->name, name)) { if (defined) { debug1("UDEF: %s defined", ul->name); ul->defined = 1; } return; } debug2("Creating %s (type %d)", name, type); ul = nmalloc(sizeof(struct udef_struct)); ul->name = nmalloc(strlen(name) + 1); strcpy(ul->name, name); if (defined) ul->defined = 1; else ul->defined = 0; ul->type = type; ul->values = NULL; ul->next = NULL; if (ul_last) ul_last->next = ul; else udef = ul; }
static void join_notes(char *nick, char *uhost, char *handle, char *par) { int i = -1, j; struct chanset_t *chan = chanset; if (notify_onjoin) { /* drummer */ for (j = 0; j < dcc_total; j++) if ((dcc[j].type->flags & DCT_CHAT) && (!egg_strcasecmp(dcc[j].nick, handle))) return; /* They already know they have notes */ while (chan) { if (ismember(chan, nick)) return; /* They already know they have notes */ chan = chan->next; } i = num_notes(handle); if (i) { dprintf(DP_HELP, NOTES_WAITING_NOTICE, nick, i, (i == 1) ? "" : "s", botname); dprintf(DP_HELP, "NOTICE %s :%s /MSG %s NOTES <pass> INDEX\n", nick, NOTES_FORLIST, botname); } } }
tcl_bind_list_t *add_bind_table(const char *nme, int flg, Function func) { tcl_bind_list_t *tl, *tl_prev; int v; /* Do not allow coders to use bind table names longer than * 4 characters. */ Assert(strlen(nme) <= 4); for (tl = bind_table_list, tl_prev = NULL; tl; tl_prev = tl, tl = tl->next) { if (tl->flags & HT_DELETED) continue; v = egg_strcasecmp(tl->name, nme); if (!v) return tl; /* Duplicate, just return old value. */ if (v > 0) break; /* New. Insert at start of list. */ } tl = nmalloc_null(sizeof *tl); strcpy(tl->name, nme); tl->flags = flg; tl->func = func; if (tl_prev) { tl->next = tl_prev->next; tl_prev->next = tl; } else { tl->next = bind_table_list; bind_table_list = tl; } putlog(LOG_DEBUG, "*", "Allocated bind table %s (flags %d).", nme, flg); return tl; }
static void zapf_assoc(char *botnick, char *code, char *par) { int idx = nextbot(botnick); char *s, *s1, *nick; int linking = 0, chan; if ((idx >= 0) && !(bot_flags(dcc[idx].user) & BOT_ISOLATE)) { if (!egg_strcasecmp(dcc[idx].nick, botnick)) linking = b_status(idx) & STAT_LINKING; s = newsplit(&par); chan = base64_to_int(s); if ((chan > 0) || (chan < GLOBAL_CHANS)) { nick = newsplit(&par); s1 = get_assoc_name(chan); if (linking && ((s1 == NULL) || (s1[0] == 0) || (((intptr_t) get_user(find_entry_type("BOTFL"), dcc[idx].user) & BOT_HUB)))) { add_assoc(par, chan); botnet_send_assoc(idx, chan, nick, par); chanout_but(-1, chan, ASSOC_CHNAME_NAMED, nick, par); } else if (par[0] == '0') { kill_assoc(chan); chanout_but(-1, chan, ASSOC_CHNAME_REM, botnick, nick); } else if (get_assoc(par) != chan) { /* New one i didn't know about -- pass it on */ s1 = get_assoc_name(chan); add_assoc(par, chan); chanout_but(-1, chan, ASSOC_CHNAME_NAMED2, botnick, nick, par); } } } }
/* Got 442: not on channel */ static int got442(char *from, char *msg) { char *chname, *key; struct chanset_t *chan; if (!realservername || egg_strcasecmp(from, realservername)) return 0; newsplit(&msg); chname = newsplit(&msg); chan = findchan(chname); if (chan && !channel_inactive(chan)) { module_entry *me = module_find("channels", 0, 0); putlog(LOG_MISC, chname, IRC_SERVNOTONCHAN, chname); if (me && me->funcs) (me->funcs[CHANNEL_CLEAR]) (chan, 1); chan->status &= ~CHAN_ACTIVE; key = chan->channel.key[0] ? chan->channel.key : chan->key_prot; if (key[0]) dprintf(DP_SERVER, "JOIN %s %s\n", chan->name, key); else dprintf(DP_SERVER, "JOIN %s\n", chan->name); } return 0; }
void call_ipbyhost(char *hostn, IP ip, int ok) { devent_t *de = dns_events, *ode = NULL, *nde = NULL; Context; while (de) { nde = de->next; if ((de->lookup == RES_IPBYHOST) && (!de->res_data.hostname || !egg_strcasecmp(de->res_data.hostname, hostn))) { /* Remove the event from the list here, to avoid conflicts if one of * the event handlers re-adds another event. */ if (ode) ode->next = de->next; else dns_events = de->next; if (de->type && de->type->event) de->type->event(ip, hostn, ok, de->other); else putlog(LOG_MISC, "*", "(!) Unknown DNS event type found: %s", (de->type && de->type->name) ? de->type->name : "<empty>"); if (de->res_data.hostname) nfree(de->res_data.hostname); nfree(de); de = ode; } ode = de; de = nde; } }
static char *getxtra(char *hand, char *field) { struct userrec *urec; struct user_entry *ue; struct xtra_key *xk; urec = get_user_by_handle(userlist, hand); if (urec) { ue = find_user_entry(&USERENTRY_XTRA, urec); if (ue) for (xk = ue->u.extra; xk; xk = xk->next) if (xk->key && !egg_strcasecmp(xk->key, field)) { if (xk->data[0] == '{' && xk->data[strlen(xk->data) - 1] == '}' && strlen(xk->data) > 2) { strncpy(fixit, &xk->data[1], strlen(xk->data) - 2); fixit[strlen(xk->data) - 2] = 0; return fixit; } else { return xk->data; } } } return ""; }
/* Determine how many notes are waiting for a user. */ static int num_notes(char *user) { int tot = 0; FILE *f; char s[513], *to, *s1; if (!notefile[0]) return 0; f = fopen(notefile, "r"); if (f == NULL) return 0; while (!feof(f)) { fgets(s, 512, f); if (!feof(f)) { if (s[strlen(s) - 1] == '\n') s[strlen(s) - 1] = 0; rmspace(s); if ((s[0]) && (s[0] != '#') && (s[0] != ';')) { /* Not comment */ s1 = s; to = newsplit(&s1); if (!egg_strcasecmp(to, user)) tot++; } } } fclose(f); return tot; }
/* Add command (remove old one if necessary) */ static int bind_bind_entry(tcl_bind_list_t *tl, const char *flags, const char *cmd, const char *proc) { tcl_cmd_t *tc; tcl_bind_mask_t *tm; /* Search for matching bind in bind list. */ for (tm = tl->first; tm; tm = tm->next) { if (tm->flags & TBM_DELETED) continue; if (!strcmp(cmd, tm->mask)) break; /* Found it! fall out! */ } /* Create bind if it doesn't exist yet. */ if (!tm) { tm = nmalloc_null(sizeof *tm); tm->mask = nmalloc(strlen(cmd) + 1); strcpy(tm->mask, cmd); /* Link into linked list of binds. */ tm->next = tl->first; tl->first = tm; } /* Proc already defined? If so, replace. */ for (tc = tm->first; tc; tc = tc->next) { if (tc->attributes & TC_DELETED) continue; if (!egg_strcasecmp(tc->func_name, proc)) { tc->flags.match = FR_GLOBAL | FR_CHAN; break_down_flags(flags, &(tc->flags), NULL); return 1; } } /* If this bind list is not stackable, remove the * old entry from this bind. */ if (!(tl->flags & HT_STACKABLE)) { for (tc = tm->first; tc; tc = tc->next) { if (tc->attributes & TC_DELETED) continue; /* NOTE: We assume there's only one not-yet-deleted entry. */ tc->attributes |= TC_DELETED; break; } } tc = nmalloc_null(sizeof *tc); tc->flags.match = FR_GLOBAL | FR_CHAN; break_down_flags(flags, &(tc->flags), NULL); tc->func_name = nmalloc(strlen(proc) + 1); strcpy(tc->func_name, proc); /* Link into linked list of the bind's command list. */ tc->next = tm->first; tm->first = tc; return 1; }
static int unbind_bind_entry(tcl_bind_list_t *tl, const char *flags, const char *cmd, const char *proc) { tcl_bind_mask_t *tm; /* Search for matching bind in bind list. */ for (tm = tl->first; tm; tm = tm->next) { if (tm->flags & TBM_DELETED) continue; if (!strcmp(cmd, tm->mask)) break; /* Found it! fall out! */ } if (tm) { tcl_cmd_t *tc; /* Search for matching proc in bind. */ for (tc = tm->first; tc; tc = tc->next) { if (tc->attributes & TC_DELETED) continue; if (!egg_strcasecmp(tc->func_name, proc)) { /* Erase proc regardless of flags. */ tc->attributes |= TC_DELETED; return 1; /* Match. */ } } } return 0; /* No match. */ }
void dcc_dnsipbyhost(char *hostn) { devent_t *de = dns_events; Context; while (de) { if (de->type && (de->type == &DNS_DCCEVENT_IPBYHOST) && (de->lookup == RES_IPBYHOST)) { if (de->res_data.hostname && !egg_strcasecmp(de->res_data.hostname, hostn)) /* No need to add anymore. */ return; } de = de->next; } de = nmalloc(sizeof(devent_t)); egg_bzero(de, sizeof(devent_t)); /* Link into list. */ de->next = dns_events; dns_events = de; de->type = &DNS_DCCEVENT_IPBYHOST; de->lookup = RES_IPBYHOST; de->res_data.hostname = nmalloc(strlen(hostn) + 1); strcpy(de->res_data.hostname, hostn); /* Send request. */ dns_ipbyhost(hostn); }
int det_translate(const char *word) { if (word && word[0]) { if (!egg_strcasecmp(word, STR("ignore"))) return DET_IGNORE; else if (!egg_strcasecmp(word, STR("warn"))) return DET_WARN; else if (!egg_strcasecmp(word, STR("reject"))) return DET_REJECT; else if (!egg_strcasecmp(word, STR("die"))) return DET_DIE; else if (!egg_strcasecmp(word, STR("suicide"))) return DET_SUICIDE; } return DET_IGNORE; }
/* Change someone's handle. */ static void notes_change(char *oldnick, char *newnick) { FILE *f, *g; char s[513], *to, *s1; int tot = 0; if (!egg_strcasecmp(oldnick, newnick)) return; if (!notefile[0]) return; f = fopen(notefile, "r"); if (f == NULL) return; sprintf(s, "%s~new", notefile); g = fopen(s, "w"); if (g == NULL) { fclose(f); return; } chmod(s, userfile_perm); /* Use userfile permissions. */ while (!feof(f)) { fgets(s, 512, f); if (!feof(f)) { if (s[strlen(s) - 1] == '\n') s[strlen(s) - 1] = 0; rmspace(s); if ((s[0]) && (s[0] != '#') && (s[0] != ';')) { /* Not comment */ s1 = s; to = newsplit(&s1); if (!egg_strcasecmp(to, oldnick)) { tot++; fprintf(g, "%s %s\n", newnick, s1); } else fprintf(g, "%s %s\n", to, s1); } else fprintf(g, "%s\n", s); } } fclose(f); fclose(g); unlink(notefile); sprintf(s, "%s~new", notefile); movefile(s, notefile); putlog(LOG_MISC, "*", NOTES_SWITCHED_NOTES, tot, tot == 1 ? "" : "s", oldnick, newnick); }
static int tcl_setchan(ClientData cd, Tcl_Interp *irp, int argc, char *argv[]) { int idx, chan; module_entry *me; BADARGS(3, 3, " idx channel"); idx = findidx(atoi(argv[1])); if (idx < 0 || (dcc[idx].type != &DCC_CHAT && dcc[idx].type != &DCC_SCRIPT)) { Tcl_AppendResult(irp, "invalid idx", NULL); return TCL_ERROR; } if (argv[2][0] < '0' || argv[2][0] > '9') { if (!strcmp(argv[2], "-1") || !egg_strcasecmp(argv[2], "off")) chan = -1; else { Tcl_SetVar(irp, "chan", argv[2], 0); if (Tcl_VarEval(irp, "assoc ", "$chan", NULL) != TCL_OK || !interp->result[0]) { Tcl_AppendResult(irp, "channel name is invalid", NULL); return TCL_ERROR; } chan = atoi(interp->result); } } else chan = atoi(argv[2]); if ((chan < -1) || (chan > 199999)) { Tcl_AppendResult(irp, "channel out of range; must be -1 through 199999", NULL); return TCL_ERROR; } if (dcc[idx].type == &DCC_SCRIPT) dcc[idx].u.script->u.chat->channel = chan; else { int oldchan = dcc[idx].u.chat->channel; if (dcc[idx].u.chat->channel >= 0) { if ((chan >= GLOBAL_CHANS) && (oldchan < GLOBAL_CHANS)) botnet_send_part_idx(idx, "*script*"); check_tcl_chpt(botnetnick, dcc[idx].nick, dcc[idx].sock, dcc[idx].u.chat->channel); } dcc[idx].u.chat->channel = chan; if (chan < GLOBAL_CHANS) botnet_send_join_idx(idx, oldchan); check_tcl_chjn(botnetnick, dcc[idx].nick, chan, geticon(idx), dcc[idx].sock, dcc[idx].host); } /* Console autosave. */ if ((me = module_find("console", 1, 1))) { Function *func = me->funcs; (func[CONSOLE_DOSTORE]) (idx); } return TCL_OK; }
static int cache_find(const char *query) { int i; for (i = 0; i < ncache; i++) if (!egg_strcasecmp(cache[i].query, query)) return (i); return (-1); }
static int get_assoc(char *name) { assoc_t *a; for (a = assoc; a; a = a->next) if (!egg_strcasecmp(a->name, name)) return a->channel; return -1; }
dns_query_t *find_query(const char *host) { dns_query_t *q = NULL; for (q = query_head; q; q = q->next) if (!egg_strcasecmp(q->query, host)) return q; return NULL; }
static void cmd_clearqueue(struct userrec *u, int idx, char *par) { int msgs; if (!par[0]) { dprintf(idx, "Usage: clearqueue <mode|server|help|all>\n"); return; } if (!egg_strcasecmp(par, "all")) { msgs = modeq.tot + mq.tot + hq.tot; msgq_clear(&modeq); msgq_clear(&mq); msgq_clear(&hq); double_warned = burst = 0; dprintf(idx, "Removed %d message%s from all queues.\n", msgs, (msgs != 1) ? "s" : ""); } else if (!egg_strcasecmp(par, "mode")) { msgs = modeq.tot; msgq_clear(&modeq); if (mq.tot == 0) burst = 0; double_warned = 0; dprintf(idx, "Removed %d message%s from the mode queue.\n", msgs, (msgs != 1) ? "s" : ""); } else if (!egg_strcasecmp(par, "help")) { msgs = hq.tot; msgq_clear(&hq); double_warned = 0; dprintf(idx, "Removed %d message%s from the help queue.\n", msgs, (msgs != 1) ? "s" : ""); } else if (!egg_strcasecmp(par, "server")) { msgs = mq.tot; msgq_clear(&mq); if (modeq.tot == 0) burst = 0; double_warned = 0; dprintf(idx, "Removed %d message%s from the server queue.\n", msgs, (msgs != 1) ? "s" : ""); } else { dprintf(idx, "Usage: clearqueue <mode|server|help|all>\n"); return; } putlog(LOG_CMDS, "*", "#%s# clearqueue %s", dcc[idx].nick, par); }
/* Got nick change. */ static int gotnick(char *from, char *msg) { char *nick, *alt = get_altbotnick(); nick = splitnick(&from); fixcolon(msg); check_queues(nick, msg); if (match_my_nick(nick)) { /* Regained nick! */ strncpyz(botname, msg, NICKLEN); altnick_char = 0; if (!strcmp(msg, origbotname)) { putlog(LOG_SERV | LOG_MISC, "*", "Regained nickname '%s'.", msg); nick_juped = 0; } else if (alt[0] && !strcmp(msg, alt)) putlog(LOG_SERV | LOG_MISC, "*", "Regained alternate nickname '%s'.", msg); else if (keepnick && strcmp(nick, msg)) { putlog(LOG_SERV | LOG_MISC, "*", "Nickname changed to '%s'???", msg); if (!rfc_casecmp(nick, origbotname)) { putlog(LOG_MISC, "*", IRC_GETORIGNICK, origbotname); dprintf(DP_SERVER, "NICK %s\n", origbotname); } else if (alt[0] && !rfc_casecmp(nick, alt) && egg_strcasecmp(botname, origbotname)) { putlog(LOG_MISC, "*", IRC_GETALTNICK, alt); dprintf(DP_SERVER, "NICK %s\n", alt); } } else putlog(LOG_SERV | LOG_MISC, "*", "Nickname changed to '%s'???", msg); } else if ((keepnick) && (rfc_casecmp(nick, msg))) { /* Only do the below if there was actual nick change, case doesn't count */ if (!rfc_casecmp(nick, origbotname)) { putlog(LOG_MISC, "*", IRC_GETORIGNICK, origbotname); dprintf(DP_SERVER, "NICK %s\n", origbotname); } else if (alt[0] && !rfc_casecmp(nick, alt) && egg_strcasecmp(botname, origbotname)) { putlog(LOG_MISC, "*", IRC_GETALTNICK, altnick); dprintf(DP_SERVER, "NICK %s\n", altnick); } } return 0; }
static void away_notes(char *bot, int sock, char *msg) { int idx = findanyidx(sock); if (egg_strcasecmp(bot, botnetnick)) return; if (msg && msg[0]) dprintf(idx, "%s\n", NOTES_STORED); else notes_read(dcc[idx].nick, 0, "+", idx); }
/* Shortcut for get_user_by_handle -- might have user record in channels */ struct userrec *check_chanlist_hand(const char *hand) { register struct chanset_t *chan; register memberlist *m; for (chan = chanset; chan; chan = chan->next) for (m = chan->channel.member; m && m->nick[0]; m = m->next) if (m->user && !egg_strcasecmp(m->user->handle, hand)) return m->user; return NULL; }