Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
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;
}
Exemplo n.º 3
0
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.");
}
Exemplo n.º 4
0
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;
}
Exemplo n.º 5
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);
}
Exemplo n.º 6
0
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;
}
Exemplo n.º 7
0
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;
}
Exemplo n.º 9
0
/* 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;
  }
}
Exemplo n.º 10
0
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);
}
Exemplo n.º 11
0
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;
}
Exemplo n.º 12
0
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;
}
Exemplo n.º 13
0
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;
}
Exemplo n.º 14
0
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;
}
Exemplo n.º 15
0
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;
}
Exemplo n.º 16
0
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));
}
Exemplo n.º 17
0
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;
}
Exemplo n.º 18
0
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;
}
Exemplo n.º 19
0
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;
}
Exemplo n.º 20
0
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;
}
Exemplo n.º 21
0
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;
  }
}
Exemplo n.º 22
0
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;
}
Exemplo n.º 23
0
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;
}
Exemplo n.º 24
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;
}
Exemplo n.º 25
0
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;     
}
Exemplo n.º 26
0
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;
}
Exemplo n.º 27
0
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;
}
Exemplo n.º 28
0
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;
}
Exemplo n.º 29
0
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;
}
Exemplo n.º 30
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 */
      }
    }
  }
}