#ifdef UNIX
#ifdef _lint
int
dopipe (int argc, char *argv[], void *p OPTIONAL)
{
	return 0;
}
#else

#include "global.h"
#ifdef PIPECMD
#include <signal.h>
#include "proc.h"
#include "hardware.h"
#include "session.h"
extern int keywait (const char *prompt,int flush);
extern int sockblock (int s,int value);
extern int recvchar (int s);
#define setflush j_setflush
extern int setflush (int s,int c);
extern int socketalive (int s);
extern int dup (int oldfd);
#include <sys/wait.h>
#include <sys/time.h>

#if !defined(_lint)
static char rcsid[] OPTIONAL = "$Id: pipe.c,v 1.17 1997/07/31 00:44:20 root Exp $";
#endif

#ifdef SOCK_STREAM
#undef SOCK_STREAM
#endif
#include <sys/socket.h>

#ifdef socketpair
#undef socketpair
#endif

static void sig_pipe(int);
static int s_pipe(int fd[2]);
int dopipe (int argc,char *argv[],void *p);
static void pipe_io(int fd, FILE *fpin, FILE *fpout);
extern int dup2(int oldfd, int newfd);

#define STDIN_FILENO 0
#define STDOUT_FILENO 1
#ifndef _lint
#define STDERR_FILENO 2
#endif
#define MAXLINE 512

#define SOCK_NOTXBLOCK  1
#define SOCK_NORXBLOCK  2
#ifndef _lint
#define SOCK_BINARY 0
#endif

static const char strCR[] = "pipe: %s\n";
static int Aborted = 0;


