/*
 * ccomm.c --
 *	Communication functions between the Frontend and the Backend.
 */

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>

#include "tmp/c.h"

RcsId ("$Header: ccomm.c,v 1.7 90/09/25 16:34:00 kemnitz Exp Locker: cimarron $");

extern	char **environ;
char **ep;
char *dp;

#ifdef notdef
char *
get_env(argv)
	char *argv;
{
	char *cp;

	int found = 0;

	if (environ)
		for (ep = environ; *ep; ep++)
			if (prefix(argv)) {
				cp = ++dp;

				found++;
			}
	if (found) 
		return (cp);
		return ("");
}

prefix(cp)
	char *cp;
{

	dp = *ep;

	while (*cp && *dp && *cp == *dp)
		cp++, dp++;
	if (*cp == 0)
		return (*dp == '=');
	return (0);
}
#endif

char *strcpy(), *ttyname();

gettty(tp)
char tp[20];
{	
	strcpy (tp, ttyname(0));
}


int
get_port()
{
	char *env, *getenv();
	int  port_no;

	env = getenv("PGPORT");

	if (env) {
		port_no = atoi(env);
	}
	else 	port_no = 4321;
	return (port_no);
}


getinaddr(sin, host, port)
struct	sockaddr_in *sin;
char	*host;
int	port;
{
	struct	hostent	*hs;

	bzero((char *)sin, sizeof *sin);
	if (host) {
		if (*host >= '0' && *host <= '9')
			sin->sin_addr.s_addr = inet_addr(host);
		else {
			if (!(hs = gethostbyname(host))) {
				perror(host);
				return(1);
			}
			if (hs->h_addrtype != AF_INET) {
				fputs(host, stderr);
				fputs(": Not Internet\n", stderr);
				return(1);
			}
			bcopy(hs->h_addr, (char *)&sin->sin_addr, hs->h_length);
		}
	}
	sin->sin_family = AF_INET;
	sin->sin_port = htons(port);
	return(0);
}

getinserv(sin, host, serv)
struct	sockaddr_in *sin;
char	*host, *serv;
{
	struct	servent	*ss;

	if (*serv >= '0' && *serv <= '9')
		return(getinaddr(sin, host, atoi(serv)));
	if (!(ss = getservbyname(serv, NULL))) {
		fputs(serv, stderr);
		fputs(": Unknown service\n", stderr);
		return(1);
	}
	return(getinaddr(sin, host, ntohs(ss->s_port)));
}

FILE	*Pfout, *Pfin;

pconnect(host, port)
char	*host, *port;
{
	struct	sockaddr_in	sin;
	int			fd, port_no;

	port_no = atoi(port);
	if (!port_no) 
		port_no = get_port();
		/* get_port() returns the environment variable PGPORT, 
		   default is 4321 */
	if (getinaddr(&sin, host, port_no))
		return(-1);
	fd = socket(AF_INET, SOCK_STREAM, 0);
	if (fd == -1) {
		return(-1);
	}
	if (connect(fd, &sin, sizeof sin) == -1)
		return(-1);
	fcntl(fd,F_SETFL,0);
	Pfout = fdopen(fd, "w");
	Pfin = fdopen(dup(fd), "r");
	return(0);
}

paccept()
{
	struct	sockaddr_in	sin;
	int			fd, nfd, i;

	if (!(fd = socket(AF_INET, SOCK_STREAM, 0)))
		return(-2);
	getinaddr(&sin, 0, 4321);
	if (bind(fd, &sin, sizeof sin))
		return(-3);
	listen(fd, SOMAXCONN);
	if ((nfd = accept(fd, NULL, NULL)) < 0)
		return(-1);
	close(fd);
	Pfout = fdopen(nfd, "w");
	Pfin = fdopen(dup(nfd), "r");
	return(0);
}

pclose()
{
	if (Pfin) {
	    fclose(Pfin);
	    Pfin = NULL;
	}
	if (Pfout) {
	    fclose(Pfout);
	    Pfout = NULL;
	}
}

pflush()
{
	if (Pfout)
	    fflush(Pfout);
}

getpstr(s, maxlen)
char	*s;
int	maxlen;
{
	int	c;

	while (maxlen-- && (c = getc(Pfin)) != EOF && c)
		*s++ = c;
	*s = '\0';
}

getpchar(s, off, maxlen)
char	*s;
int	off, maxlen;
{
	int	c;

	s += off;
	while (maxlen-- && (c = getc(Pfin)) != EOF)
		*s++ = c;
}

getpint(b)
int	b;
{
	int	n, c, p;

	n = p = 0;
	while (b-- && (c = getc(Pfin)) != EOF && p < 32) {
		n |= (c & 0xff) << p;
		p += 8;
	}
	return(n);
}

putstr(s)
char	*s;
{
	fputs(s, Pfout);
	fputc('\0', Pfout);
}

putnchar(s, n)
char	*s;
{
	while (n--)
		fputc(*s++, Pfout);
}

putint(i, b)
int	i, b;
{
	if (b > 4)
		b = 4;
	while(b--) {
		fputc(i & 0xff, Pfout);
		i >>= 8;
	}
}
