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

#include    "os.h"

#ifdef WIN32
#include "getopt.h"
#endif

#define STREAMPORT      6889

#define ENVHOST     "MUDWHOSERVER"
#define ENVPORT     "MUDWHOPORT"

int usage (void);

int main (int ac, char *av[])
{
  struct sockaddr_in addr;
  struct hostent *hp;
  int fd;
  char *p;
  int red;
  char rbuf[1024];
  char *srv = (char *) 0;
  int portnum = STREAMPORT;
  char *checkwho = (char *) 0;
  char *checkmud = (char *) 0;

  srv = getenv (ENVHOST);
  if ((p = getenv (ENVPORT)) != (char *) 0)
    portnum = atoi (p);

  while ((red = getopt (ac, av, "S:P:u:m:")) != EOF) {
    switch (red) {
    case 'S':
      srv = optarg;
      break;

    case 'P':
      portnum = atoi (optarg);
      break;

    case 'u':
      checkwho = optarg;
      break;

    case 'm':
      checkmud = optarg;
      break;

    default:
      return (usage ());
    }
  }

  if (srv == (char *) 0) {
    fprintf (stderr, "rwho server host must be provided [-S host]\n");
    return (1);
  }

  if (checkmud != (char *) 0 && checkwho != (char *) 0) {
    fprintf (stderr, "You can only search for one user or MUD entry\n");
    return (1);
  }

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

  /* not all digits or dots */
  if (*p != '\0') {
#ifndef NO_HUGE_RESOLVER_CODE
    if ((hp = gethostbyname (srv)) == (struct hostent *) 0) {
      fprintf (stderr, "unknown host %s\n", srv);
      WIN32CLEANUP
      return (1);
    }

    (void) bcopy (hp->h_addr, (char *) &addr.sin_addr, hp->h_length);
#else
    fprintf (stderr, "must use numerical notation for host name\n");
    WIN32CLEANUP
    return (1);
#endif
  } else {
#ifdef WIN32
    unsigned long f;
#else
    struct in_addr f;
#endif

#ifdef WIN32
    if ((f = inet_addr (srv)) == INADDR_NONE) {
#else
    if (inet_aton (srv, &f) == 0) {
#endif
      fprintf (stderr, "unknown host %s\n", srv);
      WIN32CLEANUP
      return (1);
    }
    (void) bcopy ((char *) &f, (char *) &addr.sin_addr, sizeof (f));
  }

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

  if ((fd = socket (AF_INET, SOCK_STREAM, 0)) < 0) {
    perror ("socket");
    WIN32CLEANUP
    return (1);
  }

  if (connect (fd, (struct sockaddr *) &addr, sizeof (addr)) < 0) {
    perror ("connect");
    WIN32CLEANUP
    return (1);
  }


  /* send request if one */
  if (checkmud != (char *) 0 || checkwho != (char *) 0) {
    char xuf[512];
    int xlen;

    sprintf (xuf, "%s=%.30s",
      checkmud == (char *) 0 ? "who" : "mud",
      checkmud == (char *) 0 ? checkwho : checkmud);

    xlen = strlen (xuf) + 1;
    if (send (fd, xuf, xlen, 0) != xlen) {
      perror ("write to rwho server failed");
      WIN32CLEANUP
      return (1);
    }
  }


  while ((red = recv (fd, rbuf, sizeof (rbuf), 0)) > 0)
    send (1, rbuf, red, 0);

  WIN32CLEANUP
  return (0);
}



int usage (void)
{
  fprintf (stderr,
    "usage: mudwho [-S server] [-P servport] [-u user] [-m mud]\n");
  fprintf (stderr, "\twhere user is someone to scan for\n");
  fprintf (stderr, "\tmud is a specific MUD to scan for\n");
  fprintf (stderr, "\t%s and %s can be set in the environment\n", ENVPORT,
    ENVHOST);
  return (1);
}