/*
    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 SOCKET 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 ((int)*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 {
    unsigned long f;

    if ((f = inet_addr (server)) == INADDR_NONE)
      return (1);
    (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%.10d\t0\t%.25s",
    localnam, password, localnam, (int)senttime, comment);
  sendto (dgramfd, pbuf, strlen (pbuf), 0,  (const struct sockaddr*)&addr, sizeof (addr));
  return (0);
}

/* disable RWHO */
int 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, (const struct sockaddr*)&addr, sizeof (addr));
    close (dgramfd);
    dgramfd = INVALID_SOCKET;
    free (password);
    free (localnam);
  }
  return (0);
}

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

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

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

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

/* send a "so-and-so-logged out" message */
int 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,  (const struct sockaddr*)&addr, sizeof (addr));
  }
  return (0);
}