    /*********************************************************************\
    *  Copyright (c) 1993 by Michael Meskes                               *
    *  (meskes@ulysses.informatik.rwth-aachen.de)                         *
    *                                                                     *
    *  You may copy or modify this file in any manner you wish, provided  *
    *  that this notice is always included, and that you hold the author  *
    *  harmless for any loss or damage resulting from the installation or *
    *  use of this software.                                              *
    \*********************************************************************/

#include <stdio.h>
#include <strings.h>
#ifndef vax
#include <malloc.h>
#endif
#include <pwd.h>
#ifndef vax
#include <unistd.h>
#endif
#include "common_def.h"
#include <ctype.h>

#if HOST_LOOKUP
#include <netdb.h>

#endif

#ifdef VMS
# define STAT vms_stat
#else
# define STAT stat
#endif

#define NUMBER 1
#define NAME 2

int delay = -1, local_port = -1, timeout = -1, trace = -1, port = -1;
char *local_dir = NULL, *filename = NULL, *password = NULL;
char *hostname = NULL, *hostaddr = NULL, *dir = NULL;

extern char *optarg;
extern int optind;

extern char *inet_ntoa();
extern long inet_addr();

extern char *strstr();

char *buffer=0L,*home;

void usage_fhost() /* print usage message */
{
   fprintf(stderr,"Usage: fhost [-d delay] [-p local port] [-l local dir]\n                [-o timeout] [-t trace] [-w password] [-f filename]\n                [-h [number|name]] [host port [directory] | abbreviation]\n");
   exit(0);
}

char *load_file(filename) /* load resource file */
char *filename;
{
    FILE *stream;
    long i,length;
    struct stat sf;
    char *f1=".fsp_prof", *f2=0L, *f3=FSPRC;

    if (!filename)
    {
	if (!STAT(f1,&sf)) filename=f1;
	else
	{
	    f2=(char *)malloc (strlen(home) + 7);
	    if (!f2)
	    {
		perror("malloc");
		return(0L);
	    }
	    sprintf (f2,"%s/.fsp_prof",home);
	    if (!STAT(f2,&sf)) filename=f2;
	    else filename=f3;
	}
    }
    stream=fopen(filename,"r");
    if (!stream)
    {
	perror(filename);
	if (f2) free(f2);
	return(0L);
    }
    i=fseek(stream,0L,2);
    if (i)
    {
        perror("fseek");
        fclose(stream);
	if (f2) free(f2);
	return(0L);
    }
    length=ftell(stream);
    if (!length)
    {
	perror("ftell");
	fclose(stream);
	if (f2) free(f2);
        return(0L);
    }
    buffer=(char *)calloc(length,sizeof(char));
    if (!buffer)
    {
	perror("malloc");
        fclose(stream);
	if (f2) free(f2);
        return(0L);
    }
    i=fseek(stream,0L,0);
    if (i)
    {
	perror("fseek");
	free(buffer);
        fclose(stream);
	if (f2) free(f2);
        return(0L);
    }
    fread(buffer,(long)sizeof(char),length,stream);
    if (ferror(stream))
    {
	perror("fread");
	free(buffer);
        fclose(stream);
	if (f2) free(f2);
        return(0L);
    }
    i=fclose(stream);
    if (i)
    {
	perror("fclose");
	free(buffer);
	if (f2) free(f2);
	return(0L);
    }
    if (f2) free(f2);
    return(buffer);
}

