Net2/usr/src/contrib/isode/quipu/dsa.c

Compare this file to the similar file:
Show the results in this format:

/* dsa.c - Main routine for QUIPU DSA process */

#ifndef lint
static char *rcsid = "$Header: /f/osi/quipu/RCS/dsa.c,v 7.9 91/03/09 11:56:48 mrose Exp $";
#endif

/*
 * $Header: /f/osi/quipu/RCS/dsa.c,v 7.9 91/03/09 11:56:48 mrose Exp $
 *
 *
 * $Log:	dsa.c,v $
 * Revision 7.9  91/03/09  11:56:48  mrose
 * update
 * 
 * Revision 7.8  91/02/22  09:39:04  mrose
 * Interim 6.8
 * 
 * Revision 7.7  90/11/20  15:28:47  mrose
 * cjr
 * 
 * Revision 7.6  90/10/17  11:54:00  mrose
 * sync
 * 
 * Revision 7.5  90/07/09  14:45:56  mrose
 * sync
 * 
 * Revision 7.4  90/03/15  11:18:57  mrose
 * quipu-sync
 * 
 * Revision 7.3  90/01/11  23:55:57  mrose
 * lint
 * 
 * Revision 7.2  90/01/11  18:37:21  mrose
 * real-sync
 * 
 * Revision 7.1  89/12/19  16:53:08  mrose
 * dgram
 * 
 * Revision 7.0  89/11/23  22:17:19  mrose
 * Release 6.0
 * 
 */

/*
 *                                NOTICE
 *
 *    Acquisition, use, and distribution of this module and related
 *    materials are subject to the restrictions of a license agreement.
 *    Consult the Preface in the User's Manual for the full terms of
 *    this agreement.
 *
 */


#include <signal.h>
#include <stdio.h>
#include <varargs.h>
#include "rosap.h"
#include "tsap.h"
#include "logger.h"
#include "tailor.h"
#include "quipu/util.h"
#include "quipu/connection.h"
#include <sys/ioctl.h>
#include <sys/stat.h>
#ifdef  BSD42
#include <sys/file.h>
#endif
#ifdef  SYS5
#include <fcntl.h>
#endif

#include "dgram.h"
#ifdef	TCP
#include "internet.h"
#endif

PS      opt;
static  int   debug = 1;
static  int   nbits = FD_SETSIZE;

extern LLog * log_dsap;

static  char *myname;

void    adios (), advise ();
static  envinit (), setdsauid();
SFD attempt_restart();
extern int print_parse_errors;
extern int parse_line;
struct task_act	* task_select();
extern time_t	time();

extern SFP abort_vector;

#ifndef NO_STATS
extern LLog    *log_stat;
#endif

/*
* Basic data structure of the DSA server.
*/
char			* mydsaname = "undefined";
struct PSAPaddr		* mydsaaddr = NULLPA;
struct PSAPaddr		* dsaladdr = NULLPA;
struct connection	* connlist;
int			  conns_used;
struct connection	* connwaitlist;
struct di_block		* deferred_dis = NULL_DI_BLOCK;
struct oper_act		* get_edb_ops;

char ** sargv;

