#include <io.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include "pcdefs.h"
#include "in.h"
#include "protocol.h"
#include "net.h"

struct tcpport sock1, sock2;
unsigned long far Sdomain(char *mname, unsigned int timeout);
extern void _far netsleep(void);
extern void ruserpass(char *host, char **pname, char **ppass);
extern u_long inet_addr(char *name);

int
rexec(ahost, rport, name, pass, cmd, fd2p)
	char **ahost;
	int rport;
	char *name, *pass, *cmd;
	int *fd2p;
{
	int s, i, s2;
	struct sockaddr sin, from;
	char c;
	short port;
	unsigned long haddr;

	haddr = inet_addr(*ahost);
	if (haddr == (u_long)-1) {
	    haddr = Sdomain(*ahost, 36);
	    if (haddr == 0) {
		    fprintf(stderr, "%s: unknown host\n", *ahost);
		    return (-1);
	    }
	}
	ruserpass(*ahost, &name, &pass);
	s = Socket(SOCK_STREAM, &sin, 0, (struct port far *)&sock1);
	if (s < 0) {
		fprintf(stderr, "Can't get socket\n");
		return (-1);
	}
	SoBind(s, 0);
	sin.addr = haddr;
	sin.port = rport;
	if ((i = SoConnect(s, &sin)) < 0) {
		if (i == -11)
			fprintf(stderr, "%s: Connection timed out\n", *ahost);
		else if (i == -10)
			fprintf(stderr, "%s: Connection refused\n", *ahost);
		else if (i == -2)
			fprintf(stderr, "No response from host or gateway.\n");
		else
			fprintf(stderr, "Connect returns %d\n", i);
		SoFree(s);
		return -1;
	}
	if (fd2p == 0) {
		(void) SoWrite(s, "", 1);
		port = 0;
	} else {
		char num[8];
		
		s2 = Socket(SOCK_STREAM, &sin, 0, (struct port far *)&sock2);
		if (s2 < 0) {
			port = 0;
			goto bad;
		}
		SoBind(s2, 0);
		SoListen(s2);
		port = ntohs(sock2.inport);
		(void) sprintf(num, "%d", port);
		(void) SoWrite(s, num, strlen(num)+1);
		for (;;) {
		    netsleep();
		    i = SoAccept(s2, &from);
		    if (i < 0) {
			fprintf(stderr, "SoAccept returns %d\n", i);
			port = 0;
			goto bad;
		    }
		    if (i > 0)
			break;
		}
		*fd2p = s2;
	}
	(void) SoWrite(s, name, strlen(name) + 1);
	/* should public key encypt the password here */
	(void) SoWrite(s, pass, strlen(pass) + 1);
	(void) SoWrite(s, cmd, strlen(cmd) + 1);
	for (;;) {
	    netsleep();
	    i = SoRead(s, &c, 1);
	    if (i < 0) {
		fprintf(stderr, "%s closed the connection.\n", *ahost);
		goto bad;
	    }
	    if (i == 1)
		break;
	}
	if (c != 0) {
	    for (;;) {
		netsleep();
		i = SoRead(s, &c, 1);
		if (i < 0)
		    break;
		if (i == 1) {
		    (void) write(2, &c, 1);
		    if (c == '\n')
			break;
		}
	    }
	    goto bad;
	}
	return (s);
bad:
	if (port)
		SoClose(*fd2p);
	SoClose(s);
	netsleep();
	netsleep();
	if (port)
		SoFree(*fd2p);
	SoFree(s);
	return (-1);
}
