pdirt/data/
pdirt/data/HELP/
pdirt/data/HELP/0/
pdirt/data/HELP/F/
pdirt/data/HELP/G/
pdirt/data/HELP/H/
pdirt/data/HELP/J/
pdirt/data/HELP/K/
pdirt/data/HELP/O/
pdirt/data/HELP/Q/
pdirt/data/HELP/R/
pdirt/data/HELP/U/
pdirt/data/HELP/V/
pdirt/data/HELP/Y/
pdirt/data/HELP/Z/
pdirt/data/MESSAGES/
pdirt/data/POWERINFO/
pdirt/data/WIZ_ZONES/
pdirt/drv/
pdirt/drv/bin/
pdirt/drv/compiler/converter/
pdirt/drv/compiler/libs/
pdirt/drv/compiler/scripts/
pdirt/drv/include/AberChat/
pdirt/drv/include/InterMud/
pdirt/drv/include/machine/
pdirt/drv/src/InterMud/
pdirt/drv/src/Players/
pdirt/drv/utils/UAFPort/
pdirt/drv/utils/dnsresolv/
pdirt/drv/utils/gdbm/
/*********************************************************************
 * AberChat Client 4.20 (C) Giancarlo Castrataro -- iDirt/Compatible *
 *********************************************************************/

#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <netdb.h>
#include "kernel.h"
#include "mobile.h"
#include "sflags.h"
#include "pflags.h"
#include "sendsys.h"
#include "log.h"
#include "mud.h"
#include "parse.h"
#include "bprintf.h"
#include "commands.h"
#include "verbs.h"
#include "timing.h"
#include "AberChat/client.h"
#include "AberChat/client_int.h"
#include "sflag.h"
#include "s_socket.h"

typedef struct _aberchat_banlist {
    char    name[120];
    struct  _aberchat_banlist *next;
} aberchat_banlist;

aberchat_banlist *aberchat_mudbanned = NULL;
aberchat_banlist *aberchat_charbanned = NULL;

Boolean auto_restart = True;
Boolean auth = False;
Boolean aber_output = False;
int aberfd = -1;
char abuffer[WRITELEN];
time_t boottime = 0;		/* when we opened the socket to the server */
time_t socktime = 0;		/* the last time anything went in or out on the socket */

extern fd_set sockets_fds;
extern int width;
extern char *WizLevels[];
extern char *FWizLevels[];
extern char *MLevels[];
extern char *Flevels[];

/* Chat sequences for all communications lines */
#ifdef ABERCHAT

char *chat_chat = "&=WB[%s&=RB@&=WB%s]&* %s\n";
char *chat_emote = "&=WB->%s&=RB@&=WB%s %s<-&*\n";
char *god_chat = "&=WrAGod: %s@%s -->&* %s\n";
char *god_emote = "&=WrAGod: %s@%s %s&*\n";
char *coder_chat = "&=WyACode: %s@%s -->&* %s\n";
char *coder_emote = "&=WyACode: %s@%s %s&*\n";
char *atell_fmt = "&+w%s&+w@&+w%s&* tells you&+w, &+w'&*%s&+w'&*\n";
char *atell_send_fmt = "You tell &+w%s&+w@&+w%s&*, &+w'&*%s&+w'&*\n";
char *atell_emote_send_fmt = "You aberemote to &+w%s&+w@&+w%s&*: %s&*\n";
char *atell_emote_fmt = "&+w%s&+w@&+w%s&* %s&*\n";
char *ainfo_fmt = "&+w[&+wAberchat info from &+w%s&+w: &*%s&+w]&*\n";
char *areply_fmt = "You reply, &+w'%s&+w'&*\n";
char *amessage_fmt = "&+wReply from %s&*: &+w%s\n";

/* the local functions */
A_COMMAND(cmd_aautocon);
A_COMMAND(cmd_aboot);
static void core_achat(int type);
A_COMMAND(cmd_acommstats);
A_COMMAND(cmd_acopyright);
A_COMMAND(cmd_ainfo);
A_COMMAND(cmd_akick);
A_COMMAND(cmd_amasslist);
A_COMMAND(cmd_amudlist);
A_COMMAND(cmd_noaberchat);
A_COMMAND(cmd_noachat);
A_COMMAND(cmd_noagod);
A_COMMAND(cmd_noainfo);
A_COMMAND(cmd_noatell);
A_COMMAND(cmd_apolicy);
A_COMMAND(cmd_areply);
A_COMMAND(cmd_ashutdown);
A_COMMAND(cmd_atell);
A_COMMAND(cmd_aversion);
A_COMMAND(cmd_awho);