void parse_file(filename, abb) /* get data out of resource file */
char *filename, *abb;
{
    char *ptrh,*ptrp,*ptra,*ptre;
    int found=0;

    ptrh=buffer=load_file(filename);
    if (!buffer) exit(1);
    while ((ptrh=(char *)strstr(ptrh,"host ")) && !found)
    {
	ptrh+=5;
	for (ptre=ptrh;*ptre!='\n';ptre++);
        ptra=(char *)strstr(ptrh,abb);
	if (ptra && ptra<ptre)
	{
	    found=1;
	   /* get host name or number */
	    for (ptrp=ptrh;!hostname && *ptrp!=' ' && *ptrp!='\n';ptrp++)
		if (!isdigit(*ptrp) && *ptrp!='.') hostname=ptrh;
	    if (!hostname) hostaddr=ptrh;
	   /* does the othe one exist, too? */
	    for (;*ptrp!=' ' && *ptrp!='\n';ptrp++);
	    for (;*ptrp==' ';ptrp++); 
	    if (*ptrp!='\n')
	    {
		if (hostaddr) hostname=ptrp;
		else if (hostname)
		{
		   hostaddr=ptrp;
		   for (;*ptrp!=' ' && *ptrp!='\n';ptrp++)
			if (!isdigit(*ptrp) && *ptrp!='.')
	    		{
			   fprintf(stderr,
				   "fhost: syntax error in setup file\n");
			   free(buffer);
			   exit(1);
	    		}
		}
	    }
	    for (ptrh++;*ptrh!='\n';ptrh++);
	    ptrp=(char *)strstr(ptrh,"fsp port ");
	    if (!ptrp)
	    {
		fprintf(stderr,"fhost: syntax error in setup file\n");
		free(buffer);
		exit(1);
	    }
	    port=atol(ptrp+9);
	    ptre=(char *)strstr(ptrh,"host "); /* begin next host */
	   /* search for environment values */
	    if (delay==-1)
	    {
		ptra=(char *)strstr(ptrh,"delay ");
		if (ptra && (!ptre || ptra<ptre)) delay=atol(ptra+6);
	    }
	    if (timeout==-1)
	    {
		ptra=(char *)strstr(ptrh,"timeout ");
		if (ptra && (!ptre || ptra<ptre)) timeout=atol(ptra+8);
	    }
	    if (trace==-1)
	    {
		ptra=(char *)strstr(ptrh,"trace ");
		if (ptra && (!ptre || ptra<ptre))
		{
			for (ptra+6;*ptra!='o' && *ptra!='\n';ptra++);
			if (*ptra=='o') trace=(ptra[1]=='n') ? 1 : 0;
	   		else
			{
			   fprintf(stderr,
				   "fhost: syntax error in setup file\n");
	   		   free(buffer);
			   exit(1);
			}
		}
	    }
	    if (local_port==-1)
	    {
		ptra=(char *)strstr(ptrh,"local port ");
		if (ptra && (!ptre || ptra<ptre)) local_port=atol(ptra+11);
	    }
	    if (local_dir==0L)
	    {
		ptra=(char *)strstr(ptrh,"local directory ");
		if (ptra && (!ptre || ptra<ptre)) local_dir=ptra+16;
	    }
	    if (dir==0L)
	    {
		ptra=(char *)strstr(ptrh,"fsp directory ");
		if (ptra && (!ptre || ptra<ptre)) dir=ptra+14;
	    }
	    if (password==0L)
	    {
		ptra=(char *)strstr(ptrh,"password ");
		if (ptra && (!ptre || ptra<ptre)) password=ptra+16;
	    }
	}
    }
    if (!found) fprintf(stderr,"host %s not found\n",abb);
    return;
}

void list_file(filename) /* list resource file */
char *filename;
{
    char *ptrh,*ptrp,*ptre;

    ptrh=buffer=load_file(filename);
    if (!buffer) exit(1);
    while (ptrh=(char *)strstr(ptrh,"host "))
    {
	ptrh+=5;
	fprintf(stderr,"host: ");
	for (;*ptrh!='\n';ptrh++) fprintf(stderr,"%c",*ptrh);
	ptrp=(char *)strstr(ptrh,"fsp port ");
	ptre=(char *)strstr(ptrh,"host ");
	if (!ptrp || (ptre && ptrp>=ptre))
	{
	   fprintf(stderr,"fhost: syntax error in setup file\n");
	   free(buffer);
	   exit(1);
	}
	fprintf(stderr," port: ");
	for (ptrp+=9;*ptrp!='\n';ptrp++) fprintf(stderr,"%c",*ptrp);
	fprintf(stderr,"\n\n");
    }
    return;
}

