/*
** idlookup.c                   A tool to look up Identifier tokens for
**                              a connection
**
** Version: 1.2
**
** This program is in the public domain and may be used freely by anyone
** who wants to. 
**
** Last update: 3 July 1992
**
** Author: Peter Eriksson <pen@lysator.liu.se>
*/
#include <stdio.h>
#include <ctype.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>


char *argv0;


/*
** Convert a character to uppercase if it is lowercase,
** else just return it. (Some implementations of the
** toupper() macro/function breaks if it is put into use
** on non-lowercase characters...)
*/
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;
}


/*
** Print an error and exit
*/
Perror(str)
  char *str;
{
  fprintf(stderr, "%s: ", argv0);
  perror(str);
  exit(1);
}


main(argc,argv)
  int argc;
  char *argv[];
{
  int fd;
  struct hostent *hp;
  struct servent *sp;
  struct sockaddr_in addr;
  int addrlen;
  FILE *fp_in, *fp_out;
  int lport, fport;
  char buffer[8192];
  char reply_type[81];
  char opsys_or_error[81];
  char identifier[1024];
  char charset[81];
  char opsys[81];
  
  
  
  if (argc != 4)
  {
    printf("usage: %s {host-or-ip-number} {local-port} {foreign-port}",
	   argv[0]);
    exit(1);
  }

  argv0 = argv[0];
  
  fd = socket(AF_INET, SOCK_STREAM, 0);
  if (fd == -1)
    Perror("socket");

  addr.sin_family = AF_INET;
  if (isdigit(argv[1][0]))
    addr.sin_addr.s_addr = inet_addr(argv[1]);
  else
  {
    if((hp = gethostbyname(argv[1])) == NULL)
    {
      fprintf(stderr, "%s: host not found (%s)\n", argv[0], argv[1]);
      exit(1);
    }
    
    memcpy(&addr.sin_addr, hp->h_addr, sizeof(addr.sin_addr));
  }
  addr.sin_port = htons(113);
  addrlen = sizeof(addr);

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

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

  if (isdigit(argv[2][0]))
    lport = atoi(argv[2]);
  else
  {
    if ((sp = getservbyname(argv[2], "tcp")) == NULL)
    {
      fprintf(stderr, "%s: service not found (%s)\n", argv[0], argv[2]);
      exit(1);
    }

    lport = ntohs(sp->s_port);
  }

  if (isdigit(argv[3][0]))
    fport = atoi(argv[3]);
  else
  {
    if ((sp = getservbyname(argv[3], "tcp")) == NULL)
    {
      fprintf(stderr, "%s: service not found (%s)\n", argv[0], argv[3]);
      exit(1);
    }

    fport = ntohs(sp->s_port);
  }

  fp_in  = fdopen(fd, "r");
  fp_out = fdopen(fd, "w");
  if (!fp_in || !fp_out)
    Perror("fdopen");

  fprintf(fp_out, "%d , %d\n", lport, fport);
  fflush(fp_out);
  shutdown(fd, 1);


  if (fgets(buffer, sizeof(buffer)-1, fp_in) == NULL)
    Perror("fgets");

  argc = sscanf(buffer, " %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);
    exit(1);
  }

  opsys[0] = charset[0] = '\0';
  if (sscanf(opsys_or_error, " %s , %s", opsys, charset) != 2)
    strcpy(opsys, opsys_or_error);
  
  if (Stricmp(reply_type, "ERROR") == 0)
  {
    if (Stricmp(opsys_or_error, "INVALID-PORT") == 0)
      fprintf(stderr, "%s: invalid port(s) specified (%d , %d)\n",
              argv[0], lport, fport);
    else if (Stricmp(opsys_or_error, "NO-USER") == 0)
      fprintf(stderr, "%s: connection not in use (%d , %d)\n",
              argv[0], lport, fport);
    else if (Stricmp(opsys_or_error, "UNKNOWN-ERROR") == 0)
      fprintf(stderr, "%s: unknown error\n", argv[0]);
    else if (Stricmp(opsys_or_error, "USER-REJECTED") == 0)
      fprintf(stderr, "%s: user rejected\n", argv[0]);
    else
      fprintf(stderr, "%s: unknown error: %s\n", argv[0], opsys_or_error);

    exit(2);
  }
  else if (Stricmp(reply_type, "USERID") != 0)
  {
    fprintf(stderr, "%s: protocol error: %s\n", argv[0], reply_type);
    exit(3);
  }

  printf("Identifier: %s\n", identifier);
  printf("Opsys:      %s\n", opsys);
  if (charset[0])
    printf("Charset:    %s\n", charset);

  fclose(fp_out);
  fclose(fp_in);
}


