/*
 * wserv.c - little program to be a pipe between a screen or
 * xterm window to the calling ircII process.
 *
 * Copyright Troy Rollo, 1992.
 * 
 * Finished by Matthew Green, 1993.
 *
 * Works by opening up the unix domain socket that ircII bind's
 * before calling wserv, and which ircII also deleted after the
 * connection has been made.
 */

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#ifdef POSIX
# include <sys/select.h>
#endif /* POSIX */
#include <sys/un.h>
#include <sys/types.h>
#include <sys/time.h>
#include <signal.h>
#ifdef pyr
# include <strings.h>
#else
# include <string.h>
#endif
#include "config.h"

#define	null(x)	((x) 0L)

/*
 * Holds the parent process id, as taken from the command line arguement.
 * We can't use getppid() here, because the parent for screen is the
 * underlying screen process, and for xterm's, it the xterm itself.
 */
static	unsigned int	ircIIpid;


/* declare the signal handler */
#if !defined(_RT) && defined(SIGWINCH)
void	got_sigwinch();
#endif /* _RT */

void	main(argc, argv)
int	argc;
char	**argv;
{
	char	*Buffer[1024];
	struct	sockaddr_un *addr = (struct sockaddr_un *) Buffer;
	int	nread;
	fd_set	reads;
	int	s;
	char	*path,
		*tmp;

	/* Set up the signal hander to pass SIGWINCH to ircII */
#if !defined(_RT) && defined(SIGWINCH)
	signal(SIGWINCH, got_sigwinch);
#endif /* _RT */

	if (argc != 2)    /* no socket is passed */
		exit(0);
	/*
	 * First thing we do here is grab the parent pid from the command
	 * line arguements, because getppid() returns the wrong pid in
	 * all cases.. is comes in via the command line arguement in the
	 * for of irc_xxxxxxxx .. as an 8 digit decimal number..  if we
	 * can't get the pid from the command line arg, then we set it
	 * to -1, which is used later to ignore them..
	 */

	path = (char *) malloc(strlen(argv[1]) + 1);
	strcpy(path, argv[1]);
	if (tmp = (char *) index(path, '_'))
		ircIIpid = atoi(++tmp);
	else
		ircIIpid = -1;

	/*
	 * Set up the socket, from the path passed, connect it.. all that
	 * stuff..  And initalise the term settings for the window.
	 */
	addr->sun_family = AF_UNIX;
	strcpy(addr->sun_path, argv[1]);
	s = socket(AF_UNIX, SOCK_STREAM, 0);
	connect(s, (struct sockaddr *) addr, sizeof(addr->sun_family) + strlen(addr->sun_path));

	term_init();

	/*
	 * The select call..  reads from the socket, and from the window..
	 * and pipes the output from out to the other..  nice and simple
	 */
	while (1)
	{
		FD_ZERO(&reads);
		FD_SET(0, &reads);
		FD_SET(s, &reads);
		select(s + 1, &reads, null(fd_set *), null(fd_set *),
			null(struct timeval *));
		if (FD_ISSET(0, &reads))
		{
			if (nread = read(0, Buffer, 1024))
				write(s, Buffer, nread);
			else
				exit(0);
		}
		if (FD_ISSET(s, &reads))
		{
			if (nread = read(s, Buffer, 1024))
				write(0, Buffer, nread);
			else
				exit(0);
		}
	}
}

/* got_sigwinch: we got a SIGWINCH, so we send it back to ircII */
#if !defined(_RT) && defined(SIGWINCH)
void	got_sigwinch()
{
	if (ircIIpid != -1)
		kill(ircIIpid, SIGWINCH);
#ifdef MUNIX
	signal(SIGWINCH, got_sigwinch);
#endif
}
#endif /* _RT */
