V9/jerq/src/sysmon/daemon.ok.c
#include <stdio.h>
/*
* The following code implements a daemon that "feeds" information to
* other processes over datakit. It handles the multiplexing
* and expects the following routines to perform the data collection
* and distribution:
* init() - initialize data collectin
* generate() - generate a new set of data
* sendinfo(fd) - send the information on the given fd
* myname() - return the name this daemon should use
* add(fd, who) - tell application that a new cleint exists
* drop(fd) - tell it that that client has disappeared
*/
#include <errno.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <dkmgr.h>
#include <ctype.h>
#include <sys/stat.h>
#include <signal.h>
#include "defs.h"
/* globals */
#define LIFETIME 24*60*60 /* secs to live since first started */
#define LIFESECS 1800 /* secs of lifetime while no clients exist */
#define RESENDSECS 5 /* secs between resends */
#define RESTART 20 /* minutes between restarts */
#define DEBUG ;
#define LOGDIR "/tmp/"
char *sysname; /* name of system */
char *oursrv; /* name of this server */
int cfd_owait[NOFILE]; /* TRUE if waiting for output to complete */
fd_set cfds; /* set of client fd's */
char errbuf[128];
bool solo; /* TRUE if started by a shell */
int clients; /* number of clients */
/* imports */
extern int errno;
extern int dkp_ld;
extern int dkmgropen;
extern int dkmgrreply;
char * malloc();
char * realloc();
char * strcpy();
/* predefined */
char * ealloc();
char * sname();
char * getsysname();
int ding();
/* specific to generator */
int generate(); /* generate information */
int sendinfo();
char *myname();
int init();
void add();
void drop();
paranoia()
{
exit(1);
}
main (argc, argv)
int argc;
char *argv[];
{
struct mgrmsg *dkmgr(), *mp;
fd_set rfds, wfds;
int fds, fd, mask;
long deathtime, lonelytime, now;
int (*sigfunc)();
FD_ZERO(rfds); FD_ZERO(wfds);
doargs(argc, argv);
detach();
init(); /* application dependent init */
lonelytime = time((long *)0) + 2*LIFESECS;
deathtime = time((long *)0) + LIFETIME;
while (1) {
/* generate the new information */
generate();
/* only read if there is a request waiting */
if (FD_ISSET(dkmgropen, rfds)) {
mp = dkmgr(oursrv, 0);
if (mp != NULL)
newclient (mp->m_chan, mp->m_uid);
}
/* send information to clients (if any) */
sigfunc = signal(SIGALRM, paranoia);
alarm(60);
for (fd = 0; fd < NOFILE; fd++) {
if (FD_ISSET(fd, wfds))
cfd_owait[fd] = FALSE;
if (FD_ISSET(fd, cfds) && !cfd_owait[fd]) {
if (sendinfo (fd) < 0)
dropclient (fd);
else
cfd_owait[fd] = TRUE;
}
}
now = time((long *)0);
alarm(0);
signal(SIGALRM, sigfunc);
/* is anyone out there? */
if (clients != 0)
lonelytime = time((long *)0) + LIFESECS;
else if (now > lonelytime)
die("life ain't worth livin");
/* time to reset? */
if (now > deathtime)
die("reached retirement age");
/* scan for request from dk or child termination */
FD_SET(dkmgropen, rfds);
if (mp != NULL) {
wfds = cfds;
fds = select (20, &rfds, &wfds, 0);
} else {
FD_ZERO(wfds);
}
/* don't hog the CPU */
sleep (RESENDSECS);
}
}
/* scan the arguments and pick a service name */
doargs (argc, argv)
int argc;
char *argv[];
{
int fd;
if (argc > 1) {
solo = FALSE;
oursrv = argv[1];
} else if ((sysname = getsysname()) != NULL) {
solo = TRUE;
oursrv = sname(sysname, myname());
oursrv = strcpy (ealloc (strlen (oursrv) + 1), oursrv);
} else {
sprintf (errbuf, "%s: cant's find /etc/whoami", oursrv);
perror (errbuf);
exit (-1);
}
}
/* detach from our environment */
detach ()
{
int i;
char logfile[64];
/* detach from the process group */
setpgrp (0, 0);
/* ignore some signals */
signal(SIGPIPE, SIG_IGN);
signal(SIGHUP, SIG_IGN);
signal(SIGTERM, SIG_IGN);
/* detach from old i/o */
switch (fork()) {
case -1:
perror ("gen: couldn't fork");
exit (-1);
case 0:
for (i = 0; i < NOFILE; i++)
close (i);
i = open ("/dev/null", 0);
strcpy (logfile, LOGDIR);
strcat (logfile, myname());
strcat (logfile, ".log");
i = creat (logfile, 0666);
i = dup (1);
break;
default:
_exit (0);
}
}
/* add client to the list */
newclient(chan, who)
int chan; /* dkchannel */
char * who; /* client */
{
int fd, i, rv;
char *devname, *dkfilename();
/* open the line to the client */
devname = dkfilename(chan);
fd = open (devname, 2);
if (fd < 0) {
perror (oursrv);
dkmgrnak (chan);
return;
}
if (dkproto(fd, dkp_ld) < 0) {
(void)close (fd);
perror (oursrv);
dkmgrnak (chan);
return;
}
dkmgrack(chan);
/* channel is open, add client to fdlist */
FD_SET(fd, cfds);
/* tell application about it */
add (fd, who);
clients++;
log("new client %s %d", who, fd);
}
dropclient (fd)
int fd;
{
/* do our bookkeeping */
FD_CLR(fd, cfds);
close (fd);
/* tell application about it */
drop (fd);
clients--;
log("drop client %d", fd);
}
die(s)
char *s;
{
log(s);
exit(0);
}
log(p1, p2, p3, p4, p5)
int p1, p2, p3, p4, p5;
{
fprintf(stderr, "[%d] ", time((long *)0));
fprintf(stderr, p1, p2, p3, p4, p5);
fprintf(stderr, "\n");
}