/*======================================================================
		    I N E T R A Y . S T A R T . C 
                    doc: Fri Mar 13 12:21:13 1992
                    dlm: Tue Aug 17 09:52:44 1993
                    (c) 1992 ant@julia
                    uE-Info: 27 6 T 0 0 72 2 2 8 ofnI
======================================================================*/

/* Note: Up to version 1.1.0 more than 1 servers could be started by
         this program. As of 1.1.1 handling of more than one sever has
         been moved to rpc.inetrayd for consistency. Variables have,
         however, not been renamed and the structure still reflects the
         olde approach. */

#define		DAEMON			/* run as daemon */

#include	<stdio.h>
#include	<signal.h>
#include	<syslog.h>
#include	<sys/types.h>
#include	<sys/ioctl.h>
#include	<sys/stat.h>
#include	<sys/param.h>
#include	<rpc/rpc.h>
#ifndef TIOCNOTTY
#include	<termios.h>
#endif
#include	"inetray.h"
#include	"config.h"
#include	"common.h"
#include	"stderr.h"
#include	"inetray.start.h"

static int 	nRunning = 0;		/* number of running servers */
static char 	*av0 = NULL;		/* server path */

extern void starter_1();		/* generated dispatch routine */

static void cleanUp(sig)		/* clean up on kill */
int sig;
{
	if (sig >= 0) 
		SYSLOG(LOG_ERR,"Shut down due to signal #%d",sig);
	(void) pmap_unset(STARTER, IRSV1);
	CLOSELOG();
	if (sig >= 0) exit(sig);
	else	      exit(1);
}

main(ac,av)
int ac; char *av[];
{
	int 	i,pid,sock,proto,rpcStat;
	char	name[MAXHOSTNAMELEN];
	register SVCXPRT *transp;
	struct stat buf;
	
	OPENLOG(av[0]);			/* set up syslog */

	for (i=0; i<NSIG; i++)		/* clean termination */
		signal(i,cleanUp);
		
	if (gethostname(name,MAXHOSTNAMELEN) < 0) {
		perror("gethostname");
		cleanUp(-1);
	}
	rpcStat = callrpc(name,STARTER,IRSV1,0,xdr_void,NULL,xdr_void,NULL);
	if (rpcStat == RPC_SUCCESS) {
		fprintf(stderr,"%s already running on %s\n",av[0],name);
		CLOSELOG();
		exit(1);
	} else if (rpcStat != RPC_PROGNOTREGISTERED &&
		   rpcStat != RPC_TIMEDOUT) {
		fprintf(stderr,"callrpc(%s,0) ",name);
		clnt_perrno(rpcStat);
		fprintf(stderr,"\n");
		cleanUp(-1);
	}

	if (ac != 2) {
		fprintf(stderr,"Usage: %s <executable>\n",av[0]);
		cleanUp(-1);
	}
	av0 = av[1];			/* set server path */
	if (stat(av0,&buf) < 0) {
		perror("stat: cannot find executable");
		cleanUp(-1);
	}

	signal(SIGIO,SIG_IGN);		/* rpc.inetrayd uses this */
	signal(SIGPIPE,SIG_IGN);	/* rpc.inetrayd uses this */
	
#ifdef DAEMON
	pid = fork();
        if (pid < 0) {
                perror("cannot fork");
                cleanUp(-1);
        }
        if (pid) exit(0);
        for (i = 0 ; i < 20; i++)
                (void) close(i);
        i = open("/dev/console", 2);
        (void) dup2(i, 1);
        (void) dup2(i, 2);
#ifndef KEEPTTY_QUIRK
        i = open("/dev/tty", 2);
        if (i >= 0) {
                (void) ioctl(i, TIOCNOTTY, (char *)NULL);
                (void) close(i);
        }
#endif
#endif
	sock = RPC_ANYSOCK;
	proto = IPPROTO_UDP;
	(void) pmap_unset(STARTER, IRSV1);

	transp = svcudp_create(sock);
	if (transp == NULL) {
		SYSLOG(LOG_ERR,"cannot create udp service.");
		cleanUp(-1);
	}
	if (!svc_register(transp, STARTER, IRSV1, starter_1, proto)) {
		SYSLOG(LOG_ERR,"unable to register (STARTER, IRSV1, udp).");
		cleanUp(-1);
	}
	svc_run();
	SYSLOG(LOG_ERR,"svc_run returned");
	cleanUp(-1);
	/* NOTREACHED */
}

static void funeral()				/* bury dead children */
{	
	int	status;
	
#ifndef DAEMON
	printf("first child died!\n");
#endif
	signal(SIGCHLD,SIG_DFL);		/* wait for all now */
	while (nRunning > 0) {
		wait(&status);			/* moment of rememberance */
#ifndef DAEMON
		printf("child returnded status %d\n",status);
#endif
		if (status != 0) 
			SYSLOG(LOG_ERR,"child returned status %d",status);
		nRunning--;			/* accounting */
	}
#ifndef DAEMON
	printf("all children died!\n");
#endif
}

void *start_1()					/* start # of servers */
{
	int	i,pid;
	static char result;

#ifndef DAEMON
	printf("START request received...\n");
#endif
	if (nRunning != 0)			/* already servicing */
		return;
	signal(SIGCHLD,funeral);		/* wait for children */
	pid = fork();
	if (pid < 0) {
		SYSLOG(LOG_ERR,"fork: %m");
		cleanUp(-1);
	}
	if (pid == 0) {				/* worker */
#ifndef DAEMON
		printf("execl: %s rpc.inetrayd STARTER\n",av0);
#endif
		if (execl(av0,"rpc.inetrayd","STARTER",NULL) < 0) {
			SYSLOG(LOG_ERR,"execl: %m");
			cleanUp(-1);
		}
	}
#ifndef DAEMON
	printf("pid %d forked...\n",pid);
#endif
	nRunning++;				/* one started */
}

