/*
    Copyright (C) 1991, Marcus J. Ranum. All rights reserved.
*/

/*
code to interface client MUDs with rwho server

this is a standalone library.
*/


#include    "os.h"

#define DGRAMPORT       6888

static int dgramfd = INVALID_SOCKET;
static char *password;
static char *localnam;
static char *lcomment;
static struct sockaddr_in addr;
time_t senttime;


/* enable RWHO and send the server a "we are up" message */
int rwhocli_setup (char *server, char *serverpw, char *myname, char *comment)
{
#ifndef NO_HUGE_RESOLVER_CODE
  struct hostent *hp;
#endif
  char pbuf[512];
  char *p;

  if (dgramfd != INVALID_SOCKET)
    return (1);

  password = malloc (strlen (serverpw) + 1);
  localnam = malloc (strlen (myname) + 1);
  lcomment = malloc (strlen (comment) + 1);
  if (password == (char *) 0 || localnam == (char *) 0 ||
    lcomment == (char *) 0)
    return (1);
  strcpy (password, serverpw);
  strcpy (localnam, myname);
  strcpy (lcomment, comment);

  p = server;
  while (*p != '\0' && (*p == '.' || isdigit (*p)))
    p++;

  if (*p != '\0') {
#ifndef NO_HUGE_RESOLVER_CODE
    if ((hp = gethostbyname (server)) == (struct hostent *) 0)
      return (1);
    (void) bcopy (hp->h_addr, (char *) &addr.sin_addr, hp->h_length);
#else
    return (1);
#endif
  } else {
#ifdef WIN32
    unsigned long f;
#else
    struct in_addr f;
#endif

#ifdef WIN32
    if ((f = inet_addr (server)) == INADDR_NONE)
      return 1;
#else
    if (inet_aton (server, &f) == 0)
      return 1;
#endif
    (void) bcopy ((char *) &f, (char *) &addr.sin_addr, sizeof (f));
  }

  addr.sin_port = htons (DGRAMPORT);
  addr.sin_family = AF_INET;

  if ((dgramfd = socket (AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET)
    return (1);

  time (&senttime);

  sprintf (pbuf, "U\t%.20s\t%.20s\t%.20s\t%.10ld\t0\t%.25s",
    localnam, password, localnam, senttime, comment);
  sendto (dgramfd, pbuf, strlen (pbuf), 0, (struct sockaddr *) &addr,
    sizeof (addr));
  return (0);
}

/* disable RWHO */
void rwhocli_shutdown (void)
{
  char pbuf[512];

  if (dgramfd != INVALID_SOCKET) {
    sprintf (pbuf, "D\t%.20s\t%.20s\t%.20s", localnam, password, localnam);
    sendto (dgramfd, pbuf, strlen (pbuf), 0, (struct sockaddr *) &addr,
      sizeof (addr));
    close (dgramfd);
    dgramfd = -1;
    free (password);
    free (localnam);
  }
}

/* send an update ping that we're alive */
void rwhocli_pingalive (void)
{
  char pbuf[512];

  if (dgramfd != INVALID_SOCKET) {
    sprintf (pbuf, "M\t%.20s\t%.20s\t%.20s\t%.10ld\t0\t%.25s",
      localnam, password, localnam, senttime, lcomment);
    sendto (dgramfd, pbuf, strlen (pbuf), 0, (struct sockaddr *) &addr,
      sizeof (addr));
  }
}

/* send a "so-and-so-logged in" message */
void rwhocli_userlogin (char *uid, const char *name, time_t tim)
{
  char pbuf[512];

  if (dgramfd != INVALID_SOCKET) {
    sprintf (pbuf, "A\t%.20s\t%.20s\t%.20s\t%.20s\t%.10ld\t0\t%.20s",
      localnam, password, localnam, uid, tim, name);
    sendto (dgramfd, pbuf, strlen (pbuf), 0, (struct sockaddr *) &addr,
      sizeof (addr));
  }
}

/* send a "so-and-so-logged out" message */
void rwhocli_userlogout (char *uid)
{
  char pbuf[512];

  if (dgramfd != INVALID_SOCKET) {
    sprintf (pbuf, "Z\t%.20s\t%.20s\t%.20s\t%.20s",
      localnam, password, localnam, uid);
    sendto (dgramfd, pbuf, strlen (pbuf), 0, (struct sockaddr *) &addr,
      sizeof (addr));
  }
}