Esempio n. 1
0
/* (a courtesy info to help during connect bursts)
 * idle <bot> <sock> <#secs> [away msg]
 */
static void bot_idle(int idx, char *par)
{
  char *bot, *work;
  int sock, idle;

  if (bot_flags(dcc[idx].user) & BOT_ISOLATE)
    return;
  bot = newsplit(&par);
  work = newsplit(&par);
#ifndef NO_OLD_BOTNET
  if (dcc[idx].u.bot->numver < NEAT_BOTNET)
    sock = atoi(work);
  else
#endif
    sock = base64_to_int(work);
  if (sock == 0)
    sock = partysock(bot, work);
  work = newsplit(&par);
#ifndef NO_OLD_BOTNET
  if (dcc[idx].u.bot->numver < NEAT_BOTNET)
    idle = atoi(work);
  else
#endif
    idle = base64_to_int(work);
  partysetidle(bot, sock, idle);
  if (par[0]) {
    partystat(bot, sock, PLSTAT_AWAY, 0);
    partyaway(bot, sock, par);
  }
  botnet_send_idle(idx, bot, sock, idle, par);
}
Esempio n. 2
0
/* join <bot> <nick> <chan> <flag><sock> <from>
 */
static void bot_join(int idx, char *par)
{
  char *bot = NULL, *nick = NULL, *x = NULL, *y = NULL;
  struct userrec *u = NULL;
  int i, sock, chan, i2, linking = 0;

  bot = newsplit(&par);
  if (bot[0] == '!') {
    linking = 1;
    bot++;
  }
  if (b_status(idx) & STAT_LINKING) {
    linking = 1;
  }
  nick = newsplit(&par);
  x = newsplit(&par);
  chan = base64_to_int(x);
  y = newsplit(&par);
  if ((chan < 0) || !y[0])
    return;			/* Woops! pre 1.2.1's send .chat off'ers
				 * too!! */
  if (!y[0]) {
    y[0] = '-';
    sock = 0;
  } else {
    sock = base64_to_int(y + 1);
  }
  i = nextbot(bot);
  if (i != idx) {		/* Ok, garbage from a 1.0g (who uses that
				 * now?) OR raistlin being evil :) */
    fake_alert(idx, "direction", bot, "join");
    return;
  }
  u = get_user_by_handle(userlist, nick);
  if (u) {
    simple_snprintf(TBUF, sizeof(TBUF), "@%s", bot);
    touch_laston(u, TBUF, now);
  }
  i = addparty(bot, nick, chan, y[0], sock, par, &i2);
  botnet_send_join_party(idx, linking, i2);
  if (i != chan) {
    if (i >= 0) {
      chanout_but(-1, i, "*** (%s) %s %s %s.\n", conf.bot->hub ? bot : "[botnet]", nick, "has left the", i ? "channel" : "party line");
    }
    if (!linking)
    chanout_but(-1, chan, "*** (%s) %s %s %s.\n", conf.bot->hub ? bot : "[botnet]", nick, "has joined the", chan ? "channel" : "party line");
  }
}
Esempio n. 3
0
static void zapf_assoc(char *botnick, char *code, char *par)
{
  int idx = nextbot(botnick);
  char *s, *s1, *nick;
  int linking = 0, chan;

  if ((idx >= 0) && !(bot_flags(dcc[idx].user) & BOT_ISOLATE)) {
    if (!egg_strcasecmp(dcc[idx].nick, botnick))
      linking = b_status(idx) & STAT_LINKING;
    s = newsplit(&par);
    chan = base64_to_int(s);
    if ((chan > 0) || (chan < GLOBAL_CHANS)) {
      nick = newsplit(&par);
      s1 = get_assoc_name(chan);
      if (linking && ((s1 == NULL) || (s1[0] == 0) ||
          (((intptr_t) get_user(find_entry_type("BOTFL"),
          dcc[idx].user) & BOT_HUB)))) {
        add_assoc(par, chan);
        botnet_send_assoc(idx, chan, nick, par);
        chanout_but(-1, chan, ASSOC_CHNAME_NAMED, nick, par);
      } else if (par[0] == '0') {
        kill_assoc(chan);
        chanout_but(-1, chan, ASSOC_CHNAME_REM, botnick, nick);
      } else if (get_assoc(par) != chan) {
        /* New one i didn't know about -- pass it on */
        s1 = get_assoc_name(chan);
        add_assoc(par, chan);
        chanout_but(-1, chan, ASSOC_CHNAME_NAMED2, botnick, nick, par);
      }
    }
  }
}
Esempio n. 4
0
/* nc <bot> <sock> <newnick>
 */