#define strip_newline(S)	S[strlen(S) -1] = '\0'

int boot_aberchat(FILE *fp, char *fn)
{   char   buffer[120];
    FILE   *fp2;
    int    mem_used = 0;
    aberchat_banlist *p;

    fgets(buffer,120,fp);
    strip_newline(buffer);
    if ((fp2 = fopen(buffer,"r")) != NULL)
    {   fgets(buffer,120,fp2);
        while (!feof(fp2))
        {    p = NEW(aberchat_banlist,1);
             mem_used += sizeof(aberchat_banlist);
             strncpy(p->name,buffer,119);
             p->next = aberchat_mudbanned;
             aberchat_mudbanned = p; 
             fgets(buffer,120,fp2);
        }
        fclose(fp2);
    }
    if (feof(fp))
       return -1;
    fgets(buffer,120,fp); 
    strip_newline(buffer);
    if ((fp2 = fopen(buffer,"r")) != NULL)
    {   fgets(buffer,120,fp2);
        while (!feof(fp2))
        {   p = NEW(aberchat_banlist,1);
            mem_used += sizeof(aberchat_banlist);
            strncpy(p->name,buffer,119);
            p->next = aberchat_charbanned;
            aberchat_charbanned = p;
            fgets(buffer,120,fp2);
        }
        fclose(fp2);
    }
    return mem_used; 
}

Boolean in_list(aberchat_banlist *list,char *name)
{   aberchat_banlist *p = list;

    while (p != NULL)
    {   if (strcasecmp(p->name,name) == 0)
            return True;
        p = p->next;
    }
    return False; 
}

Boolean aber_mudbanned(char *host)
{   return in_list(aberchat_mudbanned,host);
}

Boolean aber_charbanned(char *host)
{   return in_list(aberchat_charbanned,host);
}

/* the commands */
static void core_achat(int type)
{
  char buff[MAX_COM_LEN];

  if (!abercheck(mynum, type)) {
    bprintf("Sorry, you can't talk on that AberChat line.\n");
    return;
  }
  getreinput(buff);
  if (brkword() == -1)
    bprintf("What would you like to chat?\n");
  else {
    aprintf("%c" D "%c" D "%s" D "%s" D "%s",
	    TO_ALL, type, MYMUD, pname(mynum), buff);
  }
}

A_COMMAND(cmd_achat)
{   core_achat(CHAT);
}

A_COMMAND(cmd_acode)
{   core_achat(ACODE);
}

A_COMMAND(cmd_agod)
{   core_achat(AGOD);
}

A_COMMAND(cmd_atell)
{
  char *mud, *ctl;

  if (!abercheck(mynum, TELL)) {
    bprintf("Sorry, you can't atell at the moment.\n");
    return;
  }
  if (!(mud = strchr(item1, '@'))) {
    bprintf("Usage: ATell player@mud [message]\n");
  } else {
    *(mud++) = 0;
    if (EMPTY(txt2)) {
      bprintf("What do you want to atell them?\n");
      return;
    }
    set_areply(mynum, item1, mud);
    aprintf("%c" D "%s" D "%c" D "%s" D "%s" D "%s" D "%s\0",
	    TO_MUD, mud, TELL, pname(mynum), item1, MYMUD, txt2);
    ctl = (*txt2 == ':') ? atell_emote_send_fmt : atell_send_fmt;
    if (*txt2 == ':')
      txt2++;
    for (; *txt2 == ' '; txt2++);
    if (ststflg(mynum, SFL_SAYBACK)) {
      sendf(mynum, ctl, item1, mud, txt2);
    }
  }
}

A_COMMAND(cmd_areply)
{
  if (EMPTY(txt1)) {
    bprintf("Reply what? You need to type something after it.\n");
    return;
  } else if (!amud(mynum) || !atarget(mynum)) {
    bprintf("You have no-one to reply to.\n");
    return;
  } else if (!abercheck(mynum, TELL)) {
    bprintf("Sorry, you can't areply at the moment.\n");
    return;
  }
  if (ststflg(mynum, SFL_SAYBACK))
    sendf(mynum, areply_fmt, txt1);
  aprintf("%c" D "%s" D "%c" D "%s" D "%s" D "%s" D "%s\0", TO_MUD,
	  amud(mynum), TELL, pname(mynum), atarget(mynum), MYMUD, txt1);
}

