#ifndef lint
static char *RCSid = "$Header: /usr/brule/guest/empire/empire/emprcs/client/servercmd.c,v 2.6 1995/10/11 03:07:43 empire Exp $";
#endif /* not lint */

/*
 * servercmd.c
 *
 * Change the state depending on the command from the server.
 *
 * Dave Pare, 1989
 */

#include "misc.h"
#include "proto.h"
#include "queue.h"
#include "ioqueue.h"

#include <stdio.h>
#include <ctype.h>
#include <fcntl.h>

s_char	num_teles[64];
static	s_char	the_prompt[1024];
static	int	mode;
static	int	nbtu;
static	int	nmin;
FILE	*redir_fp;
FILE	*pipe_fp;
int	exec_fd;

void doredir();
void dopipe();
void doexecute();

int
servercmd(ioq, auxfi)
	struct	ioqueue *ioq;
	FILE *auxfi;
{
	s_char	buf[1024];
	s_char	*p;
	int	code;
	int	i;

	while (ioq_gets(ioq, buf, sizeof(buf))) {
		p = buf;
		while (*p && !isspace(*p))
			p++;
		*p++ = 0;
		if (isalpha(*buf))
			code = 10 + (*buf - 'a');
		else
			code = *buf - '0';
		switch (code) {
		case C_PROMPT:
			if (sscanf(p, "%d %d", &nbtu, &nmin) != 2) {
				fprintf(stderr, "prompt: bad server prompt %s\n", p);
			}
			mode = code;
			sprintf(the_prompt, "[%d:%d] Command : ", nbtu, nmin);
			prompt(auxfi);
			break;
		case C_REDIR:
			doredir(p);
			break;
		case C_PIPE:
			dopipe(p);
			break;
		case C_FLUSH:
			mode = code;
			sprintf(the_prompt, "%s", p);
			prompt(auxfi);
			break;
		case C_EXECUTE:
			doexecute(p, auxfi);
			break;
		case C_INFORM:
			if (*p) {
				p[strlen(p)-1] = '\0';
				sprintf(num_teles, "(%s) ", p + 1);
				if (!redir_fp &&
				    !pipe_fp &&
				    !exec_fd) {
					putchar('\07');
					prompt(0);
				}
			}
			else
				*num_teles = '\0';
			break;
		default:
			output(code, p, auxfi);
			break;
		}
	}
}

prompt(auxfi)
	FILE	*auxfi;
{
	if (mode == C_PROMPT) {
		if (redir_fp) {
			(void) fclose(redir_fp);
			redir_fp = 0;
		} else if (pipe_fp) {
			(void) pclose(pipe_fp);
			pipe_fp = 0;
		} else if (exec_fd > 0) {
			close(exec_fd);
			close(0);
			exec_fd = -1;
			open("/dev/tty", O_RDONLY, 0);
		}
	}
	if (mode == C_PROMPT)
		printf("\n");
	printf("%s%s", num_teles, the_prompt);
	(void) fflush(stdout);
	if (auxfi) {
	    fprintf(auxfi, "\n%s%s", num_teles, the_prompt);
	    (void)fflush(auxfi);
	}
}

/*
 * opens redir_fp if successful
 */
void
doredir(p)
	s_char	*p;
{
	s_char	*how;
	s_char	*name;
	int	mode;
	int	fd;

	if (redir_fp) {
		(void) fclose(redir_fp);
		redir_fp = 0;
	}
	how = p++;
	if (*p && ((*p == '>') || (*p == '!')))
		p++;
	while (*p && isspace(*p))
		p++;
	name = p;
	while (*p && !isspace(*p))
		p++;
	*p = 0;
	mode = O_WRONLY | O_CREAT;
	if (how[1] == '>')
		mode |= O_APPEND;
	else if (how[1] == '!')
		mode |= O_TRUNC;
	else
		mode |= O_EXCL;
	if (*name == 0) {
		fprintf(stderr, "Null file name after redirect\n");
		return;
	}
	if ((fd = open(name, mode, 0600)) < 0) {
		fprintf(stderr, "Redirect open failed\n");
		perror(name);
	} else {
		redir_fp = fdopen(fd, "w");
	}
}

/*
 * opens "pipe_fp" if successful
 */
void
dopipe(p)
	s_char	*p;
{
	extern	FILE *popen();

	if (*p == '|')
		p++;
	while (*p && isspace(*p))
		p++;
	if (*p == 0) {
		fprintf(stderr, "Null program name after redirect\n");
		return;
	}
	if ((pipe_fp = popen(p, "w")) == 0) {
		fprintf(stderr, "Pipe open failed\n");
		perror(p);
	}
}

void
doexecute(p, auxfi)
	s_char	*p;
	FILE 	*auxfi;
{
	extern	int sock;
	int	fd;

	while (*p && isspace(*p))
		p++;
	if (p == 0) {
		fprintf(stderr, "Null file to execute\n");
		return;
	}
	if ((fd = open(p, O_RDONLY, 0)) < 0) {
		fprintf(stderr, "Can't open execute file\n");
		perror(p);
		return;
	}
	/* copies 4k at a time to the socket */
	while (termio(fd, sock, auxfi)) /*do copy*/;
	sendeof(sock);
	close(fd);
}

extern s_char	*SO;
extern s_char	*SE;

output(code, buf, auxfi)
	int	code;
	s_char	*buf;
	FILE    *auxfi;
{
	switch (code) {
	case C_NOECHO:
		_noecho(0);
		break;
	case C_FLUSH:
		(void) fflush(stdout);
		if (auxfi)
		    (void) fflush(auxfi);
		break;
	case C_ABORT:
		printf("Aborted\n");
		if (auxfi)
		    fprintf(auxfi, "Aborted\n");
		break;
	case C_CMDERR:
	case C_BADCMD:
		printf("Error; ");
		if (auxfi)
		    fprintf(auxfi, "Error; ");
		break;
	case C_EXIT:
		printf("Exit: ");
		if (auxfi)
		    fprintf(auxfi, "Exit: ");
		break;
	case C_FLASH:
		printf("\n");
		break;
	default:
		break;
	}
	if (auxfi) {
		fprintf(auxfi, "%s", buf);
		if (code == C_FLUSH)
		    (void) fflush(auxfi);
		else
		    (void) putc('\n', auxfi);
	}

	if (redir_fp)
		fprintf(redir_fp, "%s\n", buf);
	else if (pipe_fp)
		fprintf(pipe_fp, "%s\n", buf);
	else {
		if (SO && SE)
			screen(buf);
		else
			fputs(buf, stdout);
		if (code == C_FLUSH)
			(void) fflush(stdout);
		else
			(void) putc('\n', stdout);
	}
}

screen(buf)
	register s_char *buf;
{
	register s_char *sop;
	register s_char c;

	while (c = *buf++) {
		if (c & 0x80) {
			for (sop = SO; putc(*sop, stdout); sop++)
				;
			(void) putc(c & 0x7f, stdout);
			for (sop = SE; putc(*sop, stdout); sop++)
				;
		} else
			(void) putc(c, stdout);
	}
}
