#include <stdlib.h>
#include <io.h>
#include <conio.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#include <dos.h>
#include "pcdefs.h"
#include "protocol.h"
#include "net.h"

#define TCP_EXEC	0x0002

void tcp_shut(void);
void onint();

extern int configure(char *cp, struct conf *dp);
extern int Sdominit(void);
extern int rexec(char **ahost, int rport, char *name, char *pass,
		char *cmd, int *fd2);
extern void _far netsleep(void);

int fd2;
int nflag = 0;
int active = 0;
extern struct conf far Scon;

int
main(argc, argv)
char **argv;
{
    int rem;
    char *host=0, *user=0, *passwd=0;
    char cmd[128];
    int cmd_len = 0;	/* number of characters in cmd */
    int n, i;
    char buf[512];
    int tty = isatty(0);

    argc--; argv++;
    host = *argv;
    if (!host)
	goto usage;
    argc--; argv++;
    while(argc > 0 && argv[0][0] == '-') {
	switch(argv[0][1]) {
	    case 'l':
		if (argv[0][2])
		    user = argv[0]+2;
		else {
		    argv++; argc--;
		    if (argc)
			user = argv[0];
		    else
			goto usage;
		}
		break;
	    case 'n':
		nflag++;
		break;
	    case 'p':
		if (argv[0][2])
		    passwd = argv[0]+2;
		else {
		    argv++; argc--;
		    if (argc)
			passwd = argv[0];
		    else
			goto usage;
		}
		break;
	    case '\0':
		argv++; argc--;
		goto done;
	    default:
		goto usage;
	}
	argv++; argc--;
    }
done:
    if (argc < 1) {
usage:
	fprintf(stderr, "Usage: rexec hostname [-n] [-l username] [-p passwd] command-line\n");
	exit(1);
    }
    strcpy(cmd, argv[0]);
    argv++;
    while(--argc) {
	strcat(cmd, " ");
	strcat(cmd, *argv++);
    }

    if (configure((char far *)0, &Scon) < 0) {
	fprintf(stderr, "ERROR: reading config.tel\n");
	exit (1);
    }
    i = Snetinit();
    if (i < 0) {
	fprintf(stderr, "Snetinit returns %d\n", i);
	exit (1);
    }
    onexit(tcp_shut);
    i = Sdominit();
    if (i < 0) {
	fprintf(stderr, "Sdominit returns %d\n", i);
	exit(1);
    }
    signal(SIGINT, onint);
#ifdef STDERR
    rem = rexec(&host, TCP_EXEC, user, passwd, cmd, &fd2);
#else
    rem = rexec(&host, TCP_EXEC, user, passwd, cmd, 0);
#endif
    if (rem < 0)
	exit(rem);
#ifdef STDERR
    active = 3;
#else
    active = 1;
#endif
    if (nflag) {
	SoClose(rem);
	tty = 0;
	cmd_len = -1;
    }

    /* We just reuse these variables.  They don't mean what they did above. */
    user = cmd;
    do {
	netsleep();
	if (tty) {
	    if (kbhit()) {
		n = getch();
		switch (n) {
		    case '\b':
			if (user > cmd) {
			    user--;
			    /* erase the '^' */
			    if (*user < ' ')
				_dos_write(0, "\b \b", 3, &i);
			    _dos_write(0, "\b \b", 3, &i);
			}
			break;
		    case '\r':
			n = (int)'\n';
		    case '\n':
			cputs("\r\n");
			/* check for a single control-Z */
			if (user == &cmd[1] && cmd[0] == '\032') {
			    SoClose(rem);
			} else {
			    *user++ = (char)n;
			    (void)SoWrite(rem, cmd, user - cmd);
			}
			user = cmd;
			break;
		    case '\033':
			while (user > cmd) {
			    user--;
			    if (*user < ' ')
				_dos_write(0, "\b \b", 3, &i);
			    _dos_write(0, "\b \b", 3, &i);
			}
			break;
		    default:
			if (n < ' ') {
			    buf[0] = '^';
			    buf[1] = (char)(n | 0x40);
			    _dos_write(0, buf, 2, &i);
			} else {
			    buf[0] = (char)n;
			    _dos_write(0, buf, 1, &i);
			}
			*user++ = (char)n;
			break;
		}
	    }
	} else {
	    if (!cmd_len) {
		cmd_len = fread(cmd, 1, sizeof cmd, stdin);
		if (cmd_len == 0) {
		    SoClose(rem);
		    cmd_len = -1;
		}
		user = cmd;
	    }
	    if (cmd_len > 0) {
		n = SoWrite(rem, user, &cmd[cmd_len] - user);
		if (n < 0)
		    return 0;
		user += n;
		if (user == &cmd[cmd_len])
		    cmd_len = 0;
	    }
	}
	if (active & 1) {
	    n = SoRead(rem, buf, sizeof buf);
	    if (n < 0)
		active &= ~1;
	    if (n > 0) {
		write(1, buf, n);
	    }
	}
#ifdef STDERR
	if (active & 2) {
	    n = SoRead(fd2, buf, sizeof buf);
	    if (n < 0)
		active &= ~2;
	    if (n > 0) {
		write(2, buf, n);
	    }
	}
#endif
    } while (active);
    return 0;
}

void
tcp_shut()
{
	Snetshut();
}

void
onint()
{
    signal(SIGINT, onint);
    if (active & 2) {
	SoWrite(fd2, "\2", 1);
    } else {
	Snetshut();
	exit(1);
    }
}