main(argc, argv)
int    argc;
char    **argv;
{
#ifdef DEBUG
    unsigned proc_size = 0;
    unsigned new_size;
    extern caddr_t sbrk();
#endif
    extern char	* mydsaname;
    extern char	  startup_update;
    extern time_t	timenow;
    struct task_act	* task;
    int		  secs;
    char start_buf [LINESIZE];
    /*
    * Function to stop DSA server.
    */
    SFD          stop_dsa();
#ifdef	SIGUSR1
    SFD		 list_status ();
#endif

    sargv = argv;

    if (myname = rindex (argv[0], '/'))
	myname++;
    if (myname == NULL || *myname == NULL)
	myname = argv[0];

    isodetailor (myname,0);

    envinit();  /* detach */

    quipu_syntaxes ();
    dsa_sys_init(&argc, &argv);
    setdsauid();

    print_parse_errors = FALSE;

#ifndef NO_STATS
    ll_hdinit (log_stat,myname);
#endif

    if ((opt = ps_alloc (std_open)) == NULLPS)
	     fatal (-12,"ps_alloc failed");
    if (std_setup (opt,stdout) == NOTOK)
	     fatal (-13,"std_setup failed");

    DLOG (log_dsap,LLOG_DEBUG,( "About to dsa_init()"));

    if(dsa_init() == NOTOK)
    {
	fatal(-14,"Couldn't initialise the DSA!!");
    }


    if(net_init() == NOTOK)
    {
	fatal(-15,"Couldn't start the DSA!!");
    }


    if (startup_update) 
    {
	/* Will generate a list of EDB operations! */
	(void) time (&timenow);
  	slave_update();
    }

    {
	extern char *treedir;
	char    filebuf[BUFSIZ];
	FILE   *fp;

	(void) sprintf (filebuf, "%s/PID", treedir);
	if (fp = fopen (filebuf, "w")) {
	    (void) fprintf (fp, "%d\n", getpid ());
	    (void) fclose (fp);
	}
	else
	    LLOG (log_dsap,LLOG_EXCEPTIONS,("Can't open PID file %s",filebuf));
    }

    /*
    * Do stop_dsa() on receiving a Ctrl-C
    */

    (void) signal (SIGINT, stop_dsa);
    (void) signal (SIGTERM,stop_dsa);
    (void) signal (SIGHUP, stop_dsa);

    /* now started don't stop on core dumps !!! */
    (void) signal (SIGQUIT, attempt_restart);
    (void) signal (SIGILL,  attempt_restart);
    (void) signal (SIGBUS,  attempt_restart);
    (void) signal (SIGSEGV, attempt_restart);
    (void) signal (SIGSYS,  attempt_restart);
    (void) signal (SIGPIPE,  attempt_restart);
#ifdef	SIGUSR1
    (void) signal (SIGUSR1, list_status);
#endif

    abort_vector = attempt_restart;
    parse_line = 0;

    (void) sprintf (start_buf,"DSA %s has started on %s",mydsaname,
			    paddr2str(dsaladdr,NULLNA));

    LLOG (log_dsap,LLOG_NOTICE,(start_buf));
#ifndef NO_STATS
    LLOG (log_stat,LLOG_NOTICE,(start_buf));
#endif

     if (debug)
	(void) fprintf (stderr,"%s\n",start_buf);

    start_malloc_trace (NULLCP);

#ifdef DEBUG
    proc_size = (unsigned) sbrk(0);
#endif

    for(;;)
    {
	if((task = task_select(&secs)) == NULLTASK)
	{
#ifdef DEBUG
	   if ( secs != 0 ) {
		/* Only if we are idle ! */
		new_size = (unsigned) sbrk(0);
		if ( new_size > proc_size) {
			LLOG (log_dsap, LLOG_NOTICE, ("Process grown by %d bytes", new_size - proc_size));
			proc_size = new_size;
		}
	    }
#endif
	    dsa_wait(secs);	/* Check network with timeout of secs */
	}
	else
	{
	    dsa_work(task);	/* Process the DSA task selected */
	    dsa_wait(0);
	}
    } /* forever */
} /* main */

dsa_abort(isfatal)
int	isfatal;
{
    struct connection		* cn;
    struct DSAPindication	  di_s;
    struct DSAPindication	* di = &di_s;

    for(cn=connlist; cn!=NULLCONN; cn=cn->cn_next)
	if (cn -> cn_ad != NOTOK) {
	    if (isfatal || (! cn -> cn_initiator))
		(void) close (cn -> cn_ad);
	    else {
		(void) DUAbortRequest(cn->cn_ad, di);
	    }
	}

    watch_dog ("stop_listeners");
    stop_listeners();
    watch_dog_reset();
}

SFD stop_dsa (sig)
int sig;
{
	(void) signal (sig, SIG_DFL); /* to stop recursion */
	LLOG (log_dsap,LLOG_FATAL,("*** Stopping on signal %d ***",sig));
	if (debug)
		(void) fprintf (stderr,"DSA %s has Stopped\n",mydsaname);
	dsa_abort(0);
	exit (0);
}

#ifdef	SIGUSR1
/* ARGSUSED */

SFD	list_status (sig)
int	sig;
{
    int	    fd;
    struct stat st;
    register struct connection *cn;
    time_t  now;
    
#ifndef	BSD42
    (void) signal (SIGUSR1, list_status);
#endif

    for (fd = getdtablesize () - 1; fd >= 0; fd--)
	if (fstat (fd, &st) != NOTOK)
	    LLOG (log_dsap, LLOG_EXCEPTIONS,
		  ("fd %d: fmt=0%o", fd, st.st_mode & S_IFMT));
#ifndef	NO_STATS
    LLOG (log_dsap, LLOG_EXCEPTIONS, ("logs dsap=%d stat=%d",
				  log_dsap -> ll_fd, log_stat -> ll_fd));
#else
    LLOG (log_dsap, LLOG_EXCEPTIONS, ("logs dsap=%d", log_dsap -> ll_fd));
#endif
    (void) time (&now);
    for (cn = connlist; cn; cn = cn -> cn_next)
	if (cn -> cn_ad != NOTOK)
	    LLOG (log_dsap, LLOG_EXCEPTIONS,
		  ("cn %d: init=%d used=%ld release=%ld",
		   cn -> cn_ad, cn -> cn_initiator,
		   (long) now - cn -> cn_last_used,
		   (long) now - cn -> cn_last_release));
}
#endif