A_COMMAND(cmd_akick)
{
  char *mud;

  if (plev(mynum) < LEVEL_ADMIN)
    bprintf("You aren't powerful enough.\n");
  else if (!(mud = strchr(item1, '@')))
    bprintf("Usage: AKick player@mud\n");
  else {
    *(mud++) = 0;
    aprintf("%c" D "%s" D "%c" D "%s" D "%s" D "%s",
	    TO_MUD, mud, KICK, pname(mynum), item1, MYMUD);
    aberlog("KICKOFF: %s has akicked %s@%s", pname(mynum), item1, mud);
  }
}

A_COMMAND(cmd_acommstats)
{
  int i;
  if (plev(mynum) < LEVEL_ADMIN) {
    if (!ptstflg(mynum, PFL_ABERCHAT)) {
      bprintf("Pardon?\n");
      return;
    } else if (ststflg(mynum, SFL_NOABERCHAT)) {
      bprintf("You have NoAberChat turned on. (noaberchat to toggle it)\n");
      return;
    }
    if (ptstflg(mynum, PFL_MAYCODE)) {
      bprintf("%-*s : Chat Tell Info Code\n", PNAME_LEN, "Name");
    } else {
      bprintf("%-*s : Chat Tell Info\n", PNAME_LEN, "Name");
    }
    bprintf("&+w-------------------------------------------------------------------------------\n");
    bprintf("&+w%-*s&* : %4s %4s %4s%4s\n", PNAME_LEN, pname(mynum)
	    ,ststflg(mynum, SFL_NOACHAT) ? "&+wOff &*" : "&+w On &*"
	    ,ststflg(mynum, SFL_NOATELL) ? "&+wOff &*" : "&+w On &*"
	    ,ststflg(mynum, SFL_NOAINFO) ? "&+wOff &*" : "&+w On &*"
	    ,ptstflg(mynum, PFL_MAYCODE) ? ststflg(mynum, SFL_NOACODE) ? " &+wOff &*" : " &+w On &*" : ""
	);
    bprintf("&+w-------------------------------------------------------------------------------\n");
    return;
  }
  bprintf("%-*s : Chat Tell Info Code  God\n", PNAME_LEN, "Name");
  bprintf("&+w-------------------------------------------------------------------------------\n");
  for (i = 0; i < max_players; i++) {
    if (is_in_game(i) && see_player(mynum, i)) {
      if (!ptstflg(i, PFL_ABERCHAT)) {
	bprintf("&+w%-*s&* : ---- ---- ---- ---- ----\n", PNAME_LEN, pname(i));
      } else if (ststflg(i, SFL_NOABERCHAT)) {
	bprintf("&+w%-*s&* : NoAc NoAc NoAc %4s %4s&*\n", PNAME_LEN, pname(i)
		,ptstflg(i, PFL_MAYCODE) ? "NoAc" : "----"
		,plev(i) >= LEVEL_ADMIN ? "NoAc" : "----");
      } else {
	bprintf("&+w%-*s&* : %4s %4s %4s %4s %4s\n", PNAME_LEN, pname(i)
		,ststflg(i, SFL_NOACHAT) ? "&+wOff &*" : "&+w On &*"
		,ststflg(i, SFL_NOATELL) ? "&+wOff &*" : "&+w On &*"
		,ststflg(i, SFL_NOAINFO) ? "&+wOff &*" : "&+w On &*"
		,ptstflg(i, PFL_MAYCODE) ? ststflg(i, SFL_NOACODE) ? "&+wOff &*" : "&+w On &*" : "----"
		,plev(i) >= LEVEL_ADMIN ? ststflg(i, SFL_NOAGOD) ? "&+wOff &*" : "&+w On &*" : "----"
	    );
      }
    }
  }
  bprintf("&+w-------------------------------------------------------------------------------\n");
  return;
}

A_COMMAND(cmd_noaberchat)
{
  if (!ptstflg(mynum, PFL_ABERCHAT))
    bprintf("You can't use aberchat.\n");
  else
    setsflag(SFL_NOABERCHAT, "Disable Aberchat");
  return;
}

A_COMMAND(cmd_noachat)
{
  if (!ptstflg(mynum, PFL_ABERCHAT)) {
    bprintf("You can't use the achat line.\n");
  } else {
    setsflag(SFL_NOACHAT, "Disable AChat line");
  }
  return;
}

A_COMMAND(cmd_noacode)
{
  if (!ptstflg(mynum, PFL_ABERCHAT) || !ptstflg(mynum, PFL_MAYCODE)) {
    bprintf("You can't use the acode line.\n");
  } else {
    setsflag(SFL_NOACODE, "Disable ACode line");
  }
  return;
}

A_COMMAND(cmd_noagod)
{
  if (!ptstflg(mynum, PFL_ABERCHAT) || plev(mynum) < LEVEL_ADMIN) {
    bprintf("You can't use the agod line.\n");
  } else {
    setsflag(SFL_NOAGOD, "Disable AGod line");
  }
  return;
}