main(argc,argv,envp)
    int argc;
    char **argv,**envp;
{
    int optletter,csh,host=0;
    register char *p;
    char *log,*homedir="/";
    struct passwd *pw=0L;
    struct hostent *hp;
    long addr;

    log = (char *)getlogin();
    if (log) pw = getpwnam(log);
    if (!pw) pw = getpwuid(getuid());
    if (pw)
    {
       /*
    	* Figure out what shell we're using.  A hack, we look for a shell
    	* ending in "csh".
    	*/
	csh = !strcmp(pw->pw_shell + strlen(pw->pw_shell) - 3, "csh");
        home = pw->pw_dir;   /* for default search for file .fsp_prof*/
    }
    while ((optletter=getopt(argc, argv,"d:p:l:t:o:f:h:w:")) != EOF)
        switch (optletter)
        {
        case 'd':       delay=atol(optarg); /* FSP_DELAY */
                	break;
        case 'p':       local_port=atol(optarg); /* FSP_LOCAL_PORT */
                	break;
        case 'w':       password=optarg; /* FSP_PASSWORD */
                	break;
        case 'l':       local_dir=optarg; /* FSP_LOCAL_DIR */
                	break;
        case 'o':       timeout=atol(optarg); /* FSP_TIMEOUT */
                	break;
        case 't':       if (!strcmp(optarg,"on")) trace=1;  /* FSP_TRACE */
			else if (!strcmp(optarg,"off")) trace=0;
			else usage_fhost();
			break;
	case 'f':	filename=optarg; /* file name */
			break;
	case 'h':	if (!strcmp(optarg,"number")) host=NUMBER; /* host mode */
			else if (!strcmp(optarg,"name")) host=NAME;
			else usage_fhost();
			break;
	default:	usage_fhost();
			break;
        }

    if(argc > optind+1 && !filename) /* host and port and no filename given */
    {
	for (p=argv[optind];!hostname && *p && *p!='\n';p++)
	   if (!isdigit(*p) && *p!='.') hostname=argv[optind];
        if (!hostname) hostaddr=argv[optind];
	port=atol(argv[optind+1]);
	if (argc > optind + 1) dir=argv[optind+2]; /* directory given, too */
    }
    else if (argc > optind) /* abbreviation given */
    {
	parse_file(filename, argv[optind]);
    }
    else /* list or set command-line options */
    {
	if (filename || argc==1) /* list only */
	{
	   list_file(filename);
	   exit(0);
	}
    }
    if (delay>=0)
    {
	if (csh) printf("setenv FSP_DELAY %d;\n",delay);
	else printf("FSP_DELAY=%d;\nexport FSP_DELAY;\n",delay);
    }
    if (local_port>=0)
    {
	if (csh) printf("setenv FSP_LOCALPORT %d;\n",local_port);
	else printf("FSP_LOCALPORT=%d;\nexport FSP_LOCALPORT;\n",local_port);
    }
    if (trace>=0)
    {
	if (csh)
	{
	   if (trace) printf("setenv FSP_TRACE;\n");
	   else printf("unsetenv FSP_TRACE;\n");
	}
	else
	{
	   if (trace) printf("FSP_TRACE;\nexport FSP_TRACE;\n");
	   else printf("unset FSP_TRACE;\n");
	}
    }
    if (timeout>=0)
    {
	if (csh) printf("setenv FSP_TIMEOUT %d;\n",timeout);
	else printf("FSP_TIMEOUT=%d;\nexport FSP_TIMEOUT;\n",timeout);
    }
    if (port>=0)
    {
	if (csh) printf("setenv FSP_PORT %d;\n",port);
	else printf("FSP_PORT=%d;\nexport FSP_PORT;\n",port);
    }
    if (local_dir)
    {
	if (csh) printf("setenv FSP_LOCAL_DIR ");
	else printf("FSP_LOCAL_DIR=");
	for (p=local_dir;*p && *p!='\n' && *p!=' ';p++) printf("%c",*p);
	if (csh) printf(";\n");
	else printf(";\nexport FSP_LOCAL_DIR;\n");
    }
    if (password)
    {
	if (csh) printf("setenv FSP_PASSWORD ");
	else printf("FSP_PASSWORD=");
	for (p=password;*p && *p!='\n' && *p!=' ';p++) printf("%c",*p);
	if (csh) printf(";\n");
	else printf(";\nexport FSP_PASSWORD;\n");
    }
    if (hostname || hostaddr)
    {
	if (csh) printf("setenv FSP_HOST ");
	else printf("FSP_HOST=");
	/* we need a correct ending here */
	if (hostname)
	{
		for (p=hostname;*p && *p!='\n' && *p!=' ';p++);
		*p=0;
	}
	if (hostaddr)
	{
		for (p=hostaddr;*p && *p!='\n' && *p!=' ';p++);
		*p=0;
	}
	if (host==NAME && !hostname) /* look for name if compiled to do so */
	{
#if HOST_LOOKUP
	   addr=inet_addr(hostaddr);
    	   if (hp=gethostbyaddr((char *) &addr, sizeof(addr), AF_INET))
		hostname=hp->h_name;
#endif
	   if (!hostname) host=NUMBER;
	}
	if (host==NUMBER && !hostaddr) /* look for number */
	{
#if HOST_LOOKUP
	   if (hp=gethostbyname(hostname))
		hostaddr=inet_ntoa(*(struct in_addr *) * hp->h_addr_list);
#endif
	   if (!hostaddr) host=NAME;
	}
	if (!host)
	{
	   if (hostaddr) host=NUMBER;
	   else if (hostname) host=NAME;
	   else
	   {
		fprintf(stderr,"fhost: No host given!");
		if (buffer) free(buffer);
		exit(1);
	   }
	}
	printf("%s",(host==NAME) ? hostname : hostaddr);
	if (csh) printf(";\n");
	else printf(";\nexport FSP_HOST;\n");
	if (!dir) dir=homedir; /* if host is set we need this */
    }
    if (dir)
    {
	if (csh) printf("setenv FSP_DIR ");
	else printf("FSP_DIR=");
	for (p=dir;*p && *p!='\n' && *p!=' ';p++) printf("%c",*p);
	if (csh) printf(";\n");
	else printf(";\nexport FSP_DIR;\n");
    }
    if (csh) printf("setenv FSP_NAME \"");
    else printf("FSP_NAME=\"");
    if (hostname)
        for (p=hostname;*p && *p!='\n' && *p!=' ';p++) printf("%c",*p);
    if (csh) printf("\";\n");
    else printf("\";\nexport FSP_NAME;\n");
    if (buffer) free(buffer);
    exit(0);
}
