BSD 4_3_Net_2 development
[unix-history] / usr / src / contrib / isode / quipu / dsa.c
/* 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
}
/* \f 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 */
}