static void bot_nickchange(int idx, char *par)
{
  char *bot, *ssock, *newnick;
  int sock, i;

  if (bot_flags(dcc[idx].user) & BOT_ISOLATE)
    return;
  bot = newsplit(&par);
#ifndef NO_OLD_BOTNET
  if (dcc[idx].u.bot->numver < NEAT_BOTNET) {
    fake_alert(idx, "botversion", "NEAT_BOTNET");
    return;
  }
#endif
  i = nextbot(bot);
  if (i != idx) {
    fake_alert(idx, "direction", bot);
    return;
  }
  ssock = newsplit(&par);
  sock = base64_to_int(ssock);
  newnick = newsplit(&par);
  i = partynick(bot, sock, newnick);
  if (i < 0) {
    fake_alert(idx, "sock#", ssock);
    return;
  }
  chanout_but(-1, party[i].chan, "*** (%s) Nick change: %s -> %s\n",
              bot, newnick, party[i].nick);
  botnet_send_nkch_part(idx, i, newnick);
}
Esempio n. 5
0
/* away <bot> <sock> <message>
 * null message = unaway
 */
static void bot_away(int idx, char *par)
{
  char *bot = NULL, *etc = NULL;
  int sock, partyidx, linking = 0;

  bot = newsplit(&par);
  if (bot[0] == '!') {
    linking = 1;
    bot++;
  }
  if (b_status(idx) & STAT_LINKING) {
    linking = 1;
  }
  etc = newsplit(&par);
  sock = base64_to_int(etc);
  if (par[0]) {
    partystat(bot, sock, PLSTAT_AWAY, 0);
    partyaway(bot, sock, par);
  } else {
    partystat(bot, sock, 0, PLSTAT_AWAY);
  }
  partyidx = getparty(bot, sock);
  if (!linking) {
    if (par[0])
      chanout_but(-1, party[partyidx].chan,
		  "*** (%s) %s %s: %s.\n", conf.bot->hub ? bot : "[botnet]",
		  party[partyidx].nick, "is now away", par);
    else
      chanout_but(-1, party[partyidx].chan,
		  "*** (%s) %s %s.\n", conf.bot->hub ? bot : "[botnet]",
		  party[partyidx].nick, "is no longer away");
  }
  botnet_send_away(idx, bot, sock, par, linking);
}
Esempio n. 6
0
/* who <from@bot> <tobot> <chan#>
 */
static void bot_who(int idx, char *par)
{
  char *from, *to, *p;
  int i, chan;

  from = newsplit(&par);
  p = strchr(from, '@');
  if (!p) {
    sprintf(TBUF, "%s@%s", from, dcc[idx].nick);
    from = TBUF;
  }
  to = newsplit(&par);
  if (!egg_strcasecmp(to, botnetnick))
    to[0] = 0;
#ifndef NO_OLD_BOTNET
  if (dcc[idx].u.bot->numver < NEAT_BOTNET)
    chan = atoi(par);
  else
#endif
    chan = base64_to_int(par);
  if (to[0]) {
    i = nextbot(to);
    if (i >= 0)
      botnet_send_who(i, from, to, chan);
  } else
    remote_tell_who(idx, from, chan);
}
Esempio n. 7
0
/* (a courtesy info to help during connect bursts)
 * idle <bot> <sock> <#secs> [away msg]
 */
