/*
** An ident server query daemon, built off of the pidentd test1.c
** program by Peter Eriksson <pen@lysator.liu.se>
**
** Last modified: 5 Feb 1994
**
** Rationale: Sometimes people, particularly in the context of muds,
** hide behind veils of anonymity, as they do things which they
** might not do in other circumstances. This addition should make
** it easier to know which user at a machine is logging into your
** mud, and you can then provide more information to whatever
** administrators you come across in your search for justice. It
** is better that the few spoil things for the few, rather than the
** many.
**
** This runs as a separate program because it opens many descriptors
** (multiplexes queries), and most muds are short on descriptors
** anyway. It also makes it harder for people to mess up your mud by
** creating "strange" ident servers on their own machines.
**
** Be aware that this program is only as good as the servers it connects
** to. Somone who is root can make it look like there are many
** people online, when there's only one.
*/


#include <sys/time.h>

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <stdio.h>

#define IDNTPORT 113

int Toupper(c)
  int c;
{
  if (islower(c))
    return toupper(c);
  else
    return c;
}


/*
** Compare two strings, case insensitive
*/
int Stricmp(s1, s2)
  char *s1, *s2;
{
  int diff;


  while (!(diff = Toupper(*s1) - Toupper(*s2)) && *s1)
    s1++, s2++;

  return diff;
}



main(argc,argv)
  int argc;
  char *argv[];
{
  int fd;
  struct sockaddr_in addr;
  int addrlen;
  int port;
  FILE *fp_in, *fp_out;
  int lport, fport;
  char buffer[8192];
  char reply_type[81];
  char opsys_or_error[81];
  char identifier[1024];
  
  
    /* Assuming:
     *  stdin - read from calling program
     *  stdout - write to calling program
     *
     * Calling program has responsibility to create descriptors and
     * dup2() them between fork() and exec()
     */

  
  fd = socket(AF_INET, SOCK_STREAM, 0);
  if (fd == -1)
    perror("socket");

  addr.sin_family = AF_INET;
  if(argc > 1)
    addr.sin_addr.s_addr = inet_addr(argv[1]);
  else
    addr.sin_addr.s_addr = inet_addr("127.0.0.1");

  addr.sin_port = htons(...);
  addrlen = sizeof(addr);

  if (connect(fd, &addr, addrlen) == -1)
    perror("connect");

  addrlen = sizeof(addr);
  if (getsockname(fd, &addr, &addrlen) == -1)
    perror("getsockname");

}

void send_query()
{
  fp_in  = fdopen(fd, "r");
  fp_out = fdopen(fd, "w");
  if (!fp_in || !fp_out)
    perror("fdopen");

  fprintf(fp_out, "%d , %d\n", other_port, mud_port);
  fflush(fp_out);
}

void get_answer(struct descriptor *d)
{
  shutdown(fd, 1);

  argc = sscanf(d->, "%d , %d : %[^ \t\n\r:] : %[^ \t\n\r:] : %[^\n\r]",
		&lport, &fport, reply_type, opsys_or_error, identifier);
  if (argc < 3)
  {
    fprintf(stderr, "fscanf: too few arguments (%d)\n", argc);
    return;
  }
  if (Stricmp(reply_type, "ERROR") == 0)
  {
    printf("Ident error: error code: %s\n", opsys_or_error);
    exit(1);
  }
  else if (Stricmp(reply_type, "USERID") != 0)
  {
    printf("Ident error: illegal reply type: %s\n", reply_type);
    exit(1);
  }
  else
    printf("Ident returned: Opsys=%s, Identifier: %s\n",
	   opsys_or_error, identifier);

  fclose(fp_out);
  fclose(fp_in);

} /* for(;;) */
}