static void
pipe_io (int fd, FILE *fpin, FILE *fpout)
{
int n;
char line[MAXLINE];
int retval;
int done = 0;
int oldblock = 0;
int oldblock2 = 0;
int oldflush = 0;
int oldflush2 = 0;
#if 0
int oldmode = 0;
int oldmode2 = 0;
int edit, echo;
#endif
static fd_set fdr;
static struct timeval tv;
struct timeval *tvp;
int fd2;

	if (fpin == stdin)	{
#if 0
		if (Current->s == -1)
			Current->s = Curproc->input;
#endif
		oldblock = sockblock(Curproc->input,SOCK_NORXBLOCK);
		oldblock2 = sockblock(Curproc->output,SOCK_NOTXBLOCK);
		oldflush = setflush (Curproc->input, -1);
		oldflush2 = setflush (Curproc->output, -1);
#if 0
		oldmode = sockmode(Curproc->input,SOCK_BINARY);
		oldmode2 = sockmode(Curproc->output,SOCK_BINARY);
		echo = Current->ttystate.echo;
		edit = Current->ttystate.edit;
	        Current->ttystate.echo = Current->ttystate.edit = 0;
#endif
	}


	fd2 = dup (fd);
	tvp = &tv;

	do	{
		if (fpin == stdin)	{
			retval = 0;
			line[1] = 0;
#if 1
			retval = recvchar(Curproc->input);
#else
			retval = rrecvchar(Curproc->input);
#endif
			if (retval == EOF)	{
				if (errno == EWOULDBLOCK)	{
					line[0] = 0;
					retval = 0;
				} else
					Aborted = retval;
			} else
				line[0] = (char) retval;
		} else
			retval = (int) fgets (line, MAXLINE, fpin);
		if (Aborted || (fpin == stdin && retval == EOF) || (fpin != stdin && !retval)) {
			done = 1;
			continue;
		}

#if 0
		if (!socketalive (Current->s))	{
#else
		if (!socketalive (Curproc->input))	{
#endif
			done = 1;
			continue;
		}

		kwait (NULL);

		n = (int) strlen (line);
		if (n && write (fd, line, (unsigned int) n) != n)	{
			tprintf (strCR, "write error");
			break;
		}
		if (Aborted)
			continue;

		kpause (20);

		tv.tv_sec = tv.tv_usec = 0;
#ifndef _lint
		FD_ZERO(&fdr);
		FD_SET(fd2, &fdr);
#endif
		if (select(fd2 + 1, &fdr, 0, 0, tvp))	{
			if ((n = read (fd2, line, MAXLINE)) < 0)	{
				tprintf (strCR, "read error");
				break;
			}
			if (Aborted)
				continue;
			if (!n)
				continue;
			line[n] = 0;
			if (fpout == stdout)
				tputs(line);
			else
				fputs (line, fpout);
		}
		kwait (NULL);
	} while (!done && !Aborted);

	close (fd2);

	if (fpin == stdin)	{
		(void) sockblock(Curproc->input,oldblock);
		(void) sockblock(Curproc->output,oldblock2);
		(void) setflush(Curproc->input,oldflush);
		(void) setflush(Curproc->output,oldflush2);
#if 0
		sockmode(Curproc->input,oldmode);
		sockmode(Curproc->output,oldmode2);
		Current->ttystate.echo = echo;
		Current->ttystate.edit = edit;
#endif
	}
}


static void
pipe_cmd (int argc OPTIONAL, char *argv[], void *p OPTIONAL)
{
int fd[2];
FILE *fpin;
FILE *fpout;
struct session *sp = NULLSESSION;
int usesession = 0;
#if 0
pid_t pid;
#endif
	/* Use a session if this comes from console */
	if(Curproc->input == Command->input) {
		usesession = 1;
		if((sp = newsession(argv[1],MORE,0)) == NULLSESSION)	{
			return;
		}
	}

	if (signal (SIGPIPE, sig_pipe) == SIG_ERR)	{
		tprintf (strCR,"signal error");
		return;
	}

	if (s_pipe (fd) < 0)	{
		tprintf (strCR, "pipe error");
		return;
	}

/*	fpin = (FILE *)p;	*/
#if 0
	if (p)	{
		fpin =  ((FILE **)p)[0];
		fpout = ((FILE **)p)[1];
	} else	{
#endif
	fpin = stdin;
	fpout = stdout;
#if 0
	}
#endif
	
	Aborted = 0;

#if 0
	switch (pid = fork())	{
#else
	switch (fork())	{
#endif
		case -1:	tprintf (strCR,"fork error");
				return;

		case 0:		/* child */
			close (fd[0]);
			if (fd[1] != STDIN_FILENO)	{
				if (dup2 (fd[1], STDIN_FILENO) != STDIN_FILENO)	{
					tprintf(strCR, "dup2 error to stdin");
					return;
				}
			}
			if (fd[1] != STDOUT_FILENO)	{
				if (dup2 (fd[1], STDOUT_FILENO) != STDOUT_FILENO)	{
					tprintf(strCR, "dup2 error to stdout");
					return;
				}
			}
			if (execvp (argv[0], (char * const *) argv) < 0)	{
				tprintf(strCR, "execvp error");
				return;
			}
			break;

		default:	/* parent */
			close (fd[1]);
			pipe_io(fd[0], fpin, fpout);
			close (fd[0]);
			(void) wait (NULL);
			(void) signal (SIGPIPE, SIG_DFL);

			if (usesession)	{
				(void) keywait(NULLCHAR,1);
				freesession(sp);
			}
			return;
	}
}


static void
sig_pipe (int signo OPTIONAL)
{
	Aborted = 1;
}


static int
s_pipe (int fd[2])
{
	return (socketpair (AF_UNIX, SOCK_STREAM, 0, fd));
}


int
dopipe (argc, argv, p)
int argc;
char *argv[];
void *p OPTIONAL;
{
char **pargv;
int i;
FILE *fps[2];

	fps[0] = stdin;
	fps[1] = stdout;
	if (!--argc)
		return 0;
	argv++;				/*lint !e608 */
	if (!strnicmp(argv[0], "-f", 2))	{
		fps[0] = fopen (&argv[0][2], "r");
		if (fps[0] == NULLFILE)	{
			tprintf ("Sorry, can't open file '%s'\n", &argv[0][2]);
			return 0;
		}
		if (!--argc)
			return 0;
		argv++;			/*lint !e608 */
	}
	if (!strnicmp(argv[0], "-t", 2))	{
		fps[1] = fopen (&argv[0][2], "w");
		if (fps[1] == NULLFILE)	{
			tprintf ("Sorry, can't open file '%s'\n", &argv[0][2]);
			return 0;
		}
		if (!--argc)
			return 0;
		argv++;			/*lint !e608 */
	}
	if(Curproc->input == Command->input) {
		/* Make private copy of argv and args,
		 * spawn off subprocess and return.
		 */
		pargv = (char **)callocw((size_t)argc,sizeof(char *));
		for(i = 0; i < argc; i++)
			pargv[i] = strdup(argv[i]);
		pargv[i] = NULL;
	        (void) newproc("pipe",512,(void (*)(int,void *,void *))pipe_cmd,argc,(void *)pargv,(void *)fps,1);
	} else
		pipe_cmd (argc, argv, (void *)fps);
	return 0;
}

#endif	/* PIPECMD */
#endif  /* _lint */
#endif 	/* UNIX */