static void bot_idle(int idx, char *par)
{
  char *bot = NULL, *work = NULL;
  int sock, idle;

  bot = newsplit(&par);
  work = newsplit(&par);
  sock = base64_to_int(work);
  work = newsplit(&par);
  idle = base64_to_int(work);
  partysetidle(bot, sock, idle);
  if (par[0]) {
    partystat(bot, sock, PLSTAT_AWAY, 0);
    partyaway(bot, sock, par);
  }
  botnet_send_idle(idx, bot, sock, idle, par);
}
Esempio n. 8
0
/* chan <from> <chan> <text>
 */
static void bot_chan2(int idx, char *msg)
{
  char *from, *p;
  int i, chan;

  if (bot_flags(dcc[idx].user) & BOT_ISOLATE)
    return;
  from = newsplit(&msg);
  p = newsplit(&msg);
#ifndef NO_OLD_BOTNET
  if (dcc[idx].u.bot->numver < NEAT_BOTNET)
    chan = atoi(p);
  else
#endif
    chan = base64_to_int(p);
  /* Strip annoying control chars */
  for (p = from; *p;) {
    if ((*p < 32) || (*p == 127))
      strcpy(p, p + 1);
    else
      p++;
  }
  p = strchr(from, '@');
  if (p) {
    sprintf(TBUF, "<%s> %s", from, msg);
    *p = 0;
    if (!partyidle(p + 1, from)) {
      *p = '@';
      fake_alert(idx, "user", from);
      return;
    }
    *p = '@';
    p++;
  } else {
    sprintf(TBUF, "*** (%s) %s", from, msg);
    p = from;
  }
  i = nextbot(p);
  if (i != idx) {
    fake_alert(idx, "direction", p);
  } else {
    chanout_but(-1, chan, "%s\n", TBUF);
    /* Send to new version bots */
    if (i >= 0)
      botnet_send_chan(idx, from, NULL, chan, msg);
    if (strchr(from, '@') != NULL)
      check_tcl_chat(from, chan, msg);
    else
      check_tcl_bcst(from, chan, msg);
  }
}
Esempio n. 9
0
/* part <bot> <nick> <sock> [etc..]
 */
static void bot_part(int idx, char *par)
{
  char *bot = NULL, *nick = NULL, *etc = NULL;
  struct userrec *u = NULL;
  int sock, partyidx;
  int silent = 0;

  bot = newsplit(&par);
  if (bot[0] == '!') {
    silent = 1;
    bot++;
  }
  nick = newsplit(&par);
  etc = newsplit(&par);
  sock = base64_to_int(etc);

  u = get_user_by_handle(userlist, nick);
  if (u) {
    simple_snprintf(TBUF, sizeof(TBUF), "@%s", bot);
    touch_laston(u, TBUF, now);
  }
  if ((partyidx = getparty(bot, sock)) != -1) {
    if (!silent) {
      register int chan = party[partyidx].chan;

      if (par[0])
	chanout_but(-1, chan, "*** (%s) %s %s %s (%s).\n", conf.bot->hub ? bot : "[botnet]", nick,
		    "has left the",
		    chan ? "channel" : "party line", par);
      else
	chanout_but(-1, chan, "*** (%s) %s %s %s.\n", conf.bot->hub ? bot : "[botnet]", nick,
		    "has left the",
		    chan ? "channel" : "party line");
    }
    botnet_send_part_party(idx, partyidx, par, silent);
    remparty(bot, sock);
  }

  /* check if we have a remote idx for them */
  int i = 0;

  for (i = 0; i < dcc_total; i++) {
    /* This will potentially close all simul-idxs with matching nick, even though they may be connected multiple times
       but, it won't matter as a new will just be made as needed. */
    if (dcc[i].type && dcc[i].simul >= 0 && !strcasecmp(dcc[i].nick, nick)) {
        dcc[i].simul = -1;
        lostdcc(i);
    }
  }

}
Esempio n. 10
0
/* chan <from> <chan> <text>
 */
static void bot_chan2(int idx, char *msg)
{
  char *from = NULL, *p = NULL;
  int i, chan;

  from = newsplit(&msg);
  p = newsplit(&msg);
  chan = base64_to_int(p);
  /* Strip annoying control chars */
  for (p = from; *p;) {
    if ((*p < 32) || (*p == 127))
      memmove(p, p + 1, strlen(p));
    else
      p++;
  }
  p = strchr(from, '@');
  if (p) {
    if (!conf.bot->hub) { /* Need to strip out the hub nick */
      char *q = NULL, newfrom[HANDLEN + 9 + 1]; /* HANDLEN@[botnet] */
   
      strlcpy(newfrom, from, sizeof(newfrom));
      q = strchr(newfrom, '@');
      *q = 0;
      simple_snprintf(TBUF, sizeof(TBUF), "<%s@[botnet]> %s", newfrom, msg);
    } else
      simple_snprintf(TBUF, sizeof(TBUF), "<%s> %s", from, msg);
    *p = 0;
    if (!partyidle(p + 1, from)) {
      *p = '@';
      fake_alert(idx, "user", from, "chan2_i");
      return;
    }
    *p = '@';
    p++;
  } else {
    simple_snprintf(TBUF, sizeof(TBUF), "*** (%s) %s", from, msg);
    p = from;
  }
  i = nextbot(p);
  if (i != idx) {
    fake_alert(idx, "direction", p, "chan2_ii");
  } else {
    chanout_but(-1, chan, "%s\n", TBUF);
    /* Send to new version bots */
    if (i >= 0)
      botnet_send_chan(idx, from, NULL, chan, msg);
  }
}
Esempio n. 11
0
/* part <bot> <nick> <sock> [etc..]
 */
static void bot_part(int idx, char *par)
{
  char *bot, *nick, *etc;
  struct userrec *u;
  int sock, partyidx;
  int silent = 0;

  if (bot_flags(dcc[idx].user) & BOT_ISOLATE)
    return;
  bot = newsplit(&par);
  if (bot[0] == '!') {
    silent = 1;
    bot++;
  }
  nick = newsplit(&par);
  etc = newsplit(&par);
#ifndef NO_OLD_BOTNET
  if (dcc[idx].u.bot->numver < NEAT_BOTNET) {
    sock = atoi(etc);
    silent = 1;
  } else
#endif
    sock = base64_to_int(etc);
  if (sock == 0)
    sock = partysock(bot, nick);
  u = get_user_by_handle(userlist, nick);
  if (u) {
    sprintf(TBUF, "@%s", bot);
    touch_laston(u, TBUF, now);
  }
  if ((partyidx = getparty(bot, sock)) != -1) {
    if (party[partyidx].chan >= 0)
      check_tcl_chpt(bot, nick, sock, party[partyidx].chan);
    if ((dcc[idx].u.bot->numver >= NEAT_BOTNET) && !silent) {
      register int chan = party[partyidx].chan;

      if (par[0])
        chanout_but(-1, chan, "*** (%s) %s %s %s (%s).\n", bot, nick,
                    NET_LEFTTHE, chan ? "channel" : "party line", par);
      else
        chanout_but(-1, chan, "*** (%s) %s %s %s.\n", bot, nick,
                    NET_LEFTTHE, chan ? "channel" : "party line");
    }
    botnet_send_part_party(idx, partyidx, par, silent);
    remparty(bot, sock);
  }
}
Esempio n. 12
0
/* Bot next share?
 */
static void bot_update(int idx, char *par)
{
  char *bot, x;
  int vnum;

  bot = newsplit(&par);
  x = par[0];
  if (x)
    par++;
#ifndef NO_OLD_BOTNET
  if (dcc[idx].u.bot->numver < NEAT_BOTNET)
    vnum = atoi(par);
  else
#endif
    vnum = base64_to_int(par);
  if (in_chain(bot))
    updatebot(idx, bot, x, vnum);
}
Esempio n. 13
0
/* actchan <from> <chan> <text>
 */
static void bot_actchan(int idx, char *par)
{
  char *from = NULL, *p = NULL;
  int i, chan;

  from = newsplit(&par);
  p = strchr(from, '@');
  if (p == NULL) {
    /* How can a bot do an action? */
    fake_alert(idx, "user@bot", from, "actchan_i");
    return;
  }
  *p = 0;
  if (!partyidle(p + 1, from)) {
    *p = '@';
    fake_alert(idx, "user", from, "actchan_ii");
    return;
  }
  *p = '@';
  p++;
  i = nextbot(p);
  if (i != idx) {
    fake_alert(idx, "direction", p, "actchan_iii");
    return;
  }
  p = newsplit(&par);
  chan = base64_to_int(p);
  for (p = from; *p;) {
    if ((*p < 32) || (*p == 127))
      memmove(p, p + 1, strlen(p));
    else
      p++;
  }
  if (!conf.bot->hub) { /* Need to strip out the hub nick */
    char *q = NULL, newfrom[HANDLEN + 9 + 1]; /* HANDLEN@[botnet] */
 
    strlcpy(newfrom, from, sizeof(newfrom));
    q = strchr(newfrom, '@');
    *q = 0;
    chanout_but(-1, chan, "* %s@[botnet] %s\n", newfrom, par);
  } else
    chanout_but(-1, chan, "* %s %s\n", from, par);
  botnet_send_act(idx, from, NULL, chan, par);
}
Esempio n. 14
0
/* actchan <from> <chan> <text>
 */
static void bot_actchan(int idx, char *par)
{
  char *from, *p;
  int i, chan;

  if (bot_flags(dcc[idx].user) & BOT_ISOLATE)
    return;
  from = newsplit(&par);
  p = strchr(from, '@');
  if (p == NULL) {
    /* How can a bot do an action? */
    fake_alert(idx, "user@bot", from);
    return;
  }
  *p = 0;
  if (!partyidle(p + 1, from)) {
    *p = '@';
    fake_alert(idx, "user", from);
    return;
  }
  *p = '@';
  p++;
  i = nextbot(p);
  if (i != idx) {
    fake_alert(idx, "direction", p);
    return;
  }
  p = newsplit(&par);
#ifndef NO_OLD_BOTNET
  if (dcc[idx].u.bot->numver < NEAT_BOTNET)
    chan = atoi(p);
  else
#endif
    chan = base64_to_int(p);
  for (p = from; *p;) {
    if ((*p < 32) || (*p == 127))
      strcpy(p, p + 1);
    else
      p++;
  }
  chanout_but(-1, chan, "* %s %s\n", from, par);
  botnet_send_act(idx, from, NULL, chan, par);
  check_tcl_act(from, chan, par);
}
Esempio n. 15
0
/* away <bot> <sock> <message>
 * null message = unaway
 */
static void bot_away(int idx, char *par)
{
  char *bot, *etc;
  int sock, partyidx, linking = 0;

  if (bot_flags(dcc[idx].user) & BOT_ISOLATE)
    return;
  bot = newsplit(&par);
#ifndef NO_OLD_BOTNET
  if (dcc[idx].u.bot->numver >= NEAT_BOTNET)
#endif
    if (bot[0] == '!') {
      linking = 1;
      bot++;
    }
  if (dcc[idx].status & BSTAT_LINKING)
    linking = 1;
  etc = newsplit(&par);
#ifndef NO_OLD_BOTNET
  if (dcc[idx].u.bot->numver < NEAT_BOTNET)
    sock = atoi(etc);
  else
#endif
    sock = base64_to_int(etc);
  if (sock == 0)
    sock = partysock(bot, etc);
  check_tcl_away(bot, sock, par);
  if (par[0]) {
    partystat(bot, sock, PLSTAT_AWAY, 0);
    partyaway(bot, sock, par);
  } else
    partystat(bot, sock, 0, PLSTAT_AWAY);
  partyidx = getparty(bot, sock);
  if ((dcc[idx].u.bot->numver >= NEAT_BOTNET) && !linking) {
    if (par[0])
      chanout_but(-1, party[partyidx].chan,
                  "*** (%s) %s %s: %s.\n", bot,
                  party[partyidx].nick, NET_AWAY, par);
    else
      chanout_but(-1, party[partyidx].chan,
                  "*** (%s) %s %s.\n", bot, party[partyidx].nick, NET_UNAWAY);
  }
  botnet_send_away(idx, bot, sock, par, linking);
}
Esempio n. 16
0
/* nc <bot> <sock> <newnick>
 */
static void bot_nickchange(int idx, char *par)
{
  char *bot = NULL, *ssock = NULL, *newnick = NULL;
  int sock, i;

  bot = newsplit(&par);
  i = nextbot(bot);
  if (i != idx) {
    fake_alert(idx, "direction", bot, "nickchange_i");
    return;
  }
  ssock = newsplit(&par);
  sock = base64_to_int(ssock);
  newnick = newsplit(&par);
  i = partynick(bot, sock, newnick);
  if (i < 0) {
    fake_alert(idx, "sock#", ssock, "nickchange_ii");
    return;
  }
  chanout_but(-1, party[i].chan, "*** (%s) Nick change: %s -> %s\n",
	      conf.bot->hub ? bot : "[botnet]", newnick, party[i].nick);
  botnet_send_nkch_part(idx, i, newnick);
}
Esempio n. 17
0
/* who <from@bot> <tobot> <chan#>
 */
static void bot_who(int idx, char *par)
{
  char *from = NULL, *to = NULL, *p = NULL;
  int i, chan;

  from = newsplit(&par);
  p = strchr(from, '@');
  if (!p) {
    simple_snprintf(TBUF, sizeof(TBUF), "%s@%s", from, dcc[idx].nick);
    from = TBUF;
  }
  to = newsplit(&par);
  if (!strcasecmp(to, conf.bot->nick))
    to[0] = 0;			/* (for me) */
  chan = base64_to_int(par);
  if (to[0]) {			/* Pass it on */
    i = nextbot(to);
    if (i >= 0)
      botnet_send_who(i, from, to, chan);
  } else {
    remote_tell_who(idx, from, chan);
  }
}
Esempio n. 18
0
/* join <bot> <nick> <chan> <flag><sock> <from>
 */
static void bot_join(int idx, char *par)
{
  char *bot, *nick, *x, *y;
  struct userrec *u;
  int i, sock, chan, i2, linking = 0;

  if (bot_flags(dcc[idx].user) & BOT_ISOLATE)
    return;
  bot = newsplit(&par);
#ifndef NO_OLD_BOTNET
  if (dcc[idx].u.bot->numver >= NEAT_BOTNET)
#endif
    if (bot[0] == '!') {
      linking = 1;
      bot++;
    }
  if (dcc[idx].status & BSTAT_LINKING)
    linking = 1;
  nick = newsplit(&par);
  x = newsplit(&par);
#ifndef NO_OLD_BOTNET
  if (dcc[idx].u.bot->numver < NEAT_BOTNET)
    chan = atoi(x);
  else
#endif
    chan = base64_to_int(x);
  y = newsplit(&par);
  if ((chan < 0) || !y[0])
    return;                     /* Woops! pre 1.2.1's send .chat off'ers
                                 * too!! */
  if (!y[0]) {
    y[0] = '-';
    sock = 0;
  } else {
#ifndef NO_OLD_BOTNET
    if (dcc[idx].u.bot->numver < NEAT_BOTNET)
      sock = atoi(y + 1);
    else
#endif
      sock = base64_to_int(y + 1);
  }
  /* 1.1 bots always send a sock#, even on a channel change
   * so if sock# is 0, this is from an old bot and we must tread softly
   * grab old sock# if there is one, otherwise make up one.
   */
  if (sock == 0)
    sock = partysock(bot, nick);
  if (sock == 0)
    sock = fakesock++;
  i = nextbot(bot);
  if (i != idx) {               /* Ok, garbage from a 1.0g (who uses that
                                 * now?) OR raistlin being evil :) */
    fake_alert(idx, "direction", bot);
    return;
  }
  u = get_user_by_handle(userlist, nick);
  if (u) {
    sprintf(TBUF, "@%s", bot);
    touch_laston(u, TBUF, now);
  }
  i = addparty(bot, nick, chan, y[0], sock, par, &i2);
  botnet_send_join_party(idx, linking, i2, i);
  if (i != chan) {
    if (i >= 0) {
      if (dcc[idx].u.bot->numver >= NEAT_BOTNET)
        chanout_but(-1, i, "*** (%s) %s %s %s.\n", bot, nick, NET_LEFTTHE,
                    i ? "channel" : "party line");
      check_tcl_chpt(bot, nick, sock, i);
    }
    if ((dcc[idx].u.bot->numver >= NEAT_BOTNET) && !linking)
      chanout_but(-1, chan, "*** (%s) %s %s %s.\n", bot, nick, NET_JOINEDTHE,
                  chan ? "channel" : "party line");
    check_tcl_chjn(bot, nick, chan, y[0], sock, par);
  }
}
Esempio n. 19
0
/* Newbot next share?
 */
static void bot_nlinked(int idx, char *par)
{
  char *newbot, *next, *p, s[1024], x;
  int bogus = 0, i;
  struct userrec *u;

  newbot = newsplit(&par);
  next = newsplit(&par);
  s[0] = 0;
  if (!next[0]) {
    putlog(LOG_BOTS, "*", "Invalid eggnet protocol from %s (zapfing)",
           dcc[idx].nick);
    simple_sprintf(s, "%s %s (%s)", MISC_DISCONNECTED, dcc[idx].nick,
                   MISC_INVALIDBOT);
    dprintf(idx, "error invalid eggnet protocol for 'nlinked'\n");
  } else if ((in_chain(newbot)) || (!egg_strcasecmp(newbot, botnetnick))) {
    /* Loop! */
    putlog(LOG_BOTS, "*", "%s %s (mutual: %s)",
           BOT_LOOPDETECT, dcc[idx].nick, newbot);
    simple_sprintf(s, "%s %s: disconnecting %s", MISC_LOOP, newbot,
                   dcc[idx].nick);
    dprintf(idx, "error Loop (%s)\n", newbot);
  }
  if (!s[0]) {
    for (p = newbot; *p; p++)
      if ((*p < 32) || (*p == 127) || ((p - newbot) >= HANDLEN))
        bogus = 1;
    i = nextbot(next);
    if (i != idx)
      bogus = 1;
  }
  if (bogus) {
    putlog(LOG_BOTS, "*", "%s %s!  (%s -> %s)", BOT_BOGUSLINK, dcc[idx].nick,
           next, newbot);
    simple_sprintf(s, "%s: %s %s", BOT_BOGUSLINK, dcc[idx].nick,
                   MISC_DISCONNECTED);
    dprintf(idx, "error %s (%s -> %s)\n", BOT_BOGUSLINK, next, newbot);
  }
  if (bot_flags(dcc[idx].user) & BOT_LEAF) {
    putlog(LOG_BOTS, "*", "%s %s  (%s %s)",
           BOT_DISCONNLEAF, dcc[idx].nick, newbot, BOT_LINKEDTO);
    simple_sprintf(s, "%s %s (to %s): %s",
                   BOT_ILLEGALLINK, dcc[idx].nick, newbot, MISC_DISCONNECTED);
    dprintf(idx, "error %s\n", BOT_YOUREALEAF);
  }
  if (s[0]) {
    chatout("*** %s\n", s);
    botnet_send_unlinked(idx, dcc[idx].nick, s);
    dprintf(idx, "bye %s\n", BOT_ILLEGALLINK);
    killsock(dcc[idx].sock);
    lostdcc(idx);
    return;
  }
  x = par[0];
  if (x)
    par++;
  else
    x = '-';
#ifndef NO_OLD_BOTNET
  if (dcc[idx].u.bot->numver < NEAT_BOTNET)
    i = atoi(par);
  else
#endif
    i = base64_to_int(par);
  botnet_send_nlinked(idx, newbot, next, x, i);
  if (x == '!') {
    chatout("*** (%s) %s %s.\n", next, NET_LINKEDTO, newbot);
    x = '-';
  }
  addbot(newbot, dcc[idx].nick, next, x, i);
  check_tcl_link(newbot, next);
  u = get_user_by_handle(userlist, newbot);
  if (bot_flags(u) & BOT_REJECT) {
    botnet_send_reject(idx, botnetnick, NULL, newbot, NULL, NULL);
    putlog(LOG_BOTS, "*", "%s %s %s %s", BOT_REJECTING,
           newbot, MISC_FROM, dcc[idx].nick);
  }
}