/* callsign gateway. Translates <isindex> queries to forms lookups at ualr */
/* Copyright 1995,1996 Mark Eichin <eichin@mit.edu> */
/* redistribution requires permission. */
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

int main(argc,argv)
     int argc;
     char **argv;
{
  char *query;
  int i;


  query=getenv("QUERY_STRING");

  if(argc > 1) {
    query = 0;
    i = 1;
    do {
      if (!query) {
	query=malloc(strlen(argv[i]+2));
	if (!query) return;
	*query = 0;
      } else {
	query=realloc(query,strlen(query)+strlen(argv[i])+2);
	if (!query) return;
      }
      strcat(query,argv[i]);
      strcat(query," ");
      i++;
    } while (i < argc);
    query[strlen(query)-1] = 0;	/* chop trailing space... */
  }
  do_callsign(query);
  return 0;
}

int write_str(fd,s)
     int fd;
     char *s;
{
  return write(fd,s,strlen(s));
}

int do_callsign(request)
     char *request;
{
  char *r;
  int p, st, n;

  char buf[1025];
  int rl = 0;
  char *b;
  FILE *f;

  if (request) {
    rl = strlen(request);
    if(rl > 20) {
      request = 0;
    }
  }

  if(!request || !request[0]) {
    printf("Content-type: text/html\n\n\n");
    if(rl) {
      printf("<h1>Request too long.</h1><p>\n");
    }
    printf("<isindex><h1>Enter the amateur radio callsign you wish to look up</h1>");
    printf("e.g. \"<a href=\"http://www.mit.edu:8001/callsign?n1dpu\">N1DPU</a>\" <p>");
    printf("Callsign data are provided by the United States Federal Communications Commission\n");
    printf("and the database service is provided by the <a href=\"http://www.ualr.edu/\">University of\n");
    printf("Arkansas</a> at Little Rock <a href=\"http://www.ualr.edu/~hamradio/index.html\">Amateur Radio Club.</a><p>\n");
    printf("Gateway written by <A HREF=\"/people/eichin/mwe.html\">Mark Eichin</A>\n");
    return;
  }
  for(r=request;*r;r++) if (*r == '+') *r = ' ';

  p = open_port("www.ualr.edu",80); 
/*  p = open_port("perdiem",7999);*/

  
  write_str(p,
	    "POST /htbin/callsign.exe HTTP/1.0\r\n"
	    "Accept-language: */*\r\n"
	    "Accept: text/plain, text/html\r\n"
	    "Content-type: application/x-www-form-urlencoded\r\n"
	    "User-Agent: eichin@www.mit.edu-callsign-gateway-1.1\r\n"
	    "Content-length: "
	    );
  /* we know the length is between 0 and 20, so buf is safe */
  sprintf(buf, "%d", rl+strlen("call=&name=&city=&state=&zip=&LIMIT=0100"));
  write_str(p, buf);
  
  write_str(p,
	    "\r\n"
	    "\r\n"
	    "call="
	    );
  write_str(p, request);
  write_str(p,
	    "&name=&city=&state=&zip=&LIMIT=0100\r\n"
	    );

  st = 0;

  f = fdopen(p,"r");

#if 0
  for(;;) {
    b = fgets(buf,1024,f);
    if (!b) break;
    puts(b);
  }
  fclose(f);
  close(p);
  fflush(stdout);
  return;
#endif
/*  printf("Content-type: text/html\n\n"); */

  for(;;) {
    b = fgets(buf,1024,f);
    if (!b) break;
    
    n = strlen(buf);

    /* on the first "blank" line, start forwarding */
    if ((!st)
	&& (((n == 1) && (buf[0] == '\n'))
	    || (n == 2) && (buf[0] == '\r') && (buf[1] == '\n'))) {
      st = 1;
      printf("<isindex>");
      }
    /* forward the content-type that they supplied */
    if ((!st) 
	&& !strncmp(buf, "Content-type: ", strlen("Content-type: "))) {
      if(buf[n-2] == '\r') {
	buf[n-2] = '\n';
	/* buf[n-1] = 0; */
      }
      printf("%s\n", buf);
    }
    /* forward the body */
    if (st) {
      if(buf[n-2] == '\r') {
	buf[n-2] = '\n';
	buf[n-1] = 0;
      }
      printf("%s", buf);
    }
  }
  fclose(f);
  close(p);
  fflush(stdout);
}

int open_port(server,portnum)
     char *server;
     int portnum;
{
  struct hostent *hp;
  struct sockaddr_in sin;
  int s;

  hp = gethostbyname (server);
  if (hp == NULL) {
    perror("callsign: gethostbyname");
    exit(1);
  }
  s = socket (AF_INET, SOCK_STREAM, 0);
  if (s < 0) {
    perror("callsign: socket");
    exit(1);
  }

  sin.sin_family = AF_INET;
  sin.sin_addr.s_addr = INADDR_ANY;
  sin.sin_port = 0;
  
  if (bind (s, (struct sockaddr *) &sin, sizeof sin) < 0) {
    perror("callsign: bind");
    exit(1);
  }
  memcpy (&sin.sin_addr, hp->h_addr, hp->h_length);
  sin.sin_port = htons(portnum);

  if (connect (s, (struct sockaddr *) &sin, sizeof sin) < 0) {
    perror("callsign: connect");
    close(s);
    exit(1);
  }

  return s;
}
