trustgroup *tg_add(trustgroup *itg) { trustgroup *tg = nsmalloc(POOL_TRUSTS, sizeof(trustgroup)); if(!tg) return NULL; memcpy(tg, itg, sizeof(trustgroup)); tg->name = getsstring(tg->name->content, TRUSTNAMELEN); tg->createdby = getsstring(tg->createdby->content, CREATEDBYLEN); tg->contact = getsstring(tg->contact->content, CONTACTLEN); tg->comment = getsstring(tg->comment->content, COMMENTLEN); if(!tg->name || !tg->createdby || !tg->contact || !tg->comment) { tg_free(tg, 0); return NULL; } tg->hosts = NULL; tg->marker = 0; tg->count = 0; memset(tg->exts, 0, sizeof(tg->exts)); tg->next = tglist; tglist = tg; triggerhook(HOOK_TRUSTS_NEWGROUP, tg); return tg; }
int tg_modify(trustgroup *oldtg, trustgroup *newtg) { trustgroup vnewtg; memcpy(&vnewtg, oldtg, sizeof(trustgroup)); /* unfortunately we can't just memcpy the new one over */ vnewtg.name = getsstring(newtg->name->content, TRUSTNAMELEN); vnewtg.createdby = getsstring(newtg->createdby->content, CREATEDBYLEN); vnewtg.contact = getsstring(newtg->contact->content, CONTACTLEN); vnewtg.comment = getsstring(newtg->comment->content, COMMENTLEN); if(!vnewtg.name || !vnewtg.createdby || !vnewtg.contact || !vnewtg.comment) { freesstring(vnewtg.name); freesstring(vnewtg.createdby); freesstring(vnewtg.contact); freesstring(vnewtg.comment); return 0; } /* id remains the same, count/hosts/marker/next/exts are ignored */ vnewtg.trustedfor = newtg->trustedfor; vnewtg.flags = newtg->flags; vnewtg.maxperident = newtg->maxperident; vnewtg.maxusage = newtg->maxusage; vnewtg.expires = newtg->expires; vnewtg.lastseen = newtg->lastseen; vnewtg.lastmaxusereset = newtg->lastmaxusereset; memcpy(oldtg, &vnewtg, sizeof(trustgroup)); return 1; }
void _init(void) { const char **p; array *servicemasks; controlnum[0] = '\0'; cmds = newcommandtree(); if(!cmds) return; registerhook(HOOK_NICK_MASKPRIVMSG, &handlemaskprivmsg); registerhook(HOOK_CONTROL_REGISTERED, &handlecontrolregistered); array_init(&defaultservicemasks_a, sizeof(sstring *)); for(p=DEFAULT_SERVICE_MASKS;*p;p++) { int i = array_getfreeslot(&defaultservicemasks_a); defaultservicemasks = (sstring **)defaultservicemasks_a.content; defaultservicemasks[i] = getsstring(*p, strlen(*p)); } servicemasks = getconfigitems("xsb", "servicemask"); if(!servicemasks || !servicemasks->cursi) Error("xsb", ERR_WARNING, "No service masks in config file (xsb/servicemask), using defaults."); }
static int pc_join(char *name) { patrolchannel *pc = NULL; channel *cp; for (pc = patrolchannels; pc; pc = pc->next) if (ircd_strcmp(pc->channel->content, name) == 0) return 0; cp = findchannel(name); if (!cp) return -1; pc = malloc(sizeof(patrolchannel)); pc->channel = getsstring(name, 512); pc->nick = NULL; pc->next = patrolchannels; patrolchannels = pc; pc_check(); return 0; }
void _init() { lua_setupdebugsocket(); lua_initnickpusher(); lua_initchanpusher(); dummy.name = getsstring("???", 10); if(!dummy.name) { Error("lua", ERR_ERROR, "Cannot set dummy name."); return; } cpath = getcopyconfigitem("lua", "scriptdir", "", 500); if(!cpath || !cpath->content || !cpath->content[0]) { Error("lua", ERR_ERROR, "Error loading path."); return; } suffix = getcopyconfigitem("lua", "scriptsuffix", ".lua", 10); if(!suffix) { Error("lua", ERR_ERROR, "Error loading suffix."); return; } lua_setpath(); loaded = 1; startsched = scheduleoneshot(time(NULL) + 1, &lua_startup, NULL); }
hticket *hticket_add(const char *authname, time_t expiration, struct hchannel_struct *hchan, const char *message) { hticket *tmp = hticket_get(authname, hchan), **ptr; if (hchan == NULL) return NULL; if (tmp != NULL) return tmp; tmp = (hticket*)malloc(sizeof(struct hticket_struct)); strcpy(tmp->authname, authname); tmp->time_expiration = expiration; if (message == NULL) tmp->message = NULL; else tmp->message = getsstring(message, strlen(message)); /* find the correct position */ for (ptr = &hchan->htickets;*ptr && (*ptr)->time_expiration >= expiration;ptr = &(*ptr)->next); tmp->next = *ptr; *ptr = tmp; return tmp; }
int handletopicmsg(void *source, int cargc, char **cargv) { channel *cp; nick *np; void *harg[2]; time_t topictime=0, timestamp=0; if (cargc<2) { return CMD_OK; } if (cargc>2) topictime=strtol(cargv[cargc-2], NULL, 10); if (cargc>3) timestamp=strtol(cargv[cargc-3], NULL, 10); np=getnickbynumericstr((char *)source); /* The following check removed because servers can set topics.. */ #if 0 if (np==NULL) { /* We should check the sender exists, but we still change the topic even if it doesn't */ Error("channel",ERR_WARNING,"Topic change by non-existent user %s",(char *)source); } #endif /* Grab channel pointer */ if ((cp=findchannel(cargv[0]))==NULL) { /* We're not going to create a channel for the sake of a topic.. */ return CMD_OK; } else { if (timestamp && (cp->timestamp < timestamp)) { /* Ignore topic change for younger channel * (note that topic change for OLDER channel should be impossible!) */ return CMD_OK; } if (topictime && (cp->topictime > topictime)) { /* Ignore topic change with older topic */ return CMD_OK; } if (cp->topic!=NULL) { freesstring(cp->topic); } if (cargv[cargc-1][0]=='\0') { cp->topic=NULL; cp->topictime=0; } else { cp->topic=getsstring(cargv[cargc-1],TOPICLEN); cp->topictime=topictime?topictime:getnettime(); } /* Trigger hook */ harg[0]=cp; harg[1]=np; triggerhook(HOOK_CHANNEL_TOPIC,harg); } return CMD_OK; }
int csa_dosetemail(void *source, int cargc, char **cargv) { char *email; char *error; reguser *rup; nick *sender=(nick *)source; if(cargc<3) { controlreply(sender, "SETEMAIL FALSE args"); return CMD_ERROR; } rup = findreguserbyID(atoi(cargv[0])); if(rup == NULL) { controlreply(sender, "SETEMAIL FALSE useridnotexist"); return CMD_ERROR; } if(UHasStaffPriv(rup)) { controlreply(sender, "SETEMAIL FALSE privuser"); return CMD_ERROR; } if(UHasSuspension(rup)) { controlreply(sender, "SETEMAIL FALSE suspended"); return CMD_ERROR; } if(rup->lastpasschange > atoi(cargv[1])) { controlreply(sender, "SETEMAIL FALSE passwordchanged"); return CMD_ERROR; } email = cargv[2]; if(!strcmp(email, rup->email->content)) { /* setting to the same thing? fine! */ controlreply(sender, "SETEMAIL TRUE"); return CMD_OK; } error = email_to_error(email); if(error) { controlreply(sender, "SETEMAIL FALSE %s", error); return CMD_ERROR; } freesstring(rup->email); rup->email=getsstring(email,EMAILLEN); cs_log(sender,"SETEMAIL OK username %s email %s",rup->username, rup->email->content); csdb_updateuser(rup); sendemail(rup); controlreply(sender, "SETEMAIL TRUE"); return CMD_OK; }
/* ast parser, the way we pass context around is very very hacky... */ searchNode *search_astparse(searchCtx *ctx, char *loc) { searchASTCache *cache = ctx->arg; searchASTExpr *expr = cachesearch(cache, (exprunion *)&loc); searchNode *node; char **v; int i; if(!expr) { parseError = "WARNING: AST parsing failed"; return NULL; } switch(expr->type) { case AST_NODE_LITERAL: if (!(node=(searchNode *)malloc(sizeof(searchNode)))) { parseError = "malloc: could not allocate memory for this search."; return NULL; } node->localdata = getsstring(expr->u.literal,512); node->returntype = RETURNTYPE_CONST | RETURNTYPE_STRING; node->exe = literal_exe; node->free = literal_free; return node; case AST_NODE_CHILD: v = (char **)malloc(expr->u.child.argc * sizeof(char *)); if(!v) { parseError = "malloc: could not allocate memory for this search."; return NULL; } for(i=0;i<expr->u.child.argc;i++) { searchASTExpr *child = &expr->u.child.argv[i]; cachepush(cache, child); switch(child->type) { case AST_NODE_LITERAL: v[i] = child->u.literal; break; case AST_NODE_CHILD: v[i] = (char *)child; break; default: parseError = "static_parse: bad child node type"; free(v); return NULL; } } node = expr->u.child.fn(ctx, expr->u.child.argc, v); free(v); return node; default: parseError = "static_parse: bad node type"; return NULL; } }
void safereload(char *themodule) { if (safereload_str) freesstring(safereload_str); safereload_str=getsstring(themodule, 100); if (safereload_sched) deleteschedule(safereload_sched, safereloadcallback, NULL); scheduleoneshot(1, safereloadcallback, NULL); }
void sp_addsplit(const char *name, time_t ts, flag_t type) { int slot; splitserver *srv; slot = array_getfreeslot(&splitlist); srv = &(((splitserver*)splitlist.content)[slot]); srv->name = getsstring(name, HOSTLEN); srv->ts = ts; srv->type = type; }
hchanban *hchanban_add(hchannel* hchan, const char* banmask, time_t expiration) { hchanban *tmp = (hchanban*)malloc(sizeof(hchanban)); tmp->hchan = hchan; tmp->banmask = getsstring(banmask, strlen(banmask)); tmp->expiration = expiration; tmp->next = hchanbans; hchanbans = tmp; return hchanbans; }
hcensor *hcensor_add(hcensor **hcens, const char *pat, const char *rsn, hcensor_type type) { hcensor *tmp; if (hcensor_get_by_pattern(*hcens, pat)) return NULL; tmp = malloc(sizeof(hcensor)); tmp->next = *hcens; tmp->pattern = getsstring(pat, strlen(pat)); tmp->type = type; if (rsn) tmp->reason = getsstring(rsn, strlen(rsn)); else tmp->reason = NULL; *hcens = tmp; return tmp; }
struct service_node *register_service(char *name) { struct service_node *np = ntmalloc(sizeof(service_node)); MemCheckR(np, NULL); np->name = getsstring(name, strlen(name)); if(!np->name) { MemError(); ntfree(np); return NULL; } np->handlers = NULL; np->next = tree; tree = np; return np; }
hban *hban_add(const char* pat, const char* rsn, time_t exp, int now) { hban *ptr; chanban *tmp; if (hban_get(pat) || exp <= time(NULL)) return NULL; if ((tmp = makeban(pat)) == NULL) /* bad ban */ return NULL; ptr = (hban*)malloc(sizeof(hban)); ptr->real_ban = tmp; ptr->expiration = exp; if (rsn == NULL) ptr->reason = NULL; else ptr->reason = getsstring(rsn, strlen(rsn)); ptr->next = hbans; hbans = ptr; { /* additional logic here */ huser* tmpu; for (tmpu = husers;tmpu;tmpu = tmpu->next) if (nickmatchban(tmpu->real_user, tmp, 0) && !IsOper(tmpu->real_user)) { hchannel *assert_hchan = NULL; while (tmpu->hchannels) { if (tmpu->hchannels->hchan == assert_hchan) { Error("helpmod", ERR_ERROR, "hban.c hban_add() current channel is the previous channel. Preventing lockup."); break; } assert_hchan = tmpu->hchannels->hchan; helpmod_setban(tmpu->hchannels->hchan, bantostring(ptr->real_ban), HELPMOD_BAN_DURATION, MCB_ADD, now); helpmod_kick(tmpu->hchannels->hchan, tmpu, "%s", hban_get_reason(ptr)); } } } return ptr; }
static sstring *combinesecret(char *str) { SHA256_CTX ctx; unsigned char digest[32]; char hexbuf[sizeof(digest) * 2 + 1]; SHA256_Init(&ctx); SHA256_Update(&ctx, (unsigned char *)secret->content, secret->length); SHA256_Update(&ctx, (unsigned char *)":", 1); SHA256_Update(&ctx, (unsigned char *)str, strlen(str)); SHA256_Final(digest, &ctx); SHA256_Init(&ctx); SHA256_Update(&ctx, digest, sizeof(digest)); SHA256_Final(digest, &ctx); hmac_printhex(digest, hexbuf, sizeof(digest)); return getsstring(hexbuf, strlen(hexbuf)); }
realname *findorcreaterealname(const char *name) { realname *rnp; unsigned int thehash=realnamehash(name); for (rnp=realnametable[thehash];rnp;rnp=(realname *)rnp->next) if (!strcmp(name,rnp->name->content)) { rnp->usercount++; return rnp; } rnp=newrealname(); rnp->name=getsstring(name,REALLEN); rnp->usercount=1; rnp->marker=0; rnp->nicks=NULL; rnp->next=(struct realname *)realnametable[thehash]; realnametable[thehash]=rnp; return rnp; }
host *findorcreatehost(const char *hostname) { host *hp; unsigned long thehash=hosthash(hostname); for (hp=hosttable[thehash];hp;hp=(host *)hp->next) if (!ircd_strcmp(hostname,hp->name->content)) { hp->clonecount++; return hp; } hp=newhost(); hp->name=getsstring(hostname,HOSTLEN); hp->clonecount=1; hp->marker=0; hp->nicks=NULL; hp->next=(struct host *)hosttable[thehash]; hosttable[thehash]=hp; return hp; }
struct handler *register_handler(struct service_node *service, char *command, int args, handler_function fp) { struct handler *hp = ntmalloc(sizeof(handler)); MemCheckR(hp, NULL); hp->command = getsstring(command, strlen(command)); if(!hp->command) { MemError(); ntfree(hp); return NULL; } hp->function = fp; hp->args = args; hp->next = service->handlers; hp->service = service; service->handlers = hp; return hp; }
int csa_dosettempemail(void *source, int cargc, char **cargv) { char *email; char *error; reguser *rup; nick *sender=(nick *)source; if(cargc<2) { controlreply(sender, "SETTEMPEMAIL FALSE args"); return CMD_ERROR; } rup = findreguserbyID(atoi(cargv[0])); if(rup == NULL) { controlreply(sender, "SETTEMPEMAIL FALSE useridnotexist"); return CMD_ERROR; } if(!UIsInactive(rup)) { controlreply(sender, "SETTEMPEMAIL FALSE accountactive"); return CMD_ERROR; } email = cargv[1]; error = email_to_error(email); if(error) { controlreply(sender, "SETTEMPEMAIL FALSE %s", error); return CMD_ERROR; } freesstring(rup->email); rup->email=getsstring(email,EMAILLEN); cs_log(sender,"SETTEMPEMAIL OK username %s email %s",rup->username, rup->email->content); csdb_updateuser(rup); sendemail(rup); controlreply(sender, "SETTEMPEMAIL TRUE"); return CMD_OK; }
void chanservcryptoinit(void) { int ret; FILE *e = fopen(ENTROPYSOURCE, "rb"); if(!e) { Error("chanserv",ERR_STOP,"Unable to open entropy source."); /* shouldn't be running now... */ } ret = fread(rng.randrsl, 1, sizeof(rng.randrsl), e); fclose(e); if(ret != sizeof(rng.randrsl)) { Error("chanserv",ERR_STOP,"Unable to read entropy."); /* shouldn't be running now... */ } prnginit(&rng, 1); secret=getcopyconfigitem("chanserv","secret","",128); if(!secret || !secret->content || !secret->content[0]) { unsigned char buf[32]; char hexbuf[sizeof(buf) * 2 + 1]; freesstring(secret); Error("chanserv",ERR_WARNING,"Shared secret not set, generating a random string..."); cs_getrandbytes(buf, 32); hmac_printhex(buf, hexbuf, sizeof(buf)); secret=getsstring(hexbuf, strlen(hexbuf)); } codesecret=combinesecret("codegenerator"); ticketsecret=getcopyconfigitem("chanserv","ticketsecret","",256); if(!ticketsecret || !ticketsecret->content[0]) { Error("chanserv",ERR_WARNING,"Ticket secret not set, ticketauth disabled."); freesstring(ticketsecret); ticketsecret = NULL; } }
int spcmd_splitadd(void *source, int cargc, char **cargv) { nick *np = (nick*)source; unsigned long long num; char *end; flag_t servertype = 0; char *servername; size_t servernamelen; time_t splittime; server fake; if (cargc < 1) { controlreply(np, "Usage: splitadd <servername> [+flags] [split time as unix timestamp]"); return CMD_ERROR; } servername = cargv[0]; servernamelen = strlen(servername); if (findserver(servername) != -1) { controlreply(np, "Server %s is linked right now, refusing to add split.", servername); return CMD_ERROR; } if (doessplitalreadyexist(servername)) { controlreply(np, "There is a split for %s already.", servername); return CMD_ERROR; } if (servernamelen > SERVERLEN) { controlreply(np, "Server name %s is too long (max: %d characters)", servername, SERVERLEN); return CMD_ERROR; } /* Handle flags */ if (cargc > 1) { if (setflags(&servertype, (flag_t)-1, cargv[1], servertypeflags, REJECT_UNKNOWN) != REJECT_NONE) { controlreply(np, "Flag string %s contained invalid flags.", cargv[1]); return CMD_ERROR; } } else { /* Set up a fake server for getservertype. */ memset(&fake, 0, sizeof(fake)); fake.name = getsstring(servername, servernamelen); servertype = getservertype(&fake); freesstring(fake.name); } /* Handle timestamp */ if (cargc < 3) { splittime = getnettime(); } else { errno = 0; num = strtoull(cargv[2], &end, 10); if (errno == ERANGE) { controlreply(np, "%s is out of range for a timestamp.", cargv[2]); return CMD_ERROR; } /* Truncation may happen here. * However, there's no way to get the max time_t value, so we'll just try to * find out after the fact. */ splittime = (time_t)num; if ((unsigned long long)splittime < num) { controlreply(np, "Tried to use %llu as split time value, but it's too " "large for the system to handle", num); return CMD_ERROR; } } sp_addsplit(servername, splittime, servertype); controlreply(np, "Added split for %s (%s ago) with flags %s.", servername, longtoduration(getnettime() - splittime, 1), printflags(servertype, servertypeflags)); return CMD_OK; }
int helpmod_config_read_channel(FILE *in) { hchannel *hchan; char buf[256],*ptr=(char*)buf; int flags, entries, idlekick, i; /* name */ fgets(buf, 256, in); if (feof(in)) return -1; helpmod_line_fix(&ptr); hchan = hchannel_add(ptr); /* flags */ fgets((ptr = buf), 256, in); if (feof(in)) return -1; helpmod_line_fix(&ptr); if (sscanf(ptr, "%x", (unsigned int*)&flags) != 1) return -1; hchan->flags = flags; /* welcome message */ fgets((ptr = buf), 256, in); if (feof(in)) return -1; helpmod_line_fix(&ptr); strcpy(hchan->welcome, ptr); /* lamercontrol profile */ fgets((ptr = buf), 256, in); if (feof(in)) return -1; helpmod_line_fix(&ptr); hchan->lc_profile = hlc_get(ptr); if (hconf_version >= HELPMOD_VERSION_2_11) { fgets((ptr = buf), 256, in); if (feof(in)) return -1; helpmod_line_fix(&ptr); if (sscanf(ptr, "%d", &idlekick) != 1) return -1; hchan->max_idle = idlekick; fgets((ptr = buf), 256, in); if (feof(in)) return -1; helpmod_line_fix(&ptr); hchan->ticket_message = getsstring(ptr,strlen(ptr)); } /* censor entries for channel, a bit complex */ fgets((ptr = buf), 256, in); if (feof(in)) return -1; helpmod_line_fix(&ptr); if (sscanf(ptr, "%d", &entries) != 1) return -1; for (i = 0;i<entries;i++) { char buf2[512], *ptr2; int type; fgets((ptr = buf), 256, in); if (feof(in)) return -1; helpmod_line_fix(&ptr); if (hconf_version >= HELPMOD_VERSION_2_10) { if (!sscanf(ptr, "%d", &type)) return -1; fgets((ptr = buf), 256, in); if (feof(in)) return -1; helpmod_line_fix(&ptr); } else type = HCENSOR_KICK; fgets((ptr2 = buf2), 256, in); if (feof(in)) return -1; helpmod_line_fix(&ptr2); if (ptr2[0] == '\0') ptr2 = NULL; hcensor_add(&hchan->censor, ptr, ptr2, type); } /* channel specific hterms */ fgets((ptr = buf), 256, in); if (feof(in)) return -1; helpmod_line_fix(&ptr); if (sscanf(ptr, "%d", &entries) != 1) return -1; for (i=0;i<entries;i++) helpmod_config_read_term(in, &hchan->channel_hterms); helpmod_config_read_chanstats(in, hchan->stats); /* needs to be done here */ hchannel_mode_check(hchan); return 0; }
int load_permits(void) { int loaded_lines = 0, i, j; struct permitted *new_permits, *resized, *item; struct hostent *host; array *hostnamesa, *passwordsa; sstring **hostnames, **passwords; hostnamesa = getconfigitems("nterfacer", "hostname"); passwordsa = getconfigitems("nterfacer", "password"); if(!hostnamesa || !passwordsa) return 0; if(hostnamesa->cursi != passwordsa->cursi) { nterface_log(nrl, NL_ERROR, "Different number of hostnames/passwords in config file."); return 0; } hostnames = (sstring **)hostnamesa->content; passwords = (sstring **)passwordsa->content; new_permits = ntmalloc(hostnamesa->cursi * sizeof(struct permitted)); memset(new_permits, 0, hostnamesa->cursi * sizeof(struct permitted)); item = new_permits; for(i=0;i<hostnamesa->cursi;i++) { item->hostname = getsstring(hostnames[i]->content, hostnames[i]->length); host = gethostbyname(item->hostname->content); if (!host) { nterface_log(nrl, NL_WARNING, "Couldn't resolve hostname: %s (item %d).", item->hostname->content, i + 1); freesstring(item->hostname); continue; } item->ihost = (*(struct in_addr *)host->h_addr_list[0]).s_addr; for(j=0;j<loaded_lines;j++) { if(new_permits[j].ihost == item->ihost) { nterface_log(nrl, NL_WARNING, "Host with items %d and %d is identical, dropping item %d.", j + 1, i + 1, i + 1); host = NULL; } } if(!host) { freesstring(item->hostname); continue; } item->password = getsstring(passwords[i]->content, passwords[i]->length); nterface_log(nrl, NL_DEBUG, "Loaded permit, hostname: %s.", item->hostname->content); item++; loaded_lines++; } if(!loaded_lines) { ntfree(new_permits); return 0; } resized = ntrealloc(new_permits, sizeof(struct permitted) * loaded_lines); if(!resized) { MemError(); ntfree(new_permits); return 0; } permits = resized; permit_count = loaded_lines; return permit_count; }
int handleburstmsg(void *source, int cargc, char **cargv) { channel *cp; time_t timestamp; int wipeout=0; int i; int arg=0; char *charp; int newlimit; int waslimit,waskeyed; char *nextnum; unsigned long currentmode; int isnewchan; /* (we don't see the first 2 params in cargc) */ /* AK B #+lod+ 1017561154 +tnk eits ATJWu:o,AiW1a,Ag3lV,AiWnl,AE6oI :%*[email protected] */ if (cargc<2) { Error("channel",ERR_WARNING,"Burst message with only %d parameters",cargc); return CMD_OK; } timestamp=strtol(cargv[1],NULL,10); if ((cp=findchannel(cargv[0]))==NULL) { /* We don't have this channel already */ cp=createchannel(cargv[0]); cp->timestamp=timestamp; isnewchan=1; } else { isnewchan=0; if (timestamp<cp->timestamp) { /* The incoming timestamp is older. Erase all our current channel modes, and the topic. */ cp->timestamp=timestamp; freesstring(cp->topic); cp->topic=NULL; cp->topictime=0; freesstring(cp->key); cp->key=NULL; cp->limit=0; cp->flags=0; clearallbans(cp); /* Remove all +v, +o we currently have */ for(i=0;i<cp->users->hashsize;i++) { if (cp->users->content[i]!=nouser) { cp->users->content[i]&=CU_NUMERICMASK; } } } else if (timestamp>cp->timestamp) { /* The incoming timestamp is greater. Ignore any incoming modes they may happen to set */ wipeout=1; } } /* OK, dealt with the name and timestamp. * Loop over the remaining args */ for (arg=2;arg<cargc;arg++) { if (cargv[arg][0]=='+') { /* Channel modes */ if (wipeout) { /* We ignore the modes, but we need to see if they include +l or +k * so that we can ignore their corresponding values */ for (charp=cargv[arg];*charp;charp++) { if (*charp=='k' || *charp=='l') { arg++; } } } else { /* Clear off the limit and key flags before calling setflags so we can see if the burst tried to set them */ /* If the burst doesn't set them, we restore them afterwards */ waslimit=IsLimit(cp); ClearLimit(cp); waskeyed=IsKey(cp); ClearKey(cp); /* We can then use the flag function for these modes */ setflags(&(cp->flags),CHANMODE_ALL,cargv[arg],cmodeflags,REJECT_NONE); /* Pick up the limit and key, if they were set. Note that the limit comes first */ if (IsLimit(cp)) { /* A limit was SET by the burst */ if (++arg>=cargc) { /* Ran out of args -- damn ircd is spewing out crap again */ Error("channel",ERR_WARNING,"Burst +l with no argument"); break; /* "break" being the operative word */ } else { newlimit=strtol(cargv[arg],NULL,10); } if (cp->limit>0 && waslimit) { /* We had a limit before -- we now have the lowest one of the two */ if (newlimit<cp->limit) { cp->limit=newlimit; } } else { /* No limit before -- we just have the new one */ cp->limit=newlimit; } } else if (waslimit) { SetLimit(cp); /* We had a limit before, but the burst didn't set one. Restore flag. */ } if (IsKey(cp)) { /* A key was SET by the burst */ if (++arg>=cargc) { /* Ran out of args -- oopsie! */ Error("channel",ERR_WARNING,"Burst +k with no argument"); break; } if (waskeyed) { /* We had a key before -- alphabetically first wins */ if (ircd_strcmp(cargv[arg],cp->key->content)<0) { /* Replace our key */ freesstring(cp->key); cp->key=getsstring(cargv[arg],KEYLEN); } } else { /* No key before -- just the new one */ cp->key=getsstring(cargv[arg],KEYLEN); } } else if (waskeyed) { SetKey(cp); /* We had a key before, but the burst didn't set one. Restore flag. */ } } } else if (cargv[arg][0]=='%') { /* We have one or more bans here */ nextnum=cargv[arg]+1; while (*nextnum) { /* Split off the next ban */ for (charp=nextnum;*charp;charp++) { if (*charp==' ') { *charp='\0'; charp++; break; } } setban(cp,nextnum); nextnum=charp; } } else { /* List of numerics */ nextnum=charp=cargv[arg]; currentmode=0; while (*nextnum!='\0') { /* Step over the next numeric */ for (i=0;i<5;i++) { if (*charp++=='\0') break; } if (i<5) { break; } if (*charp==',') { *charp='\0'; charp++; } else if (*charp==':') { *charp='\0'; charp++; currentmode=0; /* Look for modes */ for (;*charp;charp++) { if (*charp=='v') { currentmode|=CUMODE_VOICE; } else if (*charp=='o') { currentmode|=CUMODE_OP; } else if (*charp==',') { charp++; break; } } /* If we're ignore incoming modes, zap it to zero again */ if (wipeout) { currentmode=0; } } /* OK. At this point charp points to either '\0' if we're at the end, * or the start of the next numeric otherwise. nextnum points at a valid numeric * we need to add, and currentmode reflects the correct mode */ addnicktochannel(cp,(numerictolong(nextnum,5)|currentmode)); nextnum=charp; } } } if (cp->users->totalusers==0) { /* Oh dear, the channel is now empty. Perhaps one of those * charming empty burst messages you get sometimes.. */ if (!isnewchan) { /* I really don't think this can happen, can it..? */ /* Only send the LOSTCHANNEL if the channel existed before */ triggerhook(HOOK_CHANNEL_LOSTCHANNEL,cp); } delchannel(cp); } else { /* If this is a new channel, we do the NEWCHANNEL hook also */ if (isnewchan) { triggerhook(HOOK_CHANNEL_NEWCHANNEL,cp); } /* Just one hook to say "something happened to this channel" */ triggerhook(HOOK_CHANNEL_BURST,cp); } return CMD_OK; }
int handlemodemsg(void *source, int cargc, char **cargv) { channel *cp; int dir=1; int arg=2; char *modestr; unsigned long *lp; void *harg[4]; nick *np, *target; int hooknum; int changes=0; if (cargc<2) { return CMD_OK; } if (cargv[0][0]!='#' && cargv[0][0]!='+') { /* Not a channel, ignore */ return CMD_OK; } if ((cp=findchannel(cargv[0]))==NULL) { /* No channel, abort */ Error("channel",ERR_WARNING,"Mode change on non-existent channel %s",cargv[0]); return CMD_OK; } if (((char *)source)[2]=='\0') { /* Server mode change, treat as divine intervention */ np=NULL; } else if ((np=getnickbynumericstr((char *)source))==NULL) { /* No sender, continue but moan */ Error("channel",ERR_WARNING,"Mode change by non-existent user %s on channel %s",(char *)source,cp->index->name->content); } /* Set up the hook data */ harg[0]=cp; harg[1]=np; harg[3]=(void *)(long)(cp->flags); /* Process the mode string one character at a time */ /* Maybe I'll write this more intelligently one day if I can comprehend the ircu code that does this */ for (modestr=cargv[1];*modestr;modestr++) { switch(*modestr) { /* Set whether we are adding or removing modes */ case '+': dir=1; break; case '-': dir=0; break; /* Simple modes: just set or clear based on value of dir */ case 'n': if (dir) { SetNoExtMsg(cp); } else { ClearNoExtMsg(cp); } changes |= MODECHANGE_MODES; break; case 't': if (dir) { SetTopicLimit(cp); } else { ClearTopicLimit(cp); } changes |= MODECHANGE_MODES; break; case 's': if (dir) { SetSecret(cp); ClearPrivate(cp); } else { ClearSecret(cp); } changes |= MODECHANGE_MODES; break; case 'p': if (dir) { SetPrivate(cp); ClearSecret(cp); } else { ClearPrivate(cp); } changes |= MODECHANGE_MODES; break; case 'i': if (dir) { SetInviteOnly(cp); } else { ClearInviteOnly(cp); } changes |= MODECHANGE_MODES; break; case 'm': if (dir) { SetModerated(cp); } else { ClearModerated(cp); } changes |= MODECHANGE_MODES; break; case 'c': if (dir) { SetNoColour(cp); } else { ClearNoColour(cp); } changes |= MODECHANGE_MODES; break; case 'C': if (dir) { SetNoCTCP(cp); } else { ClearNoCTCP(cp); } changes |= MODECHANGE_MODES; break; case 'r': if (dir) { SetRegOnly(cp); } else { ClearRegOnly(cp); } changes |= MODECHANGE_MODES; break; case 'D': if (dir) { SetDelJoins(cp); } else { ClearDelJoins(cp); } changes |= MODECHANGE_MODES; break; case 'u': if (dir) { SetNoQuitMsg(cp); } else { ClearNoQuitMsg(cp); } changes |= MODECHANGE_MODES; break; case 'N': if (dir) { SetNoNotice(cp); } else { ClearNoNotice(cp); } changes |= MODECHANGE_MODES; break; case 'M': if (dir) { SetModNoAuth(cp); } else { ClearModNoAuth(cp); } changes |= MODECHANGE_MODES; break; case 'T': if (dir) { SetSingleTarg(cp); } else { ClearSingleTarg(cp); } changes |= MODECHANGE_MODES; break; /* Parameter modes: advance parameter and possibly read it in */ case 'l': if (dir) { /* +l uses a parameter, but -l does not. * If there is no parameter, don't set the mode. * I guess we should moan too in that case, but * they might be even nastier to us if we do ;) */ if (arg<cargc) { cp->limit=strtol(cargv[arg++],NULL,10); SetLimit(cp); } } else { ClearLimit(cp); cp->limit=0; } changes |= MODECHANGE_MODES; break; case 'k': if (dir) { /* +k uses a parameter in both directions */ if (arg<cargc) { freesstring(cp->key); /* It's probably NULL, but be safe */ cp->key=getsstring(cargv[arg++],KEYLEN); SetKey(cp); } } else { freesstring(cp->key); cp->key=NULL; ClearKey(cp); arg++; /* Eat the arg without looking at it, even if it's not there */ } changes |= MODECHANGE_MODES; break; /* Op/Voice */ case 'o': case 'v': if (arg<cargc) { if((lp=getnumerichandlefromchanhash(cp->users,numerictolong(cargv[arg++],5)))==NULL) { /* They're not on the channel; MODE crossed with part/kill/kick/blah */ Error("channel",ERR_DEBUG,"Mode change for user %s not on channel %s",cargv[arg-1],cp->index->name->content); } else { if ((target=getnickbynumeric(*lp))==NULL) { /* This really is a fuckup, we found them on the channel but there isn't a user with that numeric */ /* This means there's a serious bug in the nick/channel tracking code */ Error("channel",ERR_ERROR,"Mode change for user %s on channel %s who doesn't exist",cargv[arg-1],cp->index->name->content); } else { /* Do the mode change whilst admiring the beautiful code layout */ harg[2]=target; if (*modestr=='o') { if (dir) { *lp |= CUMODE_OP; hooknum=HOOK_CHANNEL_OPPED; } else { *lp &= ~CUMODE_OP; hooknum=HOOK_CHANNEL_DEOPPED; } } else { if (dir) { *lp |= CUMODE_VOICE; hooknum=HOOK_CHANNEL_VOICED; } else { *lp &= ~CUMODE_VOICE; hooknum=HOOK_CHANNEL_DEVOICED; } } triggerhook(hooknum,harg); } } } changes |= MODECHANGE_USERS; break; case 'b': if (arg<cargc) { if (dir) { setban(cp,cargv[arg++]); triggerhook(HOOK_CHANNEL_BANSET,harg); } else { clearban(cp,cargv[arg++],0); triggerhook(HOOK_CHANNEL_BANCLEAR,harg); } } changes |= MODECHANGE_BANS; break; default: Error("channel",ERR_DEBUG,"Unknown mode char '%c' %s on %s",*modestr,dir?"set":"cleared",cp->index->name->content); break; } } harg[2]=(void *)((long)changes); triggerhook(HOOK_CHANNEL_MODECHANGE,(void *)harg); return CMD_OK; }
lua_State *lua_loadscript(char *file) { char fullpath[LUA_PATHLEN]; int top; lua_State *l; lua_list *n; char buf[1024]; void *args[2]; if(!cpath || !suffix) return NULL; strlcpy(buf, file, sizeof(buf)); delchars(buf, "./\\;"); if(lua_scriptloaded(buf)) return NULL; l = lua_newstate(lua_nsmalloc, NULL); if(!l) return NULL; n = (lua_list *)luamalloc(sizeof(lua_list));; if(!n) { Error("lua", ERR_ERROR, "Error allocing list for %s.", buf); return NULL; } n->name = getsstring(buf, LUA_PATHLEN); if(!n->name) { Error("lua", ERR_ERROR, "Error allocing name item for %s.", buf); luafree(n); return NULL; } n->calls = 0; timerclear(&n->ru_utime); timerclear(&n->ru_stime); lua_loadlibs(l); lua_registerdebug(l); lua_registercommands(l); lua_registerlocalcommands(l); lua_registerdbcommands(l); lua_registersocketcommands(l); lua_registercryptocommands(l); lua_registerschedulercommands(l); args[0] = file; args[1] = l; triggerhook(HOOK_LUA_LOADSCRIPT, args); #ifdef LUA_USEJIT lua_require(l, "lib/jit"); #endif lua_require(l, "lib/bootstrap"); snprintf(fullpath, sizeof(fullpath), "%s/%s%s", cpath->content, file, suffix->content); if(luaL_loadfile(l, fullpath)) { Error("lua", ERR_ERROR, "Error loading %s.", file); lua_close(l); freesstring(n->name); luafree(n); return NULL; } n->l = l; n->next = NULL; n->prev = lua_tail; n->nicks = NULL; n->sockets = NULL; n->schedulers = NULL; if(!lua_head) { lua_head = n; } else { lua_tail->next = n; } lua_tail = n; top = lua_gettop(l); if(lua_pcall(l, 0, 0, 0)) { Error("lua", ERR_ERROR, "Error pcalling: %s.", file); lua_close(l); freesstring(n->name); if(lua_head == n) lua_head = NULL; lua_tail = n->prev; if(lua_tail) lua_tail->next = NULL; luafree(n); return NULL; } lua_settop(l, top); Error("lua", ERR_INFO, "Loaded %s.", file); lua_onload(l); return l; }
int patrol_generatepool(void) { int i, k = 0, j = 0, loops = 0; char *p, *pp; nick *np; for (i = 0; i < NICKHASHSIZE; i++) for (np = nicktable[i]; np; np = np->next) j++; if (j < patrol_min_hosts) return 0; if (PATROL_HOST_MODE == PATROL_STEAL_HOST) return PATROL_MINPOOLSIZE; i = 0; do { for (j = patrol_minmaxrand(0, NICKHASHSIZE - 1); j < NICKHASHSIZE; j++) { if (nicktable[j]) { for (p = nicktable[j]->host->name->content, pp = p; *p;) { if (*++p == '.') { if (!patrol_is_not_octet(pp, p - pp)) { if (i < PATROL_POOLSIZE) { if (i < patrol_hostpoolsize) freesstring(patrol_hostpool[i]); patrol_hostpool[i] = getsstring(pp, p - pp); i++; } else { if (k >= PATROL_POOLSIZE) break; } } pp = ++p; } } if (!patrol_is_not_octet(pp, p - pp)) { if (k < PATROL_POOLSIZE) { if (k < patrol_tailpoolsize) freesstring(patrol_tailpool[k]); patrol_tailpool[k] = getsstring(pp, p - pp); k++; } else { if (i >= PATROL_POOLSIZE) break; } } } } loops++; } while ((loops < 5) && ((i < PATROL_POOLSIZE) || (k < PATROL_POOLSIZE))); patrol_hostpoolsize = i; patrol_tailpoolsize = k; return i; }
int insmod(char *modulename) { int i; module *mods; char buf[1024], modulebuf[1024]; const char *(*verinfo)(const char **); struct module_dep *mdp; strlcpy(modulebuf, modulename, sizeof(modulebuf)); delchars(modulebuf,"./\\;"); if (isloaded(modulebuf)) { Error("core",ERR_DEBUG,"Tried to load already loaded module: %s",modulebuf); return 1; } if (strlen(modulebuf)>100) { Error("core",ERR_WARNING,"Module name too long: %s",modulebuf); return 1; } if ((mdp=getmoduledep(modulebuf))) { for (i=0;i<mdp->numparents;i++) { if (!isloaded(mdp->parents[i]->name->content)) { if (insmod(mdp->parents[i]->name->content)) { Error("core",ERR_WARNING,"Error loading dependant module %s (needed by %s)", mdp->parents[i]->name->content,modulebuf); return 1; } } } } else { Error("core",ERR_WARNING,"Loading module %s without dependency information.",modulebuf); } i=array_getfreeslot(&modules); mods=(module *)(modules.content); sprintf(buf,"%s/%s%s",moddir->content,modulebuf,modsuffix->content); mods[i].handle=dlopen(buf,RTLD_NOW|RTLD_GLOBAL); if(mods[i].handle==NULL) { Error("core",ERR_ERROR,"Loading module %s failed: %s",modulebuf,dlerror()); array_delslot(&modules,i); return -1; } mods[i].name=getsstring(modulebuf,MODULENAMELEN); verinfo=dlsym(mods[i].handle,"_version"); if(verinfo) { mods[i].buildid=verinfo(&mods[i].version); } else { mods[i].version=NULL; mods[i].buildid=NULL; } mods[i].loadedsince = time(NULL); Error("core",ERR_INFO,"Loaded module %s OK.",modulebuf); return 0; }
/* Populate the dependency array. Read the monster description above for details. * This relies on moddir being set, so call this after setting it up. */ void initmoduledeps() { FILE *fp; char buf[1024]; char *largv[100]; char largc; char *ch; struct module_dep *mdp, *tmdp; unsigned int i,j; sprintf(buf,"%s/%s",moddir->content,DEPFILE); if (!(fp=fopen(buf,"r"))) { Error("core",ERR_WARNING,"Unable to open module dependency file: %s",buf); } else { /* First pass */ while (!feof(fp)) { fgets(buf, sizeof(buf), fp); if (feof(fp)) break; /* Chomp off that ruddy newline. */ for (ch=buf;*ch;ch++) { if (*ch=='\n' || *ch=='\r') { *ch='\0'; break; } } /* We have a space-delimited list of things. Whatever will we do with that? :) */ largc=splitline(buf,largv,100,0); if (largc<1) continue; /* Add us to the array */ i=knownmodules++; if (i>=MAXMODULES) { Error("core",ERR_ERROR, "Too many modules in dependency file; rebuild with higher MAXMODULES. Module dependencies disabled.\n"); clearmoduledeps(); fclose(fp); return; } mdp=&(moduledeps[i]); mdp->name=getsstring(largv[0],100); mdp->numparents=largc-1; mdp->numchildren=0; /* peace, for now */ mdp->parents=malloc(mdp->numparents * sizeof(struct module_dep *)); /* Fill in the parents array */ for (i=0;i<(largc-1);i++) { if (!(mdp->parents[i]=getmoduledep(largv[i+1]))) { Error("core",ERR_WARNING,"Couldn't find parent module %s of %s. Module dependencies disabled.", largv[i+1],largv[0]); clearmoduledeps(); fclose(fp); return; } mdp->parents[i]->numchildren++; /* break the bad news */ } } fclose(fp); /* Second pass */ for (i=0;i<knownmodules;i++) { mdp=&(moduledeps[i]); /* Allocate child array */ if (mdp->numchildren) { mdp->children=malloc(mdp->numchildren * sizeof(struct module_dep *)); mdp->numchildren=0; /* if only real life were this simple */ } /* Now fill in the children arrays of our parents (bear with me on this) */ for (j=0;j<mdp->numparents;j++) { tmdp=mdp->parents[j]; /* This is just... */ tmdp->children[tmdp->numchildren++]=mdp; /* ... to give this line a chance at making sense */ } } } }