/*
 * 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.
 */

#if 0
static	char	rcsid[] = "@(#)$Id: wserv.c,v 1.13 1994/07/02 02:32:13 mrg Exp $";
#endif

#include "defs.h"

#ifdef HAVE_SYS_UN_H

# include "irc.h"
# include "term.h"

# include <sys/un.h>

/*
 * 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	pid_t	ircIIpid;
static int s;

/* sanity */
typedef struct sockaddr Sockaddr;
typedef struct sockaddr_un USockaddr;

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

#ifdef __STDC__
void main (int argc, char **argv)
#else
void
main(argc, argv)
	int	argc;
	char	**argv;
#endif
{
	struct	sockaddr_un my_addr, *addr = &my_addr;
	int	nread;
	fd_set	reads;
	char	*path,
		*tmp;
	char buffer[2];

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

	if (argc != 2)    /* no socket is passed */
		my_exit(1);

	/*
	 * 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;
#ifdef SUN_LEN
	addr->sun_len = strlen(path) + 1;
#endif
	strcpy(addr->sun_path, path);

	s = socket(AF_UNIX, SOCK_STREAM, 0);
	if (connect(s, (Sockaddr *) addr, sizeof(USockaddr)) < 0)
		my_exit(23);

	/*
	 * first line to for a wserv program is the tty.  this is so ircii
	 * can grab the size of the tty, and have it changed.
	 */
	tmp = ttyname(0);
	write(s, tmp, strlen(tmp));
	write(s, "\n", 1);

	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, NULL, NULL);
		if (FD_ISSET(0, &reads))
		{
			if (0 != (nread = read(0, buffer, sizeof(buffer))))
				write(s, buffer, nread);
			else
				my_exit(3);
		}
		if (FD_ISSET(s, &reads))
		{
			if (0 != (nread = read(s, buffer, sizeof(buffer))))
				write(1, buffer, nread);
			else
				my_exit(4);
		}
	}

	my_exit(8);
}

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

#else

void
main _((void))
{
	my_exit(5);
}

#endif /* HAVE_SYS_UH_H */

void my_exit(int value)
{
	printf("exiting with %d!\n", value);
	printf("errno is %d (%s)\n", errno, sys_errlist[errno]);
	exit(value);
}

void ignore (int value)
{
	/* send a ^C */
	char foo = 3;
	write(s, &foo, 1);
}