static  envinit () {
    int     i,
	    sd;

    nbits = getdtablesize ();

    if (!(debug = isatty (2))) {
	for (i = 0; i < 5; i++) {
	    switch (fork ()) {
		case NOTOK:
		    sleep (5);
		    continue;

		case OK:
		    goto fork_ok;

		default:
		    _exit (0);
	    }
	    break;
	}

fork_ok:;
	(void) chdir ("/");

	if ((sd = open ("/dev/null", O_RDWR)) == NOTOK)
	    adios ("/dev/null", "unable to read");
	if (sd != 0)
	    (void) dup2 (sd, 0), (void) close (sd);
	(void) dup2 (0, 1);
	(void) dup2 (0, 2);

#ifdef	SETSID
	if (setsid () == NOTOK)
	    advise (LLOG_EXCEPTIONS, "failed", "setsid");
#endif
#ifdef  TIOCNOTTY
	if ((sd = open ("/dev/tty", O_RDWR)) != NOTOK) {
	    (void) ioctl (sd, TIOCNOTTY, NULLCP);
	    (void) close (sd);
	}
#else
#ifdef  SYS5
	(void) setpgrp ();
	(void) signal (SIGINT, SIG_IGN);
	(void) signal (SIGQUIT, SIG_IGN);
#endif
#endif
    }
#ifndef	DEBUG
    /* "Normal" ISODE behavior of full logging only without DEBUG */
    else
	ll_dbinit (log_dsap, myname);
#endif

#ifndef	sun		/* damn YP... */
    for (sd = 3; sd < nbits; sd++) {
	if (log_dsap -> ll_fd == sd)
	    continue;
#ifdef	NO_STATS
	if (log_stats -> ll_fd == sd)
	    continue;
#endif
	(void) close (sd);
    }
#endif

    (void) signal (SIGPIPE, SIG_IGN);

    ll_hdinit (log_dsap, myname);
#ifdef	DEBUG
    advise (LLOG_TRACE, NULLCP, "starting");
#endif
}


/* 	ERRORS */

#ifndef	lint
void    adios (va_alist)
va_dcl
{
    va_list ap;

    va_start (ap);

    _ll_log (log_dsap, LLOG_FATAL, ap);

    va_end (ap);

    if (debug)
	(void) fprintf (stderr,"adios exit - see dsap.log\n");
    dsa_abort(1);
    _exit (-18);
}
#else
/* VARARGS */

void    adios (what, fmt)
char	*what,
	*fmt;
{
    adios (what, fmt);
}
#endif

#ifndef	lint
void    advise (va_alist)
va_dcl
{
    int     code;
    va_list ap;

    va_start (ap);

    code = va_arg (ap, int);

    (void) _ll_log (log_dsap, code, ap);

    va_end (ap);
}
#else
/* VARARGS */

void	advise (code, what, fmt)
char	*what,
	*fmt;
int	 code;	
{
    advise (code, what, fmt);
}
#endif



static setdsauid ()
{
struct stat buf;
extern char * treedir;

	(void) stat (treedir,&buf);

	if (setgid (buf.st_gid) == -1)
		LLOG (log_dsap,LLOG_EXCEPTIONS,("Can't set gid %d (database directory \"%s\")",buf.st_uid,treedir));

	if (setuid (buf.st_uid) == -1)
		LLOG (log_dsap,LLOG_EXCEPTIONS,("Can't set uid %d (database directory \"%s\")",buf.st_uid,treedir));
}



#define	RESTART_TIME	30		/* for connections to clear... */
#define	CLEAR_TIME	300		/*   .. */

SFD attempt_restart (sig)
int     sig;
{
int fpid, sd;
unsigned int secs;
extern char * mydsaname;

	if (sig > 0)
		(void) signal (sig, SIG_DFL); /* to stop recursion */

	if (sig >= 0 && debug)
		(void) fprintf (stderr,"DSA %s has a problem\n",mydsaname);

	dsa_abort(sig != NOTOK);
	secs = sig != NOTOK ? CLEAR_TIME : RESTART_TIME;

	for (sd = 3; sd < nbits; sd++) {
	    if (log_dsap -> ll_fd == sd)
		continue;
#ifdef	NO_STATS
	    if (log_stats -> ll_fd == sd)
		continue;
#endif
	    (void) close (sd);
	}

	if ( sig == -2 || (fpid = fork()) == 0) {
		if (sig == -2) {		    /* restart due to congestion... */
			LLOG (log_dsap,LLOG_FATAL, ("*** in-situ restart attempted ***"));
#ifndef NO_STATS
			LLOG (log_stat,LLOG_NOTICE,("RESTARTING (%s)",mydsaname));
#endif
	    	}

		sleep (secs);	/* give connections time to clear */
		(void) execv (isodefile(sargv[0], 1),sargv);
		exit (-19);
	}

	log_dsap -> ll_syslog = LLOG_FATAL;

	if (fpid != -1) {
		LLOG (log_dsap,LLOG_FATAL,("Quipu restart attempted in %d seconds (sig %d)", secs,sig));
#ifndef NO_STATS
		LLOG (log_stat,LLOG_NOTICE,("RESTARTING with pid %d (%s)",fpid,mydsaname));
#endif
	} else {
#ifndef NO_STATS
		LLOG (log_stat,LLOG_NOTICE,("PANIC (%s)",mydsaname));
#endif
		LLOG (log_dsap,LLOG_FATAL,("Quipu aborting - sig (%d)",sig));
	}

	(void) signal (SIGIOT, SIG_DFL);
	abort ();
	exit (-20);  /* abort should not return */
}