#include "config.h"
#include "includes.h"
#include "defs.h"
#include "protos.h"
#include "socks.h"

static char *Progname;

int main(int argc, char **argv) {
    struct sockaddr_in	sin;
    struct hostent *hp;
    struct servent *sp;
    char *cp, buf[1024], msg[2048];
    int v, n, i, s;
    u_int l;

#ifdef WHOIS_SERVER
    char *service = "whois",  *host = WHOIS_SERVER;
#else
    char *service = "finger", *host = "localhost";
#endif

    struct in_addr dstaddr[21];
    
#ifdef linux
    int optind = 1;
#else
    extern int optind;
#endif
	
    if ((Progname = strrchr(argv[0], '/')) == NULL) Progname = argv[0];
    else Progname++;

#ifdef SOCKS
    LIBPREFIX2(init)(Progname);
#endif
    
#ifdef WHOIS_SERVER
    while ((i = getopt(argc,argv,"h:")) != EOF) {
	extern char *optarg;
	
	switch (i) {
	    case 'h':
		host = optarg;
		break;
	    default:
		fprintf(stderr,"Usage: %s [-h host] name\n", Progname);
		exit(1);
	}
    }
#endif
    
    *(cp = buf) = '\0';
    for (i = optind; i < argc; i++) {
	if (i == 1 && !strcmp(argv[i], "-l")) {
	    strcat(cp, "/W ");
	    cp += 3;
	} else {
	    strcat(cp, argv[i]);
	    cp += strlen(argv[i]);
	}
    }
    
#ifndef WHOIS_SERVER
    if ((cp = strrchr(buf, '@')) != NULL) {
	*cp = '\0';
	host = cp + 1;
    } else {
	if ((cp = getenv("ORIG_FINGER")) == NULL) cp = ORIG_FINGER;
	execvp(cp, argv);
	fprintf(stderr, "Unable to run %s\n", cp);
	exit(1);
    }
#endif

    sin.sin_family = AF_INET;
    
    if ((sp = getservbyname(service, "tcp")) == NULL) {
	if ((v = atoi(service)) == 0) {
	    fprintf(stderr, "%s: unknown service '%s'\n", Progname, service);
	    exit(1);
	}
	sin.sin_port = htons((short) v);
    } else {
	sin.sin_port = sp->s_port;
    }
    
    if ((hp = gethostbyname(host)) == NULL) {
	if ((l = inet_addr(host)) == -1) {
	    fprintf(stderr, "%s: unknown host '%s'\n", Progname, host);
	    exit(1);
	}
	/* you are out of luck if your system doesn't use 2's        */
	/* complement in integer representation                      */
	sin.sin_addr.s_addr = l ;
    } else {
	for (i = 0; (i < 20) && *hp->h_addr_list; i++, hp->h_addr_list++)
	    memcpy(&(dstaddr[i].s_addr), *hp->h_addr_list, hp->h_length);
	dstaddr[i].s_addr = 0;	
	i = 0;
	sin.sin_addr.s_addr = dstaddr[i++].s_addr;
    }
    
    if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
	sprintf(msg, "%s: socket", Progname);
	perror(msg);
	exit(1);
    }
    
    while (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
	if ((errno == ETIMEDOUT) && (hp != NULL) && 
	    ((sin.sin_addr.s_addr = dstaddr[i++].s_addr) != 0)) {
	    continue;
	}
	
	sprintf(msg, "%s: connect", Progname);
	perror(msg);
	exit(1);
    }

    strcat(buf, "\r\n");
    
    if (write(s,buf,strlen(buf)) < 0) {
	sprintf(msg, "%s: write", Progname);
	perror(msg);
    }
    
    while ((n = read(s, buf, sizeof(buf) - 1)) > 0) {
	write(1, buf, n);
    }

    close(s);
    return 0;
}
