static int script_channel_get(script_var_t *retval, char *channel_name, char *setting) { char s[121]; struct chanset_t *chan; struct udef_struct *ul; int flagval; retval->type = SCRIPT_STRING; retval->len = -1; chan = findchan_by_dname(channel_name); if (!chan) return(-1); #define CHECK(x) !strcmp(setting, x) if (CHECK("chanmode")) get_mode_protect(chan, s); else if (CHECK("aop_delay")) sprintf(s, "%d %d", chan->aop_min, chan->aop_max); else if (CHECK("ban_time")) sprintf(s, "%d", chan->ban_time); else if (CHECK("exempt_time")) sprintf(s, "%d", chan->exempt_time); else if (CHECK("invite_time")) sprintf(s, "%d", chan->invite_time); else if (lookup_flag_by_name(normal_flag_map, setting, &flagval)) sprintf(s, "%d", chan->status & flagval); else if (lookup_flag_by_name(stupid_ircnet_flag_map, setting, &flagval)) sprintf(s, "%d", chan->ircnet_status & flagval); else { /* Hopefully it's a user-defined flag. */ for (ul = udef; ul && ul->name; ul = ul->next) { if (!strcmp(setting, ul->name)) break; } if (!ul || !ul->name) { /* Error if it wasn't found. */ return(-1); } if (ul->type == UDEF_STR) { char *value; /* If it's unset then give them an empty string. */ value = (char *)getudef(ul->values, chan->dname); if (!value) value = ""; retval->value = value; return(0); } else { /* Flag or int, all the same. */ sprintf(s, "%d", getudef(ul->values, chan->dname)); } } /* Ok, if we make it this far, the result is "s". */ retval->value = strdup(s); retval->type |= SCRIPT_FREE; return(0); }
/* Parse options for a channel. */ static int tcl_channel_modify(Tcl_Interp * irp, struct chanset_t *chan, int items, char **item) { int i, x = 0, found, old_status = chan->status, old_mode_mns_prot = chan->mode_mns_prot, old_mode_pls_prot = chan->mode_pls_prot; struct udef_struct *ul = udef; char s[121]; module_entry *me; for (i = 0; i < items; i++) { if (!strcmp(item[i], "chanmode")) { i++; if (i >= items) { if (irp) Tcl_AppendResult(irp, "channel chanmode needs argument", NULL); return TCL_ERROR; } strlcpy(s, item[i], sizeof s); set_mode_protect(chan, s); } else if (!strcmp(item[i], "ban_time")) { i++; if (i >= items) { if (irp) Tcl_AppendResult(irp, "channel ban_time needs argument", NULL); return TCL_ERROR; } chan->ban_time = atoi(item[i]); } else if (!strcmp(item[i], "exempt_time")) { i++; if (i >= items) { if (irp) Tcl_AppendResult(irp, "channel exempt_time needs argument", NULL); return TCL_ERROR; } chan->exempt_time = atoi(item[i]); } else if (!strcmp(item[i], "invite_time")) { i++; if (i >= items) { if (irp) Tcl_AppendResult(irp, "channel invite_time needs argument", NULL); return TCL_ERROR; } chan->invite_time = atoi(item[i]); } else if (item[i][0] == '+' || item[i][0] == '-') { int flagval; if (lookup_flag_by_name(normal_flag_map, item[i]+1, &flagval)) { if (item[i][0] == '-') chan->status &= ~flagval; else chan->status |= flagval; } else if (lookup_flag_by_name(stupid_ircnet_flag_map, item[i]+1, &flagval)) { if (item[i][0] == '-') chan->ircnet_status &= ~flagval; else chan->ircnet_status |= flagval; } else { /* Hopefully it's a user-defined flag! */ goto check_for_udef_flags; } } else if (!strncmp(item[i], "aop_delay", 9)) { char *p; i++; if (i >= items) { if (irp) Tcl_AppendResult(irp, item[i - 1], " needs argument", NULL); return TCL_ERROR; } p = strchr(item[i], ':'); if (p) { p++; chan->aop_min = atoi(item[i]); chan->aop_max = atoi(p); } else { chan->aop_min = atoi(item[i]); chan->aop_max = chan->aop_min; } } else { if (!strncmp(item[i] + 1, "udef_flag_", 10)) initudef(UDEF_FLAG, item[i] + 11, 0); else if (!strncmp(item[i], "udef_int_", 9)) initudef(UDEF_INT, item[i] + 9, 0); else if (!strncmp(item[i], "udef_str_", 9)) initudef(UDEF_STR, item[i] + 9, 0); check_for_udef_flags: found = 0; for (ul = udef; ul; ul = ul->next) { if (ul->type == UDEF_FLAG && /* Direct match when set during .chanset ... */ (!strcasecmp(item[i] + 1, ul->name) || /* ... or with prefix when set during chanfile load. */ (!strncmp(item[i] + 1, "udef_flag_", 10) && !strcasecmp(item[i] + 11, ul->name)))) { if (item[i][0] == '+') setudef(ul, chan->dname, 1); else setudef(ul, chan->dname, 0); found = 1; break; } else if (ul->type == UDEF_INT && /* Direct match when set during .chanset ... */ (!strcasecmp(item[i], ul->name) || /* ... or with prefix when set during chanfile load. */ (!strncmp(item[i], "udef_int_", 9) && !strcasecmp(item[i] + 9, ul->name)))) { i++; if (i >= items) { if (irp) Tcl_AppendResult(irp, "this setting needs an argument", NULL); return TCL_ERROR; } setudef(ul, chan->dname, atoi(item[i])); found = 1; break; } else if (ul->type == UDEF_STR && (!strcasecmp(item[i], ul->name) || (!strncmp(item[i], "udef_str_", 9) && !strcasecmp(item[i] + 9, ul->name)))) { char *val; i++; if (i >= items) { if (irp) Tcl_AppendResult(irp, "this setting needs an argument", NULL); return TCL_ERROR; } val = (char *)getudef(ul->values, chan->dname); if (val) free(val); /* Get extra room for new braces, etc */ val = malloc(3 * strlen(item[i]) + 10); convert_element(item[i], val); val = realloc(val, strlen(val)+1); setudef(ul, chan->dname, (int)val); found = 1; break; } } if (!found) { if (irp && item[i][0]) /* ignore "" */ Tcl_AppendResult(irp, "illegal channel option: ", item[i], NULL); x++; } } } /* If protect_readonly == 0 and chan_hack == 0 then * bot is now processing the configfile, so dont do anything, * we've to wait the channelfile that maybe override these settings * (note: it may cause problems if there is no chanfile!) * <drummer/1999/10/21> */ if (protect_readonly || chan_hack) { if (((old_status ^ chan->status) & CHAN_INACTIVE) && module_find("irc", 0, 0)) { if (channel_inactive(chan) && (chan->status & (CHAN_ACTIVE | CHAN_PEND))) dprintf(DP_SERVER, "PART %s\n", chan->name); if (!channel_inactive(chan) && !(chan->status & (CHAN_ACTIVE | CHAN_PEND))) dprintf(DP_SERVER, "JOIN %s %s\n", (chan->name[0]) ? chan->name : chan->dname, chan->channel.key[0] ? chan->channel.key : chan->key_prot); } if ((old_status ^ chan->status) & (CHAN_ENFORCEBANS | CHAN_OPONJOIN | CHAN_AUTOVOICE)) { if ((me = module_find("irc", 0, 0))) (me->funcs[IRC_RECHECK_CHANNEL])(chan, 1); } else if (old_mode_pls_prot != chan->mode_pls_prot || old_mode_mns_prot != chan->mode_mns_prot) if ((me = module_find("irc", 1, 2))) (me->funcs[IRC_RECHECK_CHANNEL_MODES])(chan); } if (x > 0) return TCL_ERROR; return TCL_OK; }
/* * Note: * - We write chanmode "" too, so that the bot won't use default-chanmode * instead of "" * - We will write empty need-xxxx too, why not? (less code + lazyness) */ static void write_channels() { FILE *f; char s[121], w[1024], w2[1024], name[163]; char need1[242], need2[242], need3[242], need4[242], need5[242]; struct chanset_t *chan; struct udef_struct *ul; if (!chanfile[0]) return; sprintf(s, "%s~new", chanfile); f = fopen(s, "w"); chmod(s, userfile_perm); if (f == NULL) { putlog(LOG_MISC, "*", "ERROR writing channel file."); return; } if (!quiet_save) putlog(LOG_MISC, "*", "Writing channel file..."); fprintf(f, "#Dynamic Channel File for %s (%s) -- written %s\n", botnetnick, ver, ctime(&now)); for (chan = chanset; chan; chan = chan->next) { convert_element(chan->dname, name); get_mode_protect(chan, w); convert_element(w, w2); convert_element(chan->need_op, need1); convert_element(chan->need_invite, need2); convert_element(chan->need_key, need3); convert_element(chan->need_unban, need4); convert_element(chan->need_limit, need5); fprintf(f, "channel add %s { chanmode %s idle-kick %d stopnethack-mode %d " "revenge-mode %d need-op %s need-invite %s need-key %s " "need-unban %s need-limit %s flood-chan %d:%d flood-ctcp %d:%d " "flood-join %d:%d flood-kick %d:%d flood-deop %d:%d " "flood-nick %d:%d aop-delay %d:%d ban-type %d ban-time %d " "exempt-time %d invite-time %d %cenforcebans %cdynamicbans " "%cuserbans %cautoop %cautohalfop %cbitch %cgreet %cprotectops " "%cprotecthalfops %cprotectfriends %cdontkickops %cstatuslog " "%crevenge %crevengebot %cautovoice %csecret %cshared %ccycle " "%cseen %cinactive %cdynamicexempts %cuserexempts %cdynamicinvites " "%cuserinvites %cnodesynch %cstatic }" "\n", name, w2, chan->idle_kick, chan->stopnethack_mode, chan->revenge_mode, need1, need2, need3, need4, need5, chan->flood_pub_thr, chan->flood_pub_time, chan->flood_ctcp_thr, chan->flood_ctcp_time, chan->flood_join_thr, chan->flood_join_time, chan->flood_kick_thr, chan->flood_kick_time, chan->flood_deop_thr, chan->flood_deop_time, chan->flood_nick_thr, chan->flood_nick_time, chan->aop_min, chan->aop_max, chan->ban_type, chan->ban_time, chan->exempt_time, chan->invite_time, PLSMNS(channel_enforcebans(chan)), PLSMNS(channel_dynamicbans(chan)), PLSMNS(!channel_nouserbans(chan)), PLSMNS(channel_autoop(chan)), PLSMNS(channel_autohalfop(chan)), PLSMNS(channel_bitch(chan)), PLSMNS(channel_greet(chan)), PLSMNS(channel_protectops(chan)), PLSMNS(channel_protecthalfops(chan)), PLSMNS(channel_protectfriends(chan)), PLSMNS(channel_dontkickops(chan)), PLSMNS(channel_logstatus(chan)), PLSMNS(channel_revenge(chan)), PLSMNS(channel_revengebot(chan)), PLSMNS(channel_autovoice(chan)), PLSMNS(channel_secret(chan)), PLSMNS(channel_shared(chan)), PLSMNS(channel_cycle(chan)), PLSMNS(channel_seen(chan)), PLSMNS(channel_inactive(chan)), PLSMNS(channel_dynamicexempts(chan)), PLSMNS(!channel_nouserexempts(chan)), PLSMNS(channel_dynamicinvites(chan)), PLSMNS(!channel_nouserinvites(chan)), PLSMNS(channel_nodesynch(chan)), PLSMNS(channel_static(chan))); for (ul = udef; ul; ul = ul->next) { if (ul->defined && ul->name) { if (ul->type == UDEF_FLAG) fprintf(f, "channel set %s %c%s%s\n", name, getudef(ul->values, chan->dname) ? '+' : '-', "udef-flag-", ul->name); else if (ul->type == UDEF_INT) fprintf(f, "channel set %s %s%s %d\n", name, "udef-int-", ul->name, (int) getudef(ul->values, chan->dname)); else if (ul->type == UDEF_STR) { char *p = (char *) getudef(ul->values, chan->dname); if (!p) p = "{}"; fprintf(f, "channel set %s udef-str-%s %s\n", name, ul->name, p); } else debug1("UDEF-ERROR: unknown type %d", ul->type); } } if (fflush(f)) { putlog(LOG_MISC, "*", "ERROR writing channel file."); fclose(f); return; } } fclose(f); unlink(chanfile); movefile(s, chanfile); }
/* * Note: * - We write chanmode "" too, so that the bot won't use default-chanmode * instead of "" * - We will write empty need-xxxx too, why not? (less code + lazyness) */ static void write_channels() { FILE *f; char s[121], w[1024], w2[1024], name[163]; char need1[242], need2[242], need3[242], need4[242], need5[242]; struct chanset_t *chan; struct udef_struct *ul; Context; if (!chanfile[0]) return; sprintf(s, "%s~new", chanfile); f = fopen(s, "w"); chmod(s, userfile_perm); if (f == NULL) { putlog(LOG_MISC, "*", "ERROR writing channel file."); return; } if (!quiet_save) putlog(LOG_MISC, "*", "Writing channel file ..."); fprintf(f, "#Dynamic Channel File for %s (%s) -- written %s\n", origbotname, ver, ctime(&now)); for (chan = chanset; chan; chan = chan->next) { convert_element(chan->dname, name); get_mode_protect(chan, w); convert_element(w, w2); convert_element(chan->need_op, need1); convert_element(chan->need_invite, need2); convert_element(chan->need_key, need3); convert_element(chan->need_unban, need4); convert_element(chan->need_limit, need5); fprintf(f, "channel %s %s%schanmode %s idle-kick %d stopnethack-mode %d \ need-op %s need-invite %s need-key %s need-unban %s need-limit %s \ flood-chan %d:%d flood-ctcp %d:%d flood-join %d:%d \ flood-kick %d:%d flood-deop %d:%d flood-nick %d:%d \ %cclearbans %cenforcebans %cdynamicbans %cuserbans %cautoop %cbitch \ %cgreet %cprotectops %cprotectfriends %cdontkickops \ %cstatuslog %crevenge %crevengebot %cautovoice %csecret \ %cshared %ccycle %cseen %cinactive %cdynamicexempts %cuserexempts \ %cdynamicinvites %cuserinvites %cnodesynch ", channel_static(chan) ? "set" : "add", name, channel_static(chan) ? " " : " { ", w2, chan->idle_kick, /* idle-kick 0 is same as dont-idle-kick (less code)*/ chan->stopnethack_mode, need1, need2, need3, need4, need5, chan->flood_pub_thr, chan->flood_pub_time, chan->flood_ctcp_thr, chan->flood_ctcp_time, chan->flood_join_thr, chan->flood_join_time, chan->flood_kick_thr, chan->flood_kick_time, chan->flood_deop_thr, chan->flood_deop_time, chan->flood_nick_thr, chan->flood_nick_time, PLSMNS(channel_clearbans(chan)), PLSMNS(channel_enforcebans(chan)), PLSMNS(channel_dynamicbans(chan)), PLSMNS(!channel_nouserbans(chan)), PLSMNS(channel_autoop(chan)), PLSMNS(channel_bitch(chan)), PLSMNS(channel_greet(chan)), PLSMNS(channel_protectops(chan)), PLSMNS(channel_protectfriends(chan)), PLSMNS(channel_dontkickops(chan)), PLSMNS(channel_logstatus(chan)), PLSMNS(channel_revenge(chan)), PLSMNS(channel_revengebot(chan)), PLSMNS(channel_autovoice(chan)), PLSMNS(channel_secret(chan)), PLSMNS(channel_shared(chan)), PLSMNS(channel_cycle(chan)), PLSMNS(channel_seen(chan)), PLSMNS(channel_inactive(chan)), PLSMNS(channel_dynamicexempts(chan)), PLSMNS(!channel_nouserexempts(chan)), PLSMNS(channel_dynamicinvites(chan)), PLSMNS(!channel_nouserinvites(chan)), PLSMNS(channel_nodesynch(chan))); for (ul = udef; ul; ul = ul->next) { if (ul->defined && ul->name) { if (ul->type == UDEF_FLAG) fprintf(f, "%c%s%s ", getudef(ul->values, chan->dname) ? '+' : '-', "udef-flag-", ul->name); else if (ul->type == UDEF_INT) fprintf(f, "%s%s %d ", "udef-int-", ul->name, getudef(ul->values, chan->dname)); else debug1("UDEF-ERROR: unknown type %d", ul->type); } } fprintf(f, "%s\n", channel_static(chan) ? "" : "}"); if (fflush(f)) { putlog(LOG_MISC, "*", "ERROR writing channel file."); fclose(f); return; } } fclose(f); unlink(chanfile); movefile(s, chanfile); }