A_COMMAND(cmd_noainfo)
{
  if (!ptstflg(mynum, PFL_ABERCHAT)) {
    bprintf("You can't see the ainfo line.\n");
  } else {
    setsflag(SFL_NOAINFO, "Disable Aberchat Info line");
  }
  return;
}

A_COMMAND(cmd_noatell)
{
  if (!ptstflg(mynum, PFL_ABERCHAT)) {
    bprintf("You can't see atells.\n");
  } else {
    setsflag(SFL_NOATELL, "Disable AberChat tells");
  }
  return;
}

A_COMMAND(cmd_ainfo)
{
  char buff[MAX_COM_LEN];

  if (!abercheck(mynum, INFOMSG) || plev(mynum) < LEVEL_ADMIN) {
    bprintf("Sorry, you can't send AINFO messages.\n");
    return;
  }
  getreinput(buff);
  if (brkword() == -1)
    bprintf("What should the message be?\n");
  else
    aprintf("%c" D "%c" D "%s" D "%s", TO_ALL, INFOMSG, MYMUD, buff);
}

A_COMMAND(cmd_aautocon)
{
  if (plev(mynum) < LEVEL_ADMIN) {
    bprintf("You aren't powerful enough.\n");
    return;
  }
  auto_restart = auto_restart ? False : True;

  bprintf("AberChat Auto Connect is %s.\n", auto_restart ? "On" : "Off");
}

A_COMMAND(cmd_aboot)
{
  if (plev(mynum) < LEVEL_ADMIN) {
    bprintf("You aren't powerful enough.\n");
    return;
  }
  switch (aberchat_boot()) {
  case 0:
    bprintf("Failed.\n");
    break;
  case 1:
    bprintf("Connected to AberChat Server.\n");
    break;
  case 2:
    bprintf("AberChat already running.\n");
    break;
  default:
    aberlog("ABERCHAT: strange result returned from aberchat_boot()");
    break;
  }
  return;
}

A_COMMAND(cmd_ashutdown)
{
  if (plev(mynum) < LEVEL_ADMIN) {
    bprintf("You aren't powerful enough.\n");
    return;
  }
  if (!aberchat_shutdown()) {
    bprintf("Aberchat not running.\n");
  } else {
    bprintf("Disconnected from AberChat server.\n");
  }
  return;
}

/* Mudlist request */
A_COMMAND(cmd_amudlist)
{
  aprintf("%c" D "%s" D "%c" D "%s", TO_MUD, MYMUD, MUDLIST, pname(mynum));
}

A_COMMAND(cmd_amasslist)
{
  if (!abercheck(mynum, 0)) {
    bprintf("Can't do that.\n");
    return;
  }
  strcpy((char *) cur_player->work2, "masslist");
  afilepagecom(NULL);
}

A_COMMAND(cmd_apolicy)
{
  char buff[1024];
  if (!abercheck(mynum, 0)) {
    bprintf("Can't do that.\n");
    return;
  }
  getreinput(buff);
  if (brkword() == -1) {
    strcpy((char *) cur_player->work2, "policy");
  } else {
    sprintf((char *) cur_player->work2, "policy.%s", buff);
  }
  afilepagecom(NULL);
}

A_COMMAND(cmd_acopyright)
{
  if (!abercheck(mynum, 0)) {
    bprintf("Can't do that.\n");
    return;
  }
  strcpy((char *) cur_player->work2, "copyright");
  afilepagecom(NULL);
}

/****************************************************************
 * cmd_awho() sends a WHO request to the specified mud.  The mud *
 * then sends a response packet, in send_awho(), and the packet *
 * is received/displayed in receive_awho()                      *
 ****************************************************************/

A_COMMAND(cmd_awho)
{
  if (EMPTY(txt1))
    bprintf("Which mud?\n");
  else
    aprintf("%c" D "%s" D "%c" D "%s" D "%s",
	    TO_MUD, txt1, WHO, MYMUD, pname(mynum));
}

/********************************************************************
 * cmd_aversion() sends the current version to the aberchat server, *
 * or makes a request to another mud for it's version.              *
 ********************************************************************/

A_COMMAND(cmd_aversion)
{
  if (EMPTY(txt1))
    aprintf("%c" D "%s" D "%c" D "%s" D "%s",
	    TO_MUD, MYMUD, AVERSION, pname(mynum), CLIENT_VERSION);
  else {
    bprintf("Version for MUD %s (if no response, client is pre-4.20):\n", txt1);
    aprintf("%c" D "%s" D "%c" D "%s" D "%s",
	    TO_MUD, txt1, AVERREQ, MYMUD, pname(mynum));
  }
}

/* the various support functions and stuff that deals with the
 * aberchat protocol itself
 */
char *player_level(int plr)
{
  if (plev(plr) >= LVL_FIRST_NONMORTAL)
  {  if (psex(plr))
        return FWizLevels[wlevel(plev(plr))];
     else
        return (WizLevels[wlevel(plev(plr))]);
  }
  else {
    if (psex(plr))
      return (FLevels[plev(plr)]);
    else
      return (MLevels[plev(plr)]);
  }
}

/* Checks to see if a player will hear a line */

Boolean abercheck(int plx, int type)
{
  if (!is_in_game(plx) || !ptstflg(plx, PFL_ABERCHAT) || ststflg(plx, SFL_NOABERCHAT) || !auth)
    return False;
  else {
    switch (type) {
    case CHAT:
      if (ststflg(plx, SFL_NOACHAT)) {
	return False;
      }
      break;
    case ACODE:
      if (!ptstflg(plx, PFL_MAYCODE) || ststflg(plx, SFL_NOACODE)) {
	return False;
      }
      break;
    case AGOD:
      if (plev(plx) < LEVEL_ADMIN || ststflg(plx, SFL_NOAGOD)) {
	return False;
      }
      break;
    case INFOMSG:
      if (ststflg(plx, SFL_NOAINFO)) {
	return False;
      }
      break;
    case TELL:
      if (ststflg(plx, SFL_NOATELL)) {
	return False;
      }
      break;
    }
  }
  return True;
}

/* Pops one argument from a string */

char *get_arg(char *txt)
{
  char *ptr;

  if (txt != NULL && (ptr = strchr(txt, DCHAR))) {
    *ptr = 0;
    return (++ptr);
  } else
    return (NULL);
}

int aberchat_boot(void)
{
  if (aberfd == -1) {
    if ((aberfd = makesock(SERVER, SERVER_PORT)) == -1) 
    {
      return 0;
    } 
    else 
    {
      FD_SET(aberfd, &sockets_fds);
      if (aberfd >= width)
	width = aberfd + 1;
      authenticate();
      time(&socktime);
      time(&boottime);
      return 1;
    }
  }
  return 2;
}

Boolean aberchat_shutdown(void)
{
  if (aberfd != -1) {
    ainfo(MYMUD, "Exited Network");
    aberlog("CONNECT: Shutdown");
    close(aberfd);
#ifndef CDIRT
    FD_CLR(aberfd, &sockets_fds);
#endif
    aberfd = -1;
    return True;
  }
  return False;
}

void aberchat_autorecon(void)
{
  aberlog("CONNECT: auto reconnect");
  aberchat_boot();
  return;
}

/* a little function to print out the aberchat socket details in a format
 * that would fit in nicely with socketcom in god.c
 */
void aberchat_socketdetails(time_t now)
{
  char idlebuff[64], loginbuff[64];
  time_t idletime,logintime;
  if (aberfd != -1) {
    idletime=now-socktime;
    logintime=now-boottime;
    if(idletime < 0) idletime=0;
    if(logintime < 0) logintime=0;
    strcpy(idlebuff, sec_to_hhmmss(idletime));
    strcpy(loginbuff, sec_to_hhmmss(logintime));
    bprintf("&+w%-19s&* %2d  %8.8s  %8.8s  %-34.34s\n"
	    ,"Aberchat socket", aberfd, idlebuff, loginbuff, SERVER);
  }
  return;
}

void aprintf(char *format,...)
{
  char buffer[WRITELEN];
  Boolean ok = False;
  va_list pvar;

  if (mynum != -1) {
    if (aberfd == -1)
      bprintf("Aberchat not running.\n");
    else if (!auth)
      bprintf("Aberchat not authenticated.\n");
    else if (!ptstflg(mynum, PFL_ABERCHAT))
      bprintf("You aren't authorized to use aberchat.\n");
    else if (ststflg(mynum, SFL_NOABERCHAT))
      bprintf("You don't have AberChat enabled.\n");
    else
      ok = True;
  } else if (aberfd != -1)
    ok = True;

  if (ok) {
    va_start(pvar, format);
    vsprintf(buffer, format, pvar);
    va_end(pvar);
    strcat(abuffer, buffer);
    aber_output = True;
  }
  return;
}

void aberchat_writepacket(void)
{
  if (aber_output) {
    write(aberfd, abuffer, strlen(abuffer) + 1);
    *abuffer = 0;
    aber_output = False;
    time(&socktime);
  }
  return;
}

void aberchat_readpacket(void)
{
  static char buff[READLEN];
  static char *pos = buff;
  int n_read, data_type;

  n_read = read(aberfd, pos, READLEN - (pos - buff));

  if (n_read <= 0) {
    if (auth) {
      ainfo("AberChat Server", "Aber Server has crashed");
      aberlog("CONNECT: Connection closed by Server.");
      aberchat_shutdown();
    }
  } else if (*(pos + n_read - 1) == 0) {
    data_type = *buff;
    abercmd(*buff, buff + 2);
    *buff = 0;
    pos = buff;
  } else {
    pos += n_read;
  }
  time(&socktime);
  return;
}

void abercmd(char type, char *packet)
{
  char *arg1, *arg2, *arg3, *arg4;
  int x;

  switch (type) {		/* commands with unlimited args here */
  case MUDLIST:
    amudlist(packet);
    return;
  case RWHO:
    receive_awho(packet);
    return;
  }

  arg1 = packet;
  arg2 = get_arg(arg1);
  arg3 = get_arg(arg2);
  arg4 = get_arg(arg3);
  if(aberchat_filter(type,arg1,arg2,arg3,arg4)) {
    return;
  }
  switch (type) {
  case KICK:
    kick_player(arg1, arg2, arg3);
    return;
  case FILEPAGE:
    afilepage(arg1, arg2, arg3);
    return;
  case AVERSION:
    aversion(arg1, arg2, arg3);
    return;
  case MSG:
    amessage(arg1, arg2, arg3);
    return;
  case TELL:
    atell(arg1, arg2, arg3, arg4);
    return;
  }
  x = mynum;
  mynum = -1;

  switch (type) {
  case AVERREQ:
    aver_reply(arg1, arg2);
    break;
  case WHO:
    send_awho(arg1, arg2);
    break;
  case CHAT:
  case ACODE:
  case AGOD:
    achat(type, arg1, arg2, arg3);
    break;
  case INFOMSG:
    ainfo(arg1, arg2);
    break;
  case AUTH:
    if (*packet == 'Y')
      auth_received(True);
    else
      auth_received(False);
    break;
  }
  mynum = x;
}

void afilepagecom(char *input)
{
  if (!input) {			/* first run */
    if (!auth || aberfd == -1) {
      bprintf("Aberchat is not running.\n");
      return;
    }
    cur_player->work = 0;
    strcpy(cur_player->cprompt, "");
    push_input_handler(afilepagecom);
  }
  aprintf("%c" D "%s" D "%c" D "%s" D "%s" D "%d", TO_MUD, MYMUD,
	  FILEPAGE, pname(mynum), cur_player->work2, cur_player->work);
  if (!auth || aberfd == -1) {
    bprintf("%s",build_prompt(mynum));
    pop_input_handler();
  }
}

void afilepage(char *player, char *txt, char *more)
{
  int plx;

  if ((plx = fpbns(player)) == -1)
    return;
  else {
    setup_globals(plx);
    bprintf("%s", txt);

    if (*more == '1') {
      cur_player->work++;
      bprintf("[File: %s] ", cur_player->work2);
    } else {
      cur_player->work = 0;
      bprintf("%s", build_prompt(mynum));
      pop_input_handler();
    }
  }
}

/* Prototype: FROM_PLAYER:TO_PLAYER:FROM_MUD:TEXT */

void atell(char *f_plr, char *to_plr, char *f_mud, char *text)
{
  int plx;
  char *ctl;

  if ((plx = fpbns(to_plr)) != -1 && !pvis(plx)) {
    if (abercheck(plx, TELL)) {
      set_areply(plx, f_plr, f_mud);
      ctl = (*text == ':') ? atell_emote_fmt : atell_fmt;
      if (*text == ':')
	text++;
      for (; *text == ' '; text++);
      sendf(plx, ctl, f_plr, f_mud, text);
      if (ststflg(plx,SFL_AWAY)) {
	aprintf("%c" D "%s" D "%c" D "%s" D "MUD %s" D
		"&*%s is marked as &+waway&*: %s",
		TO_MUD, f_mud, MSG, f_plr, MYMUD, pname(plx), players[plx].awaymsg);
      } else if (ststflg(plx,SFL_CODING)) {
	aprintf("%c" D "%s" D "%c" D "%s" D "MUD %s" D
	"&*%s is marked as &+wcoding &*and might not respond right away.",
		TO_MUD, f_mud, MSG, f_plr, MYMUD, pname(plx));
      }
    } else {
      int x = mynum;
      mynum = -1;
      aprintf("%c" D "%s" D "%c" D "%s" D "MUD %s" D "You can't ATell %s at the moment",
	      TO_MUD, f_mud, MSG, f_plr, MYMUD, to_plr);
      mynum = x;
    }
  } else {
    int x = mynum;
    mynum = -1;
    aprintf("%c" D "%s" D "%c" D "%s" D "MUD %s" D "%s is not online",
	    TO_MUD, f_mud, MSG, f_plr, MYMUD, to_plr);
    mynum = x;
  }
}

void amessage(char *to_plr, char *f_mud, char *text)
{
  int plx;

  if ((plx = fpbns(to_plr)) != -1)
    sendf(plx, amessage_fmt, f_mud, text);
}

void ainfo(char *f_mud, char *text)
{
  int plx;

  for (plx = 0; plx < max_players; plx++)
    if (abercheck(plx, INFOMSG))
      sendf(plx, ainfo_fmt, f_mud, text);
}

void achat(int type, char *f_mud, char *f_plr, char *text)
{
  char *ctl;
  int plx;

  switch (type) {
  case CHAT:
    ctl = (*text == ':') ? chat_emote : chat_chat;
    break;
  case ACODE:
    ctl = (*text == ':') ? coder_emote : coder_chat;
    break;
  case AGOD:
    ctl = (*text == ':') ? god_emote : god_chat;
    break;
  default:
    ctl = "%s - %s - %s\n";	/* dummy format in case something goes wrong :) */
    break;
  }
  if (*text == ':')
    text++;
  for (; *text == ' '; text++);

  for (plx = 0; plx < max_players; plx++) {
    if (abercheck(plx, type)) {
      sendf(plx, ctl, f_plr, f_mud, text);
    }
  }
}

extern int cmp_player(const void *, const void *);

void send_awho(char *mud, char *player)
{
  char *level, *title;
  int i, list[max_players], len;

  for (i = 0, len = 0; i < max_players; i++)
    if (is_in_game(i) && !pvis(i) && !ststflg(i,SFL_NOABERCHAT))
      list[len++] = i;

  qsort(list, len, sizeof(int), cmp_player);

  aprintf("%c" D "%s" D "%c" D "%s" D "%s", TO_MUD, mud, RWHO, player, MYMUD);
  for (i = 0; i < len; i++) {
    level = player_level(list[i]);
    title = make_title(ptitle(list[i]), pname(list[i]));
    aprintf(D "%s" D "%s" D "%s", pname(list[i]), level, title);
  }
  aberlog("AWHO: Request by %s from %s",player,mud);
}

void receive_awho(char *packet)
{
  char *player, *name, *level, *title, *mud, *next;
  int plx, i;

  player = packet;
  mud = get_arg(player);
  next = get_arg(mud);

  if ((plx = fpbns(player)) == -1)
    return;
  setup_globals(plx);

  if (!next) {
    bprintf("There are no players online at %s.\n%s", mud, build_prompt(mynum));
    return;
  }
  bprintf("\n&+wName          &+wLevel          &+wTitle\n" DASHES);
  for (i = 0; next; i++) {
    name = next;
    level = get_arg(name);
    title = get_arg(level);
    next = get_arg(title);
    bprintf("%-14s%-15s%-45.47s\n", name, level, title);
  }
  bprintf(DASHES "There %s %d player%s on %s.\n%s", (i > 1) ? "are" : "is",
	  i, (i > 1) ? "s" : "", mud, build_prompt(mynum));
}

/***************************************************************************
 * To connect to the network, authenticate() sends a packet which contains *
 * the password, mudname, mudlib, and port.  This allows the server to     *
 * build a mudlist entry for the connecting mud.  Following function is a  *
 * server response, which enables the mud to send data over aberchat       *
 ***************************************************************************/

void authenticate(void)
{
  char passwd[30];
  int oldnum = mynum;

  strcpy(passwd, crypt(PASS, "Ac"));
  auth = True;
  mynum = -1;
  aprintf("%c" D "%s" D "%c" D "%s" D "%s" D "%d" D "%s",
	  TO_MUD, MYMUD, AUTH, MYMUD, MUDLIB, PORT, passwd);
  auth = False;
  mynum = oldnum;
}

void auth_received(Boolean ok)
{
  if (ok) {
    auth = True;
    aberlog("CONNECT: Successful connection to server");
    ainfo(MYMUD, "Authenticated/Joined Network");
  } else {
    aberlog("CONNECT: Connection failed (Bad password)");
    send_msg(DEST_ALL, MODE_QUIET|MODE_BRACKET, LVL_WIZARD, LVL_MAX,
	     NOBODY, NOBODY, "Aberchat Failed: Bad Password");
    aberchat_shutdown();
  }
}

void aver_reply(char *tomud, char *player)
{
  aprintf("%c" D "%s" D "%c" D "%s" D "%s",
	  TO_MUD, tomud, AVERSION, player, CLIENT_VERSION);
}

void aversion(char *to_plr, char *client_ver, char *server_ver)
{
  int plx;

  if ((plx = fpbns(to_plr)) == -1)
    return;
  sendf(plx, "Server is: %s\n"
	"Client is: %s\n"
	"All code Copyright G. Castrataro (gcastrat@indiana.edu)\n",
	server_ver, client_ver);
}

void amudlist(char *list)
{
  char *toplr, *mudname, *mudlib, *mudaddr, *mudip, *mudport, *next;
  int pl;

  toplr = list;
  next = get_arg(toplr);

  if ((pl = fpbns(toplr)) == -1)
    return;

  setup_globals(pl);

  bprintf("\n&+wMudname         &+wAddress                  &+wIP         "
	  "     &+wPort       &+wCode Base\n" DASHES);

  while (next != NULL) {
    mudname = next;
    mudlib = get_arg(mudname);
    mudaddr = get_arg(mudlib);
    mudip = get_arg(mudaddr);
    mudport = get_arg(mudip);
    next = get_arg(mudport);
    bprintf("%-16.14s%-25.23s%-16.14s%-11s%-11.11s\n",
	    mudname, mudlib, mudaddr, mudip, mudport);
  }
  bprintf("%s%s", DASHES, build_prompt(mynum));
}

void set_areply(int plr, char *target, char *mud)
{
  if (atarget(plr)) {
    free(atarget(plr));
  }
  atarget(plr) = COPY(target);
  if (amud(plr)) {
    free(amud(plr));
  }
  amud(plr) = COPY(mud);
}

void aberchat_newconn(int plr)
{
  if (atarget(plr)) {
    free(atarget(plr));
    atarget(plr) = NULL;
  }
  if (amud(plr)) {
    free(amud(plr));
    amud(plr) = NULL;
  }
  return;
}

void kick_player(char *from, char *to, char *frommud)
{
  int plr;

  if ((plr = fpbns(to)) == -1)
    aprintf("%c" D "%s" D "%c" D "%s" D "MUD %s" D "%s is not online",
	    TO_MUD, frommud, MSG, from, MYMUD, to);
  else if (plev(plr) > LEVEL_ADMIN)
    aprintf("%c" D "%s" D "%c" D "%s" D "MUD %s" D "%s is too powerful",
	    TO_MUD, frommud, MSG, from, MYMUD, to);
  else {
    sendf(plr, "You have been kicked off aberchat by %s@%s\n", from, frommud);
    pclrflg(plr, PFL_ABERCHAT);
    pclrmsk(plr, PFL_ABERCHAT);
    aberlog("KICKOFF: %s has been akicked by %s@%s.", pname(plr), from, frommud);
  }
}

Boolean aberchat_filter(char type,char *arg1,char *arg2,char *arg3,char *arg4)
{
  switch(type) {
  /* example akick filter:
   * arg1	: from_mud
   * arg2 : target_player
   * arg3 : from_player
   */
  case KICK:
    if(1 /*EQ(arg3,"foomud")*/) 
    {
      int x;
      x = mynum;
      mynum = -1;
      aprintf("%c" D "%s" D "%c" D "%s" D "MUD %s" D "Sorry, your mud isnt allowed to akick anyone here.",
	    TO_MUD, arg3, MSG, arg1, MYMUD);
      mynum = x;
      return True;
    }
    break;
  /* example atell filter:
   * arg1	: from_player
   * arg2	: target_player
   * arg3	: from_mud
   * arg4 : text
   */
  case TELL:
    if (aber_charbanned(arg1) || aber_mudbanned(arg1))  
    { int x;
      x = mynum;
      mynum = -1;
      aprintf("%c" D "%s" D "%c" D "%s" D "MUD %s" D "Sorry, No-one wants to talk to you or anyone from that site anymore.",
	    TO_MUD, arg3, MSG, arg1, MYMUD);
      mynum = x;
      return True;
    }
    break;
  /* example achat/agod/acode filter:
   * arg1	: from_mud
   * arg2 : from_player
   * arg3 : text
   */
  case CHAT: /* or AGOD/ACODE */
    if(aber_mudbanned(arg1) || aber_charbanned(arg1))
      return True;
    break;
  /* example ainfo filter:
   * arg1	: from_mud
   * arg2	: text
   */
  case INFOMSG:
    if(aber_mudbanned(arg1))
      return True;
    break;
  }
  return False;
}
#endif