/*
 *
 * bbpage.c
 * BIG BROTHER NOTIFICATION DAEMON PROGRAM
 * Robert-Andre Croteau
 * Version 1.9b
 * Apr 15th, 2002
 *
 * (c) Copyright Quest Software, Inc.  1997-2002  All rights reserved.
 *
 */

#include "bb.h"         /* THE BIG BROTHER INCLUDE FILE */
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h>
#ifdef TIMEH
#include <time.h>       /* FOR TIMING STUFF SMM */
#else
#include <sys/time.h>   /* FOR TIMING STUFF SMM */
#endif
#include <utime.h>      /* SMM NEW */
#include <netdb.h>
#include <dirent.h>
#ifndef ZOMBIE
#include <sys/wait.h>
#endif
#ifdef SCO3
#include <unistd.h>
#endif

#ifdef MAIN
char bbprog[] = "bbpage";
#endif

#define MAXRULEARGS	7

#define MAXTRAPMSGSIZE	127

extern char *bbhome,bbtmpdir[],bbacksdir[],bb_hosts[];
extern int  fqdn;

static char *neterr;

extern char *gettimestr();
extern char *readfile();

static char rcpt_env[MAXLINE];			/* Static variable for putenv() of RCPT */
static char bbalphamsg_env[MAXLINE];		/* Static variable for putenv() of BBALPHAMSG */
static char ackcode_env[MAXLINE];		/* Static variable for putenv() of ACKCODE */
static char bbhostsvc_env[MAXLINE];		/* Static variable for putenv() of BBHOSTSVC */
static char bbhostname_env[MAXLINE];		/* Static variable for putenv() of BBHOSTSVC */
static char machip_env[MAXLINE];		/* Static variable for putenv() of MACHIP */
static char bbsvcnum_env[MAXLINE];		/* Static variable for putenv() of BBSVCNUM */
static char bbsvcname_env[MAXLINE];		/* Static variable for putenv() of BBSVCNAME */
static char bbnumeric_env[MAXLINE];		/* Static variable for putenv() of BBNUMERIC */
static char bbcolorlevel_env[MAXLINE];		/* Static variable for putenv() of BBCOLORLEVEL */
static char bbhostsvcdots_env[MAXLINE];		/* Static variable for putenv() of BBHOSTSVCDOTS */
static char bbhostsvccommas_env[MAXLINE];	/* Static variable for putenv() of BBHOSTSVCCOMMAS */
static char downsecsmsg_env[MAXLINE];		/* Static variable for putenv() of DOWNSECSMSG */
static char downsecs_env[MAXLINE];		/* Static variable for putenv() of DOWNSECS */
static char recovered_env[MAXLINE];		/* Static variable for putenv() of RECOVERED */

struct bbpageinfo {
	char	cfgdelim[MAXLINE];
	char	ignforall[MAXLINE];
	char	svcerrlist[MAXLINE];
	char	pagehelpcode[MAXLINE];
	char	recoverytagfile[MAXLINE];
	char	pagemsgfile[MAXLINE];
	int	pagedelay;
};

/*
 * Do pre-exit stuff
 */
static void cleanup(pginfop)
struct bbpageinfo *pginfop;
{

	if( strlen(pginfop->recoverytagfile) > 0 ) {
#if DEBUG
		fprintf(stderr,"Removing %s\n",pginfop->recoverytagfile);
		fflush(stderr);
#endif
		unlink(pginfop->recoverytagfile);
	}

	if( strlen(pginfop->pagemsgfile) > 0 ) {
#if DEBUG
		fprintf(stderr,"Removing %s\n",pginfop->pagemsgfile);
		fflush(stderr);
#endif
		unlink(pginfop->pagemsgfile);
	}

	return;
}

static int getsvccode(svcname,svccode,svcerrlist)
char *svcname;
char *svccode;
char *svcerrlist;
{
char worksvcname[MAXLINE];
char *workptr;
struct servent *service;

	sprintf(worksvcname,"%s:",svcname);

	workptr = strstr(svcerrlist,worksvcname);
	if( workptr ) {
		workptr += strlen(worksvcname);
		sscanf(workptr,"%s",svccode);
	}
	else if( (service=getservbyname(svcname,"tcp")) != NULL ) {
		sprintf(svccode,"7%d",(int)htons(service->s_port));
	}
	else {
		strcpy(worksvcname,"ERR:");
		workptr = strstr(svcerrlist,worksvcname);
		if( workptr ) {
			workptr += strlen(worksvcname);
			sscanf(workptr,"%s",svccode);
		}
	}

	return(0);
}

static void usage(msg)
char *msg;
{
	if( msg ) {
		fprintf(stderr,"bbwarn: %s\n",msg);
		fflush(stderr);
	}
}

static void errmsg(type,msg)
char *type;
char *msg;
{
	bb_errmsg(type,msg);
}

/*
 * Exit with cleanup
 */
static int done( rccode,pginfop )
int rccode;
struct bbpageinfo *pginfop;
{
	cleanup(pginfop);
	return(rccode);
}

static int usage_done(msg,code,pginfop)
char *msg;
int code;
struct bbpageinfo *pginfop;
{
	usage(msg);
	return(done(code,pginfop));
}


/* Set up info if message came from pre-1.08b client */
static int getoldinfo(hostsvc,hostinfo,maxlen,svccodes)
char *hostsvc;
char *hostinfo;
int maxlen;
char *svccodes;
{
int rc = 0;
FILE *fp = NULL;
char entry[MAXLINE];
char ipaddr[MAXLINE],name[MAXLINE],ipmatch[MAXLINE];
char workhostsvc[MAXLINE];
int	getlinebbhosts();
struct servent *service;
int	port;
char	svccode[MAXLINE],svcnum[MAXLINE],*workptr,*saveptr,svcmask[MAXLINE];

	memset(hostinfo,0,maxlen);

	while( getlinebbhosts(&fp,entry,sizeof(entry),LINEBBHOSTS_IPADDR) == 1 ) {

		if( (strlen(entry) > sizeof(ipaddr)-1) ) {
			entry[sizeof(ipaddr)-1] = '\0';
		}
		memset(ipaddr,0,sizeof(ipaddr));
		memset(name,0,sizeof(name));

		sscanf(entry,"%s %s",ipaddr,name);
		/* Remove dots in IP addr */
		replacestr(ipaddr,sizeof(ipaddr),".","");

		memset(workhostsvc,0,sizeof(workhostsvc));
		strncpy(workhostsvc,hostsvc,sizeof(workhostsvc)-1);

		sprintf(ipmatch,"[0-9][0-9]*%s",ipaddr);
		if( match(hostsvc,ipmatch,REG_FULL) ) {
			memset(svccode,0,sizeof(svccode));
			memset(svcnum,0,sizeof(svcnum));
			/* Get svc code, hostsvc - ipaddr */
			workhostsvc[strlen(workhostsvc)-strlen(ipaddr)] = '\0';
			/* Is NET err ? (^7) */
			if( strncmp(workhostsvc,neterr,strlen(neterr)) == 0 ) {
				/* get svc name fromn /etc/services */
				port = -1;
				port = atoi(&workhostsvc[strlen(neterr)]);
				if( (service=getservbyport(port,"tcp")) != NULL ) {
					strcpy(svccode,service->s_name);
				}
				else {
					continue;
				}
			}
			else {
				/* get svc name from error codes */
				sprintf(svcmask,":%s",workhostsvc);
				workptr = strstr(svccodes,svcmask);
				if( workptr ) {
					saveptr = workptr;
					while( (workptr-1) >= svccodes && !isspace(*(workptr-1)) ) {
						workptr--;
					}
					/* no name defined as in ...   :100 instead of disk:100 */
					if( workptr == saveptr ) {
						continue;
					}
					*saveptr = ' ';
					sscanf(workptr,"%s %s",svccode,svcnum);
					*saveptr = ':';
				}
				else {
					continue;
				}
			}
			/* save info */
			if( fqdn != 1 ) {
				workptr = strchr(name,'.');
				if( workptr ) {
					*workptr = '\0';
				}
			}

			/* Save host (xxx.yyy.com) svc (disk) */
			sprintf(hostinfo,"%s %s",name,svccode);

			rc = 1;
			fclose(fp);

			break;
		}
	}

	return(rc);
}

static int getsetup(dstval,token,maxlen)
char *dstval;
char *token;
int  maxlen;
{
FILE	*fp;
char	setupfile[MAXLINE];
char	setupline[MAXLINE];
char	worktoken[MAXLINE];
int	cont,rc;

	if( !dstval || !token ) {
		return(0);
	}

	if( *token == '\0' ) {
		return(0);
	}

	memset(dstval,0,maxlen);
	cont = 0;

	sprintf(setupfile,"%s/etc/bbwarnsetup.cfg",bbhome);
	sprintf(worktoken,"%s:",token);

	rc = 1;
	
	/* Open etc/bbwarnsetup.cfg */
	if( (fp=fopen(setupfile,"r")) != NULL ) {
		while( fgets(setupline,sizeof(setupline)-1,fp) != NULL ) {
			stripleadtrailspaces(setupline);
			if( (cont == 0 && strncmp(setupline,worktoken,strlen(worktoken)) == 0) || (cont == 1) ) {
				if( cont == 0 ) {
					stripleadtrailspaces(&setupline[strlen(worktoken)]);
					strncat(dstval,&setupline[strlen(worktoken)],maxlen-strlen(dstval)-1);
				}
				else {
					strncat(dstval,setupline,maxlen-strlen(dstval)-1);
				}
				rc = 0;
				/* Do we have a line continuation character ? */
				if( dstval[strlen(dstval)-1] != '\\' ) {
					break;		/* nope */
				}
				else {
					/* Remove the continuation character */
					dstval[strlen(dstval)-1] = '\0';
					cont = 1;
				}
			}
		}
		fclose(fp);
	}

	return(rc);

}

/*
 * Extract initial delay and delay from recipient
 * 0 - error
 * 1 - no error
 */
static int getdelay(rcpt,initdelay,delay,type,pagedelay)
char *rcpt;
int *initdelay;
int *delay;
int *type;
int pagedelay;
{
char *pgptr;
char workbuf[MAXLINE];

	if( (rcpt == NULL) || (initdelay == NULL) || (delay == NULL) || (pagedelay < 0) ) {
		return(0);
	}

	*delay = pagedelay;
	*initdelay = 0;
	
	pgptr = strchr(rcpt,':');
	if( pgptr != NULL ) {
		++pgptr;
		strcpy(workbuf,pgptr);	/* Save full override qualifier */
		/* Now just get the initial delay value */
		if( *pgptr == '~' ) {
			/*
			 * recipient:~XXX[-YYY]
			 */
			*type = PAGE_INITDELAY;
			pgptr++;
			if( sscanf(pgptr,"%d-%d",initdelay,delay) != 2 ) {
				*initdelay = atoi(pgptr);
#if DEBUG
			        fprintf(stderr,"getdelay(): PAGE_INITDELAY:ARGS!=2 - initdelay = %d, delay = %d\n",*initdelay,*delay);
			        fflush(stderr);
#endif
			}
			else {
#if DEBUG
			        fprintf(stderr,"getdelay(): PAGE_INITDELAY:ARGS==2 - initdelay = %d, delay = %d\n",*initdelay,*delay);
			        fflush(stderr);
#endif
			}
		}
		else if( *pgptr == '^') {
			/*
			 * recipient:^XXX[-YYY]
			 */
			*type = PAGE_ESCALATE;
			pgptr++;
			if( sscanf(pgptr,"%d-%d",initdelay,delay) != 2 ) {
				*initdelay = atoi(pgptr);
#if DEBUG
			        fprintf(stderr,"getdelay(): PAGE_ESCALATE:ARGS!=2 - initdelay = %d, delay = %d\n",*initdelay,*delay);
			        fflush(stderr);
#endif
			}
			else {
#if DEBUG
			        fprintf(stderr,"getdelay(): PAGE_ESCALATE:ARGS==2 - initdelay = %d, delay = %d\n",*initdelay,*delay);
			        fflush(stderr);
#endif
			}
		}
		else {
			/*
			 * recipient:XXX
			 */
			*type = PAGE_BASIC;
			*initdelay = 0;
			*delay = atoi(pgptr);
#if DEBUG
		        fprintf(stderr,"getdelay(): PAGE_BASIC:NONDEFAULT - initdelay = %d, delay = %d\n",*initdelay,*delay);
		        fflush(stderr);
#endif
		}
	}
	else {
		*initdelay = 0;
		*delay = pagedelay;
		*type = PAGE_BASIC;
#if DEBUG
		fprintf(stderr,"getdelay(): PAGE_BASIC:DEFAULT - initdelay = %d, delay = %d\n",*initdelay,*delay);
		fflush(stderr);
#endif
	}

	return(1);
}


void expand_briefrcpts(rcptslist,maxlen)
char *rcptslist;
int  maxlen;
{
char *newrcptslist, lastchar, pgrcpts[MAXLINE];
char *workptr, *qualptr, *newpgrs;
int  len;
int  errdone = 0;

	if( !rcptslist ) {
		return;
	}

	stripleadtrailspaces(rcptslist);
	if( strlen(rcptslist) == 0 ) {
		return;
	}

	if( (newrcptslist=(char *) calloc(1,maxlen)) == NULL) {
		return;
	}

	workptr = rcptslist;
	while( *workptr != '\0' ) {
		len = strcspn(workptr," \t");
		/* Keep the last char to reset it later */
		lastchar = *(workptr+len);
		/* Terminate recipient */
		*(workptr+len) = '\0';
		/* recipient does not contain qualifier */
		if( (qualptr = strchr(workptr,':')) != NULL ) {
			*qualptr = '\0';
		}
		getsetup(pgrcpts,workptr,sizeof(pgrcpts));
		if( strlen(pgrcpts) > 0 ) {
			/* Remove qualifiers from recipients */
			while( (qualptr = strchr(pgrcpts,':')) != NULL ) {
				while( *qualptr && !isspace(*qualptr) ) {
					*qualptr = ' ';
					qualptr++;
				}
			}
			/* Remove extra spaces generated */
			space_sep(pgrcpts);
			newpgrs = pgrcpts;
		}
		else {
			newpgrs = workptr;
		}
		/* Make sure new list will stay within bounds */
		/* I know, I could go for each rcpt but hey */
		/* if someone ever gets this filled up they deserve */
		/* be shot ! > 100 recipients ! */
		if( (strlen(newrcptslist)+strlen(newpgrs)+2) < (size_t)maxlen ) {
			if(strlen(newrcptslist) > 0) {
				strcat(newrcptslist," ");
			}
			strcat(newrcptslist,newpgrs);
		}
		else {
			/* Only complain once */
			if( errdone == 0 ) {
				bb_errmsg("bbpage","Page group expansion failed - too many recipients");
				errdone = 1;
			}
		}
		/* Go to next recipient */
		workptr += len;
		/* Remember our old last char, put it back */
		*workptr = lastchar;
		while( isspace(*workptr) ) {
			workptr++;
		}
	}

	strcpy(rcptslist,newrcptslist);
	free(newrcptslist);
	return;
}

static int save_notif(hostsvc,machip,rcptentry,svcnum,downsecsmsg,recovered)
char *hostsvc;
char *machip;
char *rcptentry;
char *svcnum;
char *downsecsmsg;
int  recovered;
{
char	logline[MAXLINE];
char	notiflog[MAXLINE];

	if( recovered == 1 ) {
		sprintf(notiflog,"%s/recoverymsgs.log",bbacksdir);
	}
	else {
		sprintf(notiflog,"%s/notifications.log",bbacksdir);
	}
	
#if DEBUG
	fprintf(stderr,"notiflog: <%s>\n",notiflog);
	fflush(stderr);
#endif

	sprintf(logline,"%s %s (%s) %s %d %s %s\n",gettimestr()
							,hostsvc
							,machip
							,rcptentry
							,(int)time(NULL)
							,svcnum
							,downsecsmsg);
	return(appendfile(notiflog,logline));
}

static int save_recoveries(host,svc,downsecs)
char *host;
char *svc;
int downsecs;
{
char	logline[MAXLINE];
char	logname[MAXLINE];

	sprintf(logname,"%s/recoveries.log",bbacksdir);
	
	sprintf(logline,"%s %s %s %d %d\n",gettimestr()
						,host
						,svc
						,(int)time(NULL)
						,downsecs);
	return(appendfile(logname,logline));
}

static int save_acklog(np_acknumber,delay,acknumber,np_filename,np_host,np_color,message)
char *np_acknumber;
char *delay;
char *acknumber;
char *np_filename;
char *np_host;
char *np_color;
char *message;
{
char	logline[MAXLINE];
char	logname[MAXLINE];
time_t	timenow;

	timenow = time(NULL);
	sprintf(logname,"%s/acklog",bbacksdir);
	
	sprintf(logline,"%d\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",timenow
							,np_acknumber
							,delay
							,acknumber
							,np_filename
							,np_host
							,np_color
							,message);
	return(appendfile(logname,logline));
}


static int send_mail(mailmsg,subject,rcpt)
char *mailmsg;
char *subject;
char *rcpt;
{
char *mail;
char mailcmd[MAXLINE];
FILE *pipef;
char recipient[MAXLINE];

#if DEBUG
	fprintf(stderr,"Sending out the following mail message:\n");
	fprintf(stderr,"Subject: %s\n",subject);
	fprintf(stderr,"Text: %s\n",mailmsg);
	fprintf(stderr,"Recipient: %s\n",rcpt);
	fflush(stderr);
#endif

	mail = getenv("MAIL");
	if( !mail ) {
		mail = "";
	}
	if( strlen(mail) == 0 ) {
		fprintf(stderr,"MAIL env variable not set\n");
		fflush(stderr);
		return(0);
	}

	if( (strlen(mail) + strlen(subject) + strlen(recipient)) > (MAXLINE-1) ) {
		fprintf(stderr,"MAIL too large\n");
		fflush(stderr);
		return(0);
	}

	if( match(rcpt,"ep-.*",REG_FULL) == 1 ) {
		strcpy(recipient,rcpt+3);
	}
	else {
		strcpy(recipient,rcpt);
	}

	memset(mailcmd,0,sizeof(mailcmd));

	replacestr(subject,sizeof(subject),"'","");
	replacestr(recipient,sizeof(recipient),"'","");
	sprintf(mailcmd,"%s '%s' '%s'",mail,subject,recipient);

	if( (pipef=popen(mailcmd,"w")) != NULL ) {
		fprintf(pipef,"%s",mailmsg);
		pclose(pipef);
	}
	else {
		fprintf(stderr,"Could not popen() to send out mail");
		fflush(stderr);
		return(0);
	}

	return(1);
}

static int send_numeric(nummsg,prefix,suffix,rcpt)
char *nummsg;
char *prefix;
char *suffix;
char *rcpt;
{
#ifdef SCO3
pid_t child;
#else
int child;
#endif
int status;
char cmd[MAXLINE];
char cmdarg1[MAXLINE];
char cmdarg2[MAXLINE];
char cmdarg3[MAXLINE];

#if DEBUG
	fprintf(stderr,"Sending out the following numeric message:\n");
	fprintf(stderr,"Numeric code: %s\n",nummsg);
	fprintf(stderr,"Recipient: %s\n",rcpt);
	fflush(stderr);
#endif

	if((child = fork()) < 0) {
		fprintf(stderr,"Couldn't fork() to send numeric message\n");
		fflush(stderr);
		return(0);
	}

	if (child == 0) {	/* THE CHILD */
		sprintf(cmd,"%s/bin/sendmsg",bbhome);
		sprintf(cmdarg1,"%s/etc/numeric.scr",bbhome);
		sprintf(cmdarg2,"%s%s",prefix,rcpt);
		sprintf(cmdarg3,"%s%s",nummsg,suffix);
		execlp(cmd,cmd,cmdarg1,cmdarg2,cmdarg3,(char *)NULL);
		fprintf(stderr,"Couldn't execlp() to send numeric message\n");
		fflush(stderr);
		exit(1);
	}

#ifdef ZOMBIE
	wait(&status);
#endif

	return(1);
}

static int send_sms(smsmsg,rcpt)
char *smsmsg;
char *rcpt;
{
#ifdef SCO3
pid_t child;
#else
int child;
#endif
int status;
char cmd[MAXLINE];
char cmdarg1[MAXLINE];
char filename[MAXLINE];
char recipient[MAXLINE];

#if DEBUG
	fprintf(stderr,"Sending out the following SMS message:\n");
	fprintf(stderr,"SMS msg: %s\n",smsmsg);
	fprintf(stderr,"Recipient: %s\n",rcpt);
	fflush(stderr);
#endif

	strcpy(recipient,rcpt+4);

	if((child = fork()) < 0) {
		fprintf(stderr,"Couldn't fork() to send SMS message\n");
		fflush(stderr);
		return(0);
	}

	if (child == 0) {	/* THE CHILD */
		sprintf(filename,"%s/sms-%d",bbtmpdir,getpid());
		if( savefile(filename,smsmsg) != 1 ) {
			fprintf(stderr,"Couldn't create SMS message file for %s\n",recipient);
			fflush(stderr);
			exit(0);
		}
		sprintf(cmd,"%s/bin/sendmsg",bbhome);
		sprintf(cmdarg1,"%s/etc/sms.scr",bbhome);
		execlp(cmd,cmd,cmdarg1,filename,recipient,(char *)NULL);
		unlink(filename);
		fprintf(stderr,"Couldn't execlp() to send SMS message\n");
		fflush(stderr);
		exit(1);
	}

#ifdef ZOMBIE
	wait(&status);
#else
	waitpid(child,&status,0);
#endif

	unlink(filename);

	return(1);
}

static int send_alpha(alphamsg,rcpt)
char *alphamsg;
char *rcpt;
{
#ifdef SCO3
pid_t child;
#else
int child;
#endif
int status;
char recipient[MAXLINE];
struct stat statinfo;
char *alphapgr;

#if DEBUG
	fprintf(stderr,"Sending out the following Alpha message:\n");
	fprintf(stderr,"Alpha msg: %s\n",alphamsg);
	fprintf(stderr,"Recipient: %s\n",rcpt);
	fflush(stderr);
#endif

	alphapgr = getenv("ALPHAPGR");
	if( !alphapgr ) {
		alphapgr = "";
	}
	if( strlen(alphapgr) == 0 ) {
		fprintf(stderr,"ALPHAPGR env variable not set\n");
		fflush(stderr);
		return(0);
	}

	if( stat(alphapgr,&statinfo) != 0 ) {
		fprintf(stderr,"Alpha pager program <%s> not found\n",alphapgr);
		fflush(stderr);
		return(0);
	}

	strcpy(recipient,rcpt+6);

	if((child = fork()) < 0) {
		fprintf(stderr,"Couldn't fork() to send Alpha message\n");
		fflush(stderr);
		return(0);
	}

	if (child == 0) {	/* THE CHILD */
		execlp(alphapgr,alphapgr,recipient,alphamsg,(char *)NULL);
		fprintf(stderr,"Couldn't execlp() to send Alpha message\n");
		fflush(stderr);
		exit(1);
	}

#ifdef ZOMBIE
	wait(&status);
#endif

	return(1);
}

static int send_qpage(qpagemsg,rcpt)
char *qpagemsg;
char *rcpt;
{
char qpagecmd[MAXLINE];
char recipient[MAXLINE];
struct stat statinfo;
char *qpage, *qpageargs;
FILE *pipef;
char arguments[MAXLINE];

#if DEBUG
	fprintf(stderr,"Sending out the following qpage message:\n");
	fprintf(stderr,"Qpage msg: %s\n",qpagemsg);
	fprintf(stderr,"Recipient: %s\n",rcpt);
	fflush(stderr);
#endif

	qpage = getenv("QPAGE");
	if( !qpage ) {
		qpage = "";
	}
	if( strlen(qpage) == 0 ) {
		fprintf(stderr,"QPAGE env variable not set\n");
		fflush(stderr);
		return(0);
	}
	qpageargs = getenv("QPAGEARGS");
	if( !qpageargs ) {
		qpageargs = "";
	}
	if( strlen(qpageargs) == 0 ) {
		fprintf(stderr,"QPAGEARGS env variable not set\n");
		fflush(stderr);
		return(0);
	}

	if( stat(qpage,&statinfo) != 0 ) {
		fprintf(stderr,"Qpage program <%s> not found\n",qpage);
		fflush(stderr);
		return(0);
	}

	strcpy(recipient,rcpt+3);

	memset(arguments,0,sizeof(arguments));
	strncpy(arguments,qpageargs,sizeof(arguments));
	replacestr(arguments,sizeof(arguments),"'","");
	replacestr(recipient,sizeof(recipient),"'","");
	memset(qpagecmd,0,sizeof(qpagecmd));
	sprintf(qpagecmd,"%s '%s' -p '%s'",qpage,arguments,recipient);

	if( (pipef=popen(qpagecmd,"w")) != NULL ) {
		fprintf(pipef,"%s",qpagemsg);
		pclose(pipef);
	}
	else {
		fprintf(stderr,"Could not popen() to use Qpage");
		fflush(stderr);
		return(0);
	}

	return(1);
}

static int send_sendpage(sendpagemsg,rcpt)
char *sendpagemsg;
char *rcpt;
{
char sendpagecmd[MAXLINE];
char recipient[MAXLINE];
struct stat statinfo;
char *sendpage, *sendpageargs;
FILE *pipef;
char arguments[MAXLINE];

#if DEBUG
	fprintf(stderr,"Sending out the following sendpage message:\n");
	fprintf(stderr,"Sendpage msg: %s\n",sendpagemsg);
	fprintf(stderr,"Recipient: %s\n",rcpt);
	fflush(stderr);
#endif

	sendpage = getenv("SENDPAGE");
	if( !sendpage ) {
		sendpage = "";
	}
	if( strlen(sendpage) == 0 ) {
		fprintf(stderr,"SENDPAGE env variable not set\n");
		fflush(stderr);
		return(0);
	}
	sendpageargs = getenv("SENDPAGEARGS");
	if( !sendpageargs ) {
		sendpageargs = "";
	}
	if( strlen(sendpageargs) == 0 ) {
		fprintf(stderr,"SENDPAGEARGS env variable not set\n");
		fflush(stderr);
		return(0);
	}

	if( stat(sendpage,&statinfo) != 0 ) {
		fprintf(stderr,"Sendpage program <%s> not found\n",sendpage);
		fflush(stderr);
		return(0);
	}

	/* It's either sp- or hsp- */
	if( strncmp(rcpt,"sp-",3) == 0 ) {
		strcpy(recipient,rcpt+3);
	}
	else {
		strcpy(recipient,rcpt+4);
	}

	memset(sendpagecmd,0,sizeof(sendpagecmd));
	memset(arguments,0,sizeof(arguments));
	strncpy(arguments,sendpageargs,sizeof(arguments));
	replacestr(arguments,sizeof(arguments),"'","");
	replacestr(recipient,sizeof(recipient),"'","");

	if( strncmp(rcpt,"sp-",3) == 0 ) {
		sprintf(sendpagecmd,"%s '%s' '%s'",sendpage,arguments,recipient);
	}
	else {
		sprintf(sendpagecmd,"%s '%s' '-p%s'",sendpage,arguments,recipient);
	}

	if( (pipef=popen(sendpagecmd,"w")) != NULL ) {
		fprintf(pipef,"%s",sendpagemsg);
		pclose(pipef);
	}
	else {
		fprintf(stderr,"Could not popen() to use Sendpage");
		fflush(stderr);
		return(0);
	}

	return(1);
}

static int send_smsclient(smsclientmsg,rcpt)
char *smsclientmsg;
char *rcpt;
{
char smsclient[MAXLINE];
char recipient[MAXLINE];
char smsmsg[MAXLINE];
struct stat statinfo;
#ifdef SCO3
pid_t child;
#else
int child;
#endif
int status;

#if DEBUG
	fprintf(stderr,"Sending out the following smsclient message:\n");
	fprintf(stderr,"smsclient msg: %s\n",smsclientmsg);
	fprintf(stderr,"Recipient: %s\n",rcpt);
	fflush(stderr);
#endif

	sprintf(smsclient,"%s/bin/sendsms",bbhome);
	if( stat(smsclient,&statinfo) != 0 ) {
		fprintf(stderr,"smsclient program <%s> not found\n",smsclient);
		fflush(stderr);
		return(0);
	}

	strcpy(recipient,rcpt+10);

	if((child = fork()) < 0) {
		fprintf(stderr,"Couldn't fork() to send smsclient message\n");
		fflush(stderr);
		return(0);
	}

	if (child == 0) {	/* THE CHILD */
		memset(smsmsg,0,sizeof(smsmsg));
		strncpy(smsmsg,smsclientmsg,150);
		/* Send the right buffer out Rob ! */
		/* Thanks to Douwe.Dijkstra@I-Pay.com */
		execlp(smsclient,smsclient,recipient,smsmsg,(char *)NULL);
		fprintf(stderr,"Couldn't execlp() to send smsclient message\n");
		fflush(stderr);
		exit(1);
	}

#ifdef ZOMBIE
	wait(&status);
#endif

	return(1);
}

static int send_snmptrap(msg,rcpt,ipaddr,svc,recovered)
char *msg;
char *rcpt;
char *ipaddr;
char *svc;
int recovered;
{
char snmptrap_pgm[MAXLINE],snmptrap_type[MAXLINE],entoid[MAXLINE],trapcodes[MAXLINE];
char recipient[MAXLINE],*workptr,*workptr1,workbuf[MAXLINE];
#ifdef SCO3
pid_t child;
#else
int child;
#endif
int status;
struct stat statinfo;
char redlines[MAXLINE],yellowlines[MAXLINE];
char trapmsg[MAXLINE],outtrapmsg[MAXLINE];
char arg1[MAXLINE],arg2[MAXLINE],arg3[MAXLINE],arg4[MAXLINE],arg5[MAXLINE],arg6[MAXLINE],arg7[MAXLINE];
char specifictype[MAXLINE],generaltype[MAXLINE];
int specifictype_int;

	getsetup(snmptrap_pgm,"snmptrap_pgm", sizeof(snmptrap_pgm));
	if( strlen(snmptrap_pgm) == 0 ) {
		fprintf(stderr,"SNMP trap program location is undefined in bbwarnsetup.cfg (snmptrap_pgm)\n");
		fflush(stderr);
		return(0);
	}
#if DEBUG
	fprintf(stderr,"snmptrap program location: <%s>\n",snmptrap_pgm);
	fflush(stderr);
#endif

	if( stat(snmptrap_pgm,&statinfo) != 0 ) {
		fprintf(stderr,"SNMP trap program <%s> not found\n",snmptrap_pgm);
		fflush(stderr);
		return(0);
	}

	getsetup(snmptrap_type,"snmptrap_type", sizeof(snmptrap_type));
	if( strlen(snmptrap_type) == 0 ) {
		fprintf(stderr,"SNMP trap type is undefined in bbwarnsetup.cfg (snmptrap_type)\n");
		fflush(stderr);
		return(0);
	}
#if DEBUG
	fprintf(stderr,"snmptrap type: <%s>\n",snmptrap_type);
	fflush(stderr);
#endif
	if( !((strcmp(snmptrap_type,"CMU") == 0)
		|| (strcmp(snmptrap_type,"UCD") == 0)
		|| (strcmp(snmptrap_type,"SOLARIS") == 0)
		|| (strcmp(snmptrap_type,"HPOV") == 0)) ) {
		fprintf(stderr,"Unknown SNMP trap type <%s> \n", snmptrap_type);
		fflush(stderr);
		return(0);
	}

	getsetup(entoid,"entoid", sizeof(entoid));
	if( strlen(entoid) == 0 ) {
		fprintf(stderr,"SNMP enterprise OID is undefined in bbwarnsetup.cfg (entoid)\n");
		fflush(stderr);
		return(0);
	}
#if DEBUG
	fprintf(stderr,"Enterprise OID: <%s>\n",entoid);
	fflush(stderr);
#endif

	getsetup(trapcodes,"trapcodes", sizeof(trapcodes));
	if( strlen(trapcodes) == 0 ) {
		fprintf(stderr,"SNMP trap codes are undefined in bbwarnsetup.cfg (trapcodes)\n");
		fflush(stderr);
		return(0);
	}
#if DEBUG
	fprintf(stderr,"snmptrap trap codes: <%s>\n",trapcodes);
	fflush(stderr);
#endif

	strcpy(recipient,rcpt+5);

	memset(arg1,0,sizeof(arg1));
	memset(arg2,0,sizeof(arg2));
	memset(arg3,0,sizeof(arg3));
	memset(arg4,0,sizeof(arg4));
	memset(arg5,0,sizeof(arg5));
	memset(arg6,0,sizeof(arg6));
	memset(arg7,0,sizeof(arg7));

	memset(redlines,0,sizeof(redlines));
	memset(yellowlines,0,sizeof(yellowlines));
	memset(trapmsg,0,sizeof(trapmsg));

	if( strcmp(svc,"disk") == 0 ) {
		sscanf(msg,"%s %s %s %s %s %s %s",arg1,arg2,arg3,arg4,arg5,arg6,arg7);
		sprintf(trapmsg,"%s:%s %s %s %s %s %s %s %s - ",ipaddr,svc,arg1,arg2,arg3,arg4,arg5,arg6,arg7);
		workptr = msg;
		while( (workptr=strstr(workptr,"&red")) != NULL ) {
			memset(arg2,0,sizeof(arg2));
			memset(arg3,0,sizeof(arg3));
			sscanf(workptr,"%*s %s %s",arg2,arg3);
			if( (strlen(arg2) + strlen(arg3) + 4 + strlen(trapmsg)) < (MAXTRAPMSGSIZE) ) {
				strcat(trapmsg,arg2);
				strcat(trapmsg," ");
				strcat(trapmsg,arg3);
				strcat(trapmsg,"  ");
			}
			else {
				break;
			}
			workptr++;
		}
		workptr = msg;
		while( (workptr=strstr(workptr,"&yellow")) != NULL ) {
			memset(arg2,0,sizeof(arg2));
			memset(arg3,0,sizeof(arg3));
			sscanf(workptr,"%*s %s %s",arg2,arg3);
			if( (strlen(arg2) + strlen(arg3) + 4 + strlen(trapmsg)) < (MAXTRAPMSGSIZE) ) {
				strcat(trapmsg,arg2);
				strcat(trapmsg," ");
				strcat(trapmsg,arg3);
				strcat(trapmsg,"  ");
			}
			else {
				break;
			}
			workptr++;
		}
	}
	else if( strcmp(svc,"procs") == 0 ) {
		workptr = strchr(msg,'\r');
		workptr1 = strchr(msg,'\n');
		sprintf(trapmsg,"%s:%s ",ipaddr,svc);
		if( workptr == NULL && workptr1 == NULL ) {
			strncat(trapmsg,msg,MAXTRAPMSGSIZE);
		}
		else if( workptr != NULL && workptr1 == NULL  ) {
			if( (workptr - msg) < MAXTRAPMSGSIZE ) {
				strncat(trapmsg,msg,workptr-msg);
			}
			else {
				strncat(trapmsg,msg,MAXTRAPMSGSIZE);
			}
		}
		else if( workptr == NULL && workptr1 != NULL  ) {
			if( (workptr1 - msg) < MAXTRAPMSGSIZE ) {
				strncat(trapmsg,msg,workptr1-msg);
			}
			else {
				strncat(trapmsg,msg,MAXTRAPMSGSIZE);
			}
		}
		else {
			if( workptr > workptr1 ) {
				workptr = workptr1;
			}
			if( (workptr - msg) < MAXTRAPMSGSIZE ) {
				strncat(trapmsg,msg,workptr-msg);
			}
			else {
				strncat(trapmsg,msg,MAXTRAPMSGSIZE);
			}
		}
	}
	else {
		sprintf(trapmsg,"%s:%s ",ipaddr,svc);
	}

#if DEBUG
	fprintf(stderr,"snmptrap message: <%s>\n",trapmsg);
	fflush(stderr);
#endif
	sprintf(workbuf,"%s:",svc);
	workptr = strstr(trapcodes,workbuf);
	if( workptr == NULL ) {
		fprintf(stderr,"SNMP trap code for <%s> not defined in bbwarnsetup.cfg (trapcodes)\n",svc);
		fflush(stderr);
		strcpy(specifictype,"999");
	}
	else {
		workptr += strlen(workbuf);
		sscanf(workptr,"%s",specifictype);
		if( recovered == 1 ) {
			specifictype_int = atoi(specifictype) + 1;
			sprintf(specifictype,"%d",specifictype_int);
		}
	}
	strcpy(generaltype,"6");

	if((child = fork()) < 0) {
		fprintf(stderr,"Couldn't fork() to send SNMP trap message\n");
		fflush(stderr);
		return(0);
	}

	if (child == 0) {	/* THE CHILD */
		if( strcmp(snmptrap_type,"SOLARIS") == 0 ) {
			/* Solaris wants spaces between (%s) */
			/* Thanks to David Balkwill <dbalkwill@hemscott.co.uk> */
			sprintf(outtrapmsg,"%s STRING ( %s )",entoid,trapmsg);
#if DEBUG
			fprintf(stderr,"Sending out the following SOLARIS SNMP trap message:\n");
			fprintf(stderr,"Trap msg: %s\n",outtrapmsg);
			fprintf(stderr,"Trap server: %s\n",recipient);
			fflush(stderr);
#endif
			execlp(snmptrap_pgm,snmptrap_pgm,"-h",recipient,"-c","public","-e",entoid,"-i",ipaddr,"-g",generaltype,"-s",specifictype,"-a",outtrapmsg, (char *)NULL);
		}
		else if( strcmp(snmptrap_type,"CMU") == 0 ) {
			sprintf(outtrapmsg,"%s STRING(%s)",entoid,trapmsg);
#if DEBUG
			fprintf(stderr,"Sending out the following CMU SNMP trap message:\n");
			fprintf(stderr,"Trap msg: %s\n",outtrapmsg);
			fprintf(stderr,"Trap server: %s\n",recipient);
			fflush(stderr);
#endif
			execlp(snmptrap_pgm,snmptrap_pgm,"-a",ipaddr,"-d",recipient,"",generaltype,specifictype,outtrapmsg, (char *)NULL);
		}
		else if( strcmp(snmptrap_type,"UCD") == 0 ) {
#if DEBUG
			fprintf(stderr,"Sending out the following UCD SNMP trap message:\n");
			fprintf(stderr,"Trap server: %s\n",recipient);
			fprintf(stderr,"Trap msg: %s\n",trapmsg);
			fprintf(stderr,"recipient: %s\n",recipient);
			fprintf(stderr,"entoid: %s\n",entoid);
			fprintf(stderr,"ipaddr: %s\n",ipaddr);
			fprintf(stderr,"generaltype: %s\n",generaltype);
			fprintf(stderr,"specifictype: %s\n",specifictype);
			fflush(stderr);
#endif
			execlp(snmptrap_pgm,snmptrap_pgm,"-v","1",recipient,"",entoid,ipaddr,generaltype,specifictype,"0",entoid,"s", trapmsg, (char *)NULL);
		}
		else if( strcmp(snmptrap_type,"HPOV") == 0 ) {
			fprintf(stderr,"HP Openview based SNMP trap handling not yet implemented\n");
			fflush(stderr);
			exit(0);
		}
		else {
			fprintf(stderr,"Unknown snmptrap type <%s> defined in bbwarnsetup.cfg\n",snmptrap_type);
			fflush(stderr);
			exit(0);
		}
	}

#ifdef ZOMBIE
	wait(&status);
#endif

	return(1);
}


static int send_extpage(rcptentry)
char *rcptentry;
{
char extpage[MAXLINE];
char scriptname[MAXLINE];
struct stat statinfo;
#ifdef SCO3
pid_t child;
#else
int child;
#endif
int  status;
char *workptr;
char errormsg[MAXLINE];

#if DEBUG
	fprintf(stderr,"Sending out using an externally defined method \n");
	fprintf(stderr,"Recipient: <%s>\n",rcptentry);
	fflush(stderr);
#endif

	if( rcptentry == NULL ) {
		return(0);
	}

	/* A recipient must be at least ext-X- */
	/* where X is any character */
	if( strlen(rcptentry) < 7 ) {
		return(0);
	}

	/* It must start with ext- */
	if( strncmp(rcptentry,"ext-",4) != 0 ) {
		return(0);
	}

	/* it must be in the form ext-XXX- */
	memset(scriptname,0,sizeof(scriptname));
	strncpy(scriptname,rcptentry+4,sizeof(scriptname)-1);
	if( (workptr=strchr(scriptname,'-')) == NULL ) {
		return(0);
	}
	*workptr = '\0';
	workptr++;

	/* Path name of script must fit in extpage */
	/* BBHOME + /ext/pg/ + scriptname + NULL */
	if( strlen(bbhome) + 9 + strlen(scriptname) >= sizeof(extpage) ) {
		return(0);
	}

	sprintf(extpage,"%s/ext/pg/%s",bbhome,scriptname);
	
	memset(errormsg,0,sizeof(errormsg));
	if( stat(extpage,&statinfo) != 0 ) {
		strcpy(errormsg,"Could not find script: ");
		strncat(errormsg,scriptname,sizeof(errormsg)-strlen(errormsg)-1);
		bb_errmsg("bbpage",errormsg);
		return(0);
	}

	if((child = fork()) < 0) {
		bb_errmsg("bbpage","Couldn't fork() for user defined notification script");
		return(0);
	}

	if (child == 0) {	/* THE CHILD */
		bb_putenv("RCPT",workptr,rcpt_env,sizeof(rcpt_env));
		execlp(extpage,extpage,(char *)NULL);
		strcpy(errormsg,"Couldn't execlp() ");
		strncat(errormsg,extpage,sizeof(errormsg)-strlen(errormsg)-1);
		bb_errmsg("bbpage",errormsg);
		exit(1);
	}

#ifdef ZOMBIE
	wait(&status);
#endif

	return(1);
}

int bb_page(argmsg)
char *argmsg;
{
char	workmsg[MAXLINE];
char	hostsvc[MAXLINE],bbhostsvc[MAXLINE];
char	msg[MAXLINE],*msgptr;
char	pagehelpusernum[MAXLINE];
struct stat	statinfo;
int	recovered;
char	bbwarn[16];
char	workfilename[MAXLINE];
char	arg2[MAXLINE];
FILE	*fp;
char	*workptr,*workptr1;
int	oldstylepagemsg;
char	hostinfo[MAXLINE];
char	redhost[MAXLINE],redsvc[MAXLINE];
char	machip[MAXLINE],redhostip[MAXLINE];
time_t	timenow;
struct tm	*time_tm;
int	ip1,ip2,ip3,ip4;
char	ruleargs[MAXRULEARGS][MAXLINE];
int	i,cont;
int	nowday;
int	nowtime;
char	machsvc[MAXLINE],svcerr[MAXLINE];
char	pagers[MAXLINE*2],pgrcpts[MAXLINE],pgpager[MAXLINE],*pgptr;
char	instr[MAXLINE],fullinstr[MAXLINE],usageline[MAXLINE*2],workline[MAXLINE*2],workline1[MAXLINE*2];
char	ignpagers[MAXLINE*2], *ptrpagers, *ignpager;
char	*beginptr,*endptr;
char	dayval[MAXLINE],timesval[MAXLINE],startdayval[MAXLINE],enddayval[MAXLINE],starttimesval[MAXLINE],endtimesval[MAXLINE];
int	startday,endday,starttimes,endtimes;
int	ignore;
char	hosts[MAXLINE*2],hostentry[MAXLINE],exhosts[MAXLINE*2],hghosts[MAXLINE],svcs[MAXLINE],exsvcs[MAXLINE];
char	*dayrange,*timesrange;
char	rcptentry[MAXLINE],rcptentry1[MAXLINE],rcptentry2[MAXLINE];
char	overrideval[MAXLINE],*overrideptr,*overrideptr1,*overrideptr2;
int	ftype;
char	pagedelayval[MAXLINE];
int	initdelay1,delay1,type1,initdelay2,delay2,type2;
char	bbnumeric[MAXLINE];
char	bbalpha[sizeof(msg)+MAXLINE];
char	*npfilecontents,npfilename[MAXLINE];
int	rc,rcptnum,randval,tmprandval,np_exists;
char	filemask[MAXLINE];
char	prefix[MAXLINE],suffix[MAXLINE],pagelevelsmail[MAXLINE],pagelevels[MAXLINE];
char	pagetype[MAXLINE],pageaddhtmlpath[MAXLINE];
DIR	*dirinfo;
char	bbgroup[MAXLINE],color[MAXLINE];
char	*bblogstatus,*bbwebhtmllogs,*cgibinurl,*bbwebhost,*bbwebhosturl;
char	downsecsmsg[MAXLINE],downsecsval[MAXLINE],briefrcpts[MAXLINE*2];
char	randvalstr[10],randvaltag[MAXLINE],randvalsubjtag[MAXLINE],htmllink[MAXLINE],tmprandvalstr[16];
char	mailsubject[MAXLINE];
char	numcode[MAXLINE];
struct bbpageinfo pginfo;
int	save_notification;
char	errormsg[MAXLINE];
extern	int purpleoffset;

	memset(&pginfo,0,sizeof(pginfo));
	memset(color,0,sizeof(color));

	sprintf(workfilename,"%s/etc/bbwarnrules.cfg",bbhome);
	if( stat(workfilename,&statinfo) != 0 ) {
		return(usage_done("bbwarnrules.cfg not found",1,&pginfo));
	}

	sprintf(workfilename,"%s/etc/bbwarnsetup.cfg",bbhome);
	if( stat(workfilename,&statinfo) != 0 ) {
		usage("bbwarnsetup.cfg not found - using defaults");
	}


#if DEBUG
	fprintf(stderr,"argmsg: %s\n",argmsg);
	fflush(stderr);
#endif


	/* 
	 * Not really needed, released code will be
	 * called withing bbd
	 *
	 * clean_string(argmsg,"`$;|&{}\\");
	 *
	 */

	memset(workmsg,0,sizeof(workmsg));
	strncpy(workmsg,argmsg,MAXLINE-1);

	stripleadtrailspaces(workmsg);

	msgptr = workmsg;
	while( *msgptr && !isspace(*msgptr) ) {
		msgptr++;
	}
	*msgptr = '\0';
	msgptr++;
	while(isspace(*msgptr)) {
		msgptr++;
	}

	if( strlen(msgptr) > 0 ) {
		strcpy(msg,msgptr);
#if DEBUG
		fprintf(stderr,"msg: %s\n",msg);
		fflush(stderr);
#endif
	}
	else {
		return(usage_done("notification message missing",2,&pginfo));
	}

	memset(hostsvc,0,sizeof(hostsvc));
	strncpy(hostsvc,workmsg,sizeof(hostsvc)-1);

	/* Don't do notifications on summaries */
	if( !strncmp(hostsvc,"summary.",strlen("summary.")) ) {
		return(done(0,&pginfo));
	}

#if DEBUG
	fprintf(stderr,"hostsvc: %s\n",hostsvc);
	fflush(stderr);
#endif

	/*
	 * if !FQDN then remove domain name
	 */
	if( fqdn != 1 ) {
		workptr = strrchr(hostsvc,'.');   /* Point to service name */
		workptr1 = strchr(hostsvc,',');	  /* Point to domain name */
		if( workptr && workptr1 && (workptr1 > workptr) ) {
			strcpy(workptr,workptr1);
		}
	}

	memset(arg2,0,sizeof(arg2));
	strncpy(arg2,msg,sizeof(arg2)-1);
	sscanf(msg,"%s",arg2);

#if DEBUG
	fprintf(stderr,"2nd word in message is: <%s>\n",arg2);
	fflush(stderr);
#endif

	recovered = 0;
	/* Check if notification comes from the paging web page */
	/* host.service tag is notify-admin.pagehelp		*/
	if( !strcmp(hostsvc,"notify-admin.pagehelp") ) {
#if DEBUG
		fprintf(stderr,"We have a \"notify-admin\" request\n",hostsvc);
		fflush(stderr);
#endif
		strcpy(pagehelpusernum,arg2);
	}
	else {
		/* Should you notify and not create any np_* tag files ? */
		/* used when color has become normal state again */
		if( !strcmp(arg2,"recovered") ) {
#if DEBUG
			fprintf(stderr,"We have a \"recovered\" message\n",hostsvc);
			fflush(stderr);
#endif
			sprintf(pginfo.recoverytagfile,"%s/nprec_%s",bbtmpdir,hostsvc);
			/* If multiple BBDISPLAY exists then a BBPAGER */
			/* may receive multiple recovery message for the */
			/* same event.  Only handle the 1st request */
			if( stat(pginfo.recoverytagfile,&statinfo)  == 0 ) {
				/* Don't do a done() because that'll remove */
				/* the associated nprec_ file */
				pginfo.recoverytagfile[0] = '\0';
				return(100);
			}
			if( (fp = fopen(pginfo.recoverytagfile,"w")) == NULL ) {
				fprintf(stderr,"Could not create recovery tag file\n");
				return(done(1,&pginfo));
			}
			fclose(fp);
			recovered = 1;
		}
		strcpy(color,arg2);
#if DEBUG
		fprintf(stderr,"color of msg: %s\n",color);
		fflush(stderr);
#endif
	}

	/* Has this BBPAGER been disabled */
	getsetup(bbwarn, "bbwarn", sizeof(bbwarn));
	strtoupper(bbwarn);

#if DEBUG
	fprintf(stderr,"bbwarn: %s\n",bbwarn);
	fflush(stderr);
#endif

	/*
	 * SMM - IF WE'RE IN FAILOVER MODE - OVERRIDE
	 */
	sprintf(workfilename,"%s/FAILOVER-BBPAGER",bbtmpdir);
	if( stat(workfilename,&statinfo) == 0 ) {
#if DEBUG
		fprintf(stderr,"bbwarn: %s, reset du to existence of %s\n",bbwarn,workfilename);
		fflush(stderr);
#endif
		strcpy(bbwarn,"TRUE");
	}

	/* If BBWARN is disabled, exit */
	if( (strlen(bbwarn) == 0) || strcmp(bbwarn,"TRUE") ) {
		return(done(0,&pginfo));
	}

	/*
	 * Get pagedelay value from config file
	 */
	getsetup(pagedelayval,"pagedelay",sizeof(pagedelayval));
	if( isdigit(pagedelayval[0]) ) {
		pginfo.pagedelay = atoi(pagedelayval);
	}
	else {
		pginfo.pagedelay = 15;
	}
#if DEBUG
	fprintf(stderr,"pagedelay: %s\n",pagedelayval);
	fflush(stderr);
#endif

	/*
	 * GET THE BBWARN RULES CONFIGURATION FILE DELIMITER
	 */
	strcpy(pginfo.cfgdelim,";");
	getsetup(pginfo.cfgdelim, "cfgdelim", sizeof(pginfo.cfgdelim));
#if DEBUG
	fprintf(stderr,"cfgdelim: %s\n",pginfo.cfgdelim);
	fflush(stderr);
#endif

	/*
	 * GET THE SERVICE:ERROR TAGS
	 */
	strcpy(pginfo.svcerrlist,"disk:100 cpu:200 procs:300 msgs:400 conn:500 http:600 dns:800 ERR:999");
	getsetup(pginfo.svcerrlist, "svcerrlist", sizeof(pginfo.svcerrlist));
#if DEBUG
	fprintf(stderr,"svcerrlist: %s\n",pginfo.svcerrlist);
	fflush(stderr);
#endif

	/*
	 * Get the code for required help when user uses HTML form
	 *   to page the admin(s)
	 */
	strcpy(pginfo.pagehelpcode ,"911");
	getsetup(pginfo.pagehelpcode, "pagehelpcode", sizeof(pginfo.pagehelpcode));
#if DEBUG
	fprintf(stderr,"pagehelpcode: %s\n",pginfo.pagehelpcode);
	fflush(stderr);
#endif

	memset(redhost,0,sizeof(redhost));
	memset(redsvc,0,sizeof(redsvc));

	workptr = strchr(hostsvc,'.');
	if( !workptr ) {

#if DEBUG
		fprintf(stderr,"Invalid host in message: %s\n",hostsvc);
		fprintf(stderr,"Is this a pre1.08 message ? if so upgrade your client\n");
		fflush(stderr);
#endif
		if ( match(hostsvc,"[0-9]*",REG_FULL) == 0 ) {
			return(usage_done("Invalid host defined in message",1,&pginfo));
		}

		/*
		 * Leave the following code here if we ever decide
		 * to support pre-1.08 clients
		 *
		 */

        	oldstylepagemsg = 1;

		/*
		 * We presume this is old style message
		 * Rebuild into a new BBWARN style message
		 * host.service (host,domain.service) is the 1st argument
		 * We have to rebuild the IP address without '.' and match with
		 * the incoming
		 */

		neterr = getenv("NETERR");
		if( !neterr || strlen(neterr) == 0 ) {
			neterr = "7";
		}

		memset(hostinfo,'\0',sizeof(hostinfo));
		if( getoldinfo(hostsvc,hostinfo,sizeof(hostinfo),pginfo.svcerrlist) ) {
			sscanf(hostinfo,"%s %s", redhost,redsvc);
			sprintf(bbhostsvc,"%s.%s",redhost,redsvc);
#if DEBUG
			fprintf(stderr,"hostinfo: (bbhostsvc:%s) (redhost:%s) (redsvc:%s)\n",bbhostsvc,redhost,redsvc);
			fflush(stderr);
#endif
		}
		else {
			/*
			 * An unmatched host may occur when the definition in the
			 * foreign bb-hosts file is not the same as the local one
			 * i.e 10.2.4.5  and 10.2.4.05
			 *  one produces 10245 and the other 102405
			 */
			strcpy(redsvc,"ERR");
			sprintf(redhost,"unmatched-%s",hostsvc);
			sprintf(bbhostsvc,"%s.%s",redhost,redsvc);
#if DEBUG
			fprintf(stderr,"hostinfo(unmatched): (bbhostsvc:%s) (redhost:%s) (redsvc:%s)\n",bbhostsvc,redhost,redsvc);
			fflush(stderr);
#endif
		}
	}
	else {
        	oldstylepagemsg = 0;
		strncpy(redhost,hostsvc,workptr-hostsvc);
		replacestr(redhost,sizeof(redhost),",",".");
		strcpy(redsvc,workptr+1);
		sprintf(bbhostsvc,"%s.%s",redhost,redsvc);
#if DEBUG
		fprintf(stderr,"hostinfo: (hostsvc:%s) (bbhostsvc:%s) (redhost:%s) (redsvc:%s)\n",hostsvc,bbhostsvc,redhost,redsvc);
		fflush(stderr);
#endif
	}


	/*
	 * Get the code for required help when user uses HTML form
	 *   to page the admin(s)
	 */
	memset(pginfo.ignforall,'\0',sizeof(pginfo.ignforall));
	getsetup(pginfo.ignforall, "ignforall", sizeof(pginfo.ignforall));
#if DEBUG
	fprintf(stderr,"ignforall: %s\n",pginfo.ignforall);
	fflush(stderr);
#endif

	/* Does this host match the ignore token ? */
	if( strlen(pginfo.ignforall) && match(hostsvc,pginfo.ignforall,REG_FULL) ) {
#if DEBUG
		fprintf(stderr,"host: %s matched ignforall regex: %s\n",hostsvc,pginfo.ignforall);
		fflush(stderr);
#endif
		return(done(0,&pginfo));
	}

	/*
	 * Get day of week and time of day
	 * day of week, 0-6
	 * time of day  0000-2359
	 */
	time(&timenow);
	time_tm = localtime(&timenow);
	nowday = time_tm->tm_wday;
	nowtime = (time_tm->tm_hour * 100) + time_tm->tm_min;

	/*
	 Get IP address of host (formatted) and service code
	 */
	memset(redhostip,0,sizeof(redhostip));
	memset(machsvc,0,sizeof(machsvc));
	if( getipaddr(redhost,redhostip,sizeof(redhostip),1) == 0 ) {

		sscanf(redhostip,"%d.%d.%d.%d",&ip1,&ip2,&ip3,&ip4);
		sprintf(machip,"%03d%03d%03d%03d",ip1,ip2,ip3,ip4);
		getsvccode(redsvc,svcerr,pginfo.svcerrlist);
		sprintf(machsvc,"%s.%s",redhost,redsvc);
#if DEBUG
		fprintf(stderr,"machip: %s - redsvc: %s - svcerr: %s\n",machip,redsvc,svcerr);
		fflush(stderr);
#endif
	}
	else {

		/* They're unmatched */
		/* but could be a message from the help HTML page */
		/* Is it ? */
		if( strcmp(redhost,"notify-admin") != 0 ) {
			/* Nope */
			strcpy(machip,"999999999999");
			/* Old way, obsolete */
			if( oldstylepagemsg == 1 ) {
				strcpy(svcerr,"999");
#if DEBUG
				fprintf(stderr,"machip: %s - svcerr: %s\n",machip,svcerr);
				fflush(stderr);
#endif
			}
			else {

				sprintf(redhost,"unmatched-%s",redhost);
				sprintf(machsvc,"%s.%s",redhost,redsvc);
				getsvccode(redsvc,svcerr,pginfo.svcerrlist);
#if DEBUG
				fprintf(stderr,"redhost: %s - machsvc: %s - svcerr: %s\n",redhost,machsvc,svcerr);
				fflush(stderr);
#endif
			}

		}
		else {
			/* This is a user help request from HTML form */

			strcpy(svcerr,pginfo.pagehelpcode);
			strcpy(machip,pagehelpusernum);
#if DEBUG
			fprintf(stderr,"machip: %s - svcerr: %s\n",machip,svcerr);
			fflush(stderr);
#endif
		}

	}


	sprintf(workfilename,"%s/etc/bbwarnrules.cfg",bbhome);
	if( (fp=fopen(workfilename,"r")) == NULL ) {
		return(usage_done("Can't open bbwarnrules.cfg",1,&pginfo));
	}


	cont = 0;
	memset(instr,0,sizeof(instr));
	memset(pagers,0,sizeof(pagers));
	memset(ignpagers,0,sizeof(ignpagers));
	while( fgets(instr,sizeof(instr)-1,fp) != NULL ) {
		stripleadtrailspaces(instr);
		/* empty line ? */
		if( instr[0] == '\0' ) {
			continue;
		}
		/* Comment ? */
		if( instr[0] == '#' ) {
			continue;
		}

		if( cont == 0 ) {
			memset(fullinstr,0,sizeof(fullinstr));
		}

		if( (strlen(fullinstr)+strlen(instr)) < sizeof(instr) ) {
			strcat(fullinstr,instr);
		}
		else {
			if( (sizeof(fullinstr)-strlen(fullinstr)-1) > 0 ) {
				strncat(fullinstr,instr,sizeof(fullinstr)-strlen(fullinstr)-1);
			}
		}
		/* Do we have a continuation tag ? */
		if( instr[strlen(instr)-1] == '\\' ) {
			/* Yup */
			/* Only remove if it's still part of the string */
			/* The instr may not have been completely copied into fullinstr */
			if( fullinstr[strlen(fullinstr)-1] == '\\' ) {
				fullinstr[strlen(fullinstr)-1] = '\0';
			}
			cont = 1;
			continue;
		}

		cont = 0;
		/* If you're wondering why I'm not using fullinstr */
		/* it's because it's new code (the '\') and only instr */
		/* was used in the code further below */
		memset(instr,0,sizeof(instr));
		strncpy(instr,fullinstr,sizeof(instr)-1);
#if DEBUG
		fprintf(stderr,"rule line: %s\n",instr);
		fflush(stderr);
#endif
		/*
		 * For unmatched records and HTML form paging just match on lines
		 * that start with "unmatched-" and "notify-admin" respectively
		 */
		if( strncmp(redhost,"unmatched-*",strlen("unmatched-*")) == 0 ) {
			if( strncmp(instr,"unmatched-*",strlen("unmatched-*")) != 0 ) {
				continue;
			}
		}
		else if( strncmp(redhost,"notify-admin",strlen("notify-admin")) == 0 ) {
			if( strncmp(instr,"notify-admin",strlen("notify-admin")) != 0 ) {
				continue;
			}
		}

		strcpy(workline,instr);
		strcat(workline,";");	/* make sure all columns are handled in the while loop */
		beginptr = workline;
		i = 0;
		while( ((endptr = strchr(beginptr,pginfo.cfgdelim[0])) != NULL) && (i < MAXRULEARGS) ) {
			*endptr = '\0';
			strcpy(ruleargs[i],beginptr);
			stripleadtrailspaces(ruleargs[i]);
			space_sep(ruleargs[i]);
			/*
			 * Check if column 1,3,5,6,7 are empty
			 */
			if( (strlen(ruleargs[i]) == 0) && (i != 1) && (i!= 3) ) {
				sprintf(usageline,"Empty column %d",i);
				usage(usageline);
				continue;
			}
			beginptr = ++endptr;
#if DEBUG
			fprintf(stderr,"Column %d: %s\n",i+1,ruleargs[i]);
			fflush(stderr);
#endif
			i++;
		}
		/* Invalid rule line ? missing args ? */
		if( i != MAXRULEARGS ) {
			memset(usageline,0,sizeof(usageline));
			strcpy(usageline,"Invalid rule line: ");
			strncat(usageline,instr,MAXLINE-strlen("Invalid rule line: ")-1);
			usage(usageline);
			continue;
		}
	
		/*
		 * Arg 1: hosts
		 * Arg 2: excluded hosts
		 * Arg 3: services
		 * Arg 4: excluded hosts
		 * Arg 5: Days of week
		 * Arg 6: Time of day
		 * Arg 7: recipients
		 */

		ignore = 0;

		/*
		 * !line indicates recipients to ignore if it matches
		 * remove ! from line and handle like normal rule line
		 */
		if( ruleargs[0][0] == '!' ) {
			ignore = 1;
			strcpy(ruleargs[0],&ruleargs[0][1]);
#if DEBUG
		fprintf(stderr,"It's an ignore line, don't notify: %s \n",ruleargs[6]);
		fflush(stderr);
#endif
			ptrpagers = ignpagers;
		}
		else {
			ptrpagers = pagers;
		}

		/*
		 * Get host list to include
		 */
		if( strlen(ruleargs[0]) == 0 ) {
			memset(usageline,0,sizeof(usageline));
			strcpy(usageline,"Invalid rule line(hosts undefined): ");
			strncat(usageline,instr,MAXLINE-strlen("Invalid rule line(hosts undefined): ")-1);
			usage(usageline);
			continue;
		}

		memset(workline,0,sizeof(workline));
		strcpy(workline,ruleargs[0]);
		workptr = workline;
		memset(hosts,'\0',sizeof(hosts));
#if DEBUG
		fprintf(stderr,"Substituting hg- tags in the rule line\n");
		fprintf(stderr,"Original column 1:       %s\n",ruleargs[0]);
		fflush(stderr);
#endif
		/*
		 * Expand host list with hg- entries from bbwarnsetup.cfg
		 */
		while( *workptr ) {
			while( isspace(*workptr) ) {
				workptr++;
			}
			if( !*workptr ) {
				break;
			}
			sscanf(workptr,"%s",hostentry);
#if DEBUG
			fprintf(stderr,"Checking host definition: %s\n",hostentry);
			fflush(stderr);
#endif
			workptr += strlen(hostentry);
			
			stripleadspaces(workptr);
			if( strncmp(hostentry,"hg-",strlen("hg-")) == 0 ) {
				memset(hghosts,0,sizeof(hghosts));
				getsetup(hghosts,hostentry,sizeof(hghosts));
				if( strlen(hghosts) == 0 ) {
					sprintf(usageline,"%s token is empty",hostentry);
					usage(usageline);
				}
				else {
					space_sep(hghosts);
					sprintf(hosts,"%s %s",hosts,hghosts);
				}
			}
			else {
				sprintf(hosts,"%s %s",hosts,hostentry);
			}
		} 
		/*
		 * I know for a fact that it starts with a space
		 */
		stripleadtrailspaces(hosts);
		if( strlen(hosts) == 0 ) {
			strcpy(usageline,"Column 1 is empty");
			usage(usageline);
			continue;
		}
		space_sep(hosts);
#if DEBUG
		fprintf(stderr,"Included hosts are: <%s>\n",hosts);
		fflush(stderr);
#endif
		/*replacestr(hosts,sizeof(hosts),"*",".*");*/
		replacestr(hosts,sizeof(hosts)," ","|");
#if DEBUG
		fprintf(stderr,"Column 1 converted to a regex: <%s>\n",hosts);
		fflush(stderr);
#endif

		/*
		 * Get host list to exclude
		 */
		strcpy(workline,ruleargs[1]);
		workptr = workline;
		memset(exhosts,'\0',sizeof(exhosts));
#if DEBUG
		fprintf(stderr,"Original column 2:       %s\n",ruleargs[1]);
		fflush(stderr);
#endif
		/* Expand host list with hg- entries from bbwarnsetup.cfg */
		while( *workptr ) {
			while( isspace(*workptr) ) {
				workptr++;
			}
			if( !*workptr ) {
				break;
			}
			sscanf(workptr,"%s",hostentry);
#if DEBUG
			fprintf(stderr,"Checking host definition: %s\n",hostentry);
			fflush(stderr);
#endif
			workptr += strlen(hostentry);
			stripleadspaces(workptr);
			if( strncmp(hostentry,"hg-",strlen("hg-")) == 0 ) {
				memset(hghosts,0,sizeof(hghosts));
				getsetup(hghosts,hostentry,sizeof(hghosts));
				if( strlen(hghosts) == 0 ) {
					sprintf(usageline,"%s token is empty",hostentry);
					usage(usageline);
				}
				else {
					space_sep(hghosts);
					sprintf(exhosts,"%s %s",exhosts,hghosts);
				}
			}
			else {
				sprintf(exhosts,"%s %s",exhosts,hostentry);
			}
		}
		/* I know for a fact that it starts with a space */
		stripleadspaces(exhosts);
		space_sep(exhosts);
#if DEBUG
		fprintf(stderr,"Excluded hosts are: <%s>\n",exhosts);
		fflush(stderr);
#endif
		/* Does this host match an exclude token ? */
		if( strlen(exhosts) ) {
			/*replacestr(exhosts,sizeof(exhosts),"*",".*");*/
			replacestr(exhosts,sizeof(exhosts)," ","|");
#if DEBUG
			fprintf(stderr,"Excluded hosts converted to a regex: <%s>\n",exhosts);
			fprintf(stderr,"Trying to match <%s> with exhosts regex: %s\n",redhost,exhosts);
			fflush(stderr);
#endif
			if( match(redhost,exhosts,REG_FULL|REG_PATHEXP) ) {
				/*
				 * Yup
				 */
#if DEBUG
				fprintf(stderr,"Ignore this rule as host <%s> matched this excluding regex: %s\n",redhost,exhosts);
				fflush(stderr);
#endif
				continue;
			}
#if DEBUG
			fprintf(stderr,"host <%s> did not with exhosts regex: %s\n",redhost,exhosts);
			fflush(stderr);
#endif
		}

#if DEBUG
		fprintf(stderr,"Trying to match host <%s> with hosts regex: %s\n",redhost,hosts);
		fflush(stderr);
#endif
		/* Does this host match an include token ? */
		if( !match(redhost,hosts,REG_FULL|REG_PATHEXP) ) {
			/*
			 * Nope
			 */
#if DEBUG
			fprintf(stderr,"Ignore this rule as host <%s> did not match this regex: %s\n",redhost,hosts);
			fflush(stderr);
#endif
			continue;
		}
#if DEBUG
		fprintf(stderr,"Host <%s> matched this regex: %s\n",redhost,hosts);
		fflush(stderr);
#endif
		/*
		 * Get services list to include
		 */
		if( strlen(ruleargs[2]) == 0 ) {
			memset(usageline,0,sizeof(usageline));
			strcpy(usageline,"Invalid rule line(services undefined): ");
			strncat(usageline,instr,MAXLINE-strlen("Invalid rule line(services undefined): ")-1);
			usage(usageline);
			continue;
		}
		strcpy(svcs,ruleargs[2]);
		space_sep(svcs);
		/*replacestr(svcs,sizeof(svcs),"*",".*");*/
		replacestr(svcs,sizeof(svcs)," ","|");
	
		/*
		 * Get services list to exclude
		 */
		strcpy(exsvcs,ruleargs[3]);
		space_sep(exsvcs);
		/*replacestr(exsvcs,sizeof(exsvcs),"*",".*");*/
		replacestr(exsvcs,sizeof(exsvcs)," ","|");
	
#if DEBUG
		fprintf(stderr,"Trying to match service <%s> with svcs regex: %s\n",redsvc,exsvcs);
		fflush(stderr);
#endif
		/* Does this service match an exclude token ? */
		if( strlen(exsvcs) && match(redsvc,exsvcs,REG_FULL) ) {
#if DEBUG
			fprintf(stderr,"Ignore this rule as service <%s> matched this excluding regex: %s\n",redsvc,exsvcs);
			fflush(stderr);
#endif
			continue;
		}

		/* Does this service match an include token ? */
		if( strlen(svcs) && !match(redsvc,svcs,REG_FULL) ) {
#if DEBUG
			fprintf(stderr,"Ignore this rule as service <%s> did not match this regex: %s\n",redsvc,svcs);
			fflush(stderr);
#endif
			continue;
		}

		/*
		 * Is today a match for the days column ?
		 */
		strcpy(workline,ruleargs[4]);
		if( strcmp(workline,"*") == 0 ) {
#if DEBUG
			fprintf(stderr,"Day definition in rule line matched all (*)\n");
			fflush(stderr);
#endif
			goto dotime;
		}
		strtolower(workline);
		workptr = workline;
		while( *workptr ) {
			while( isspace(*workptr) ) {
				workptr++;
			}
			if( !*workptr ) {
				break;
			}
			sscanf(workptr,"%s",dayval);
			workptr += strlen(dayval);
			stripleadspaces(workptr);
			dayrange = strchr(dayval,'-');
			if( dayrange ) {
#if DEBUG
				fprintf(stderr,"We have a day range: %s\n",dayval);
				fflush(stderr);
#endif
				*dayrange = '\0';
				dayrange++;
				if( *dayrange && !isspace(*dayrange) ) {
					strcpy(startdayval,dayval);
					strcpy(enddayval,dayrange);
#if DEBUG
					fprintf(stderr,"Start day range: %s\n",startdayval);
					fprintf(stderr,"End   day range: %s\n",enddayval);
					fflush(stderr);
#endif
				}
				else {
					memset(usageline,0,sizeof(usageline));
					strcpy(usageline,"Invalid rule line(invalid day range): ");
					strncat(usageline,instr,MAXLINE-strlen("Invalid rule line(invalid day range)): ")-1);
					usage(usageline);
					continue;
				}
			}
			else {
				strcpy(startdayval,dayval);
				strcpy(enddayval,dayval);
#if DEBUG
				fprintf(stderr,"Start/End day range: %s\n",startdayval);
				fflush(stderr);
#endif
			}
			startday = -1;
			startday = atoi(startdayval);
			endday = -1;
			endday = atoi(enddayval);
			if( startday < 0 || startday > 6 || endday < 0 || endday > 6 ) {
				memset(usageline,0,sizeof(usageline));
				strcpy(usageline,"Invalid rule line(invalid day range): ");
				strncat(usageline,instr,MAXLINE-strlen("Invalid rule line(invalid day range)): ")-1);
				usage(usageline);
				continue;
			}
			if( (nowday >= startday) && (nowday <= endday) ) {
#if DEBUG
				fprintf(stderr,"Current day <%d> is within Start/End day range: <%d-%d>\n",nowday,startday,endday);
				fflush(stderr);
#endif
				workptr=startdayval;
				break;
			}
		}
		if( strlen(workptr) == 0 ) {
#if DEBUG
			fprintf(stderr,"Current day <%d> is not within Start/End day range: <%d-%d>\n",nowday,startday,endday);
			fflush(stderr);
#endif
			continue;
		}
dotime:
		/*
		 * Is the current time a match for the time column ?
		 */
		strcpy(workline,ruleargs[5]);
		if( strcmp(workline,"*") == 0 ) {
#if DEBUG
			fprintf(stderr,"Time definition in rule line matched all (*)\n");
			fflush(stderr);
#endif
			goto dorcpts;
		}
		strtolower(workline);
		workptr = workline;
		while( *workptr ) {
			while( isspace(*workptr) ) {
				workptr++;
			}
			if( !*workptr ) {
				break;
			}
			sscanf(workptr,"%s",timesval);
			timesrange = strchr(timesval,'-');
			workptr += strlen(timesval);
			stripleadspaces(workptr);
			if( timesrange ) {
#if DEBUG
				fprintf(stderr,"We have a time range: %s\n",timesval);
				fflush(stderr);
#endif
				*timesrange = '\0';
				timesrange++;
				if( *timesrange && !isspace(*timesrange) ) {
					strcpy(starttimesval,timesval);
					strcpy(endtimesval,timesrange);
#if DEBUG
					fprintf(stderr,"Start time range: %s\n",starttimesval);
					fprintf(stderr,"End   time range: %s\n",endtimesval);
					fflush(stderr);
#endif
				}
				else {
					memset(usageline,0,sizeof(usageline));
					strcpy(usageline,"Invalid rule line(invalid time range): ");
					strncat(usageline,instr,MAXLINE-strlen("Invalid rule line(invalid time range)): ")-1);
					usage(usageline);
					continue;
				}
			}
			else {
				strcpy(starttimesval,timesval);
				strcpy(endtimesval,timesval);
#if DEBUG
				fprintf(stderr,"Start/End time range: %s\n",starttimesval);
				fflush(stderr);
#endif
			}
			starttimes = -1;
			starttimes = atoi(starttimesval);
			endtimes = -1;
			endtimes = atoi(endtimesval);
			if( starttimes < 0 || starttimes > 2400 || endtimes < 0 || endtimes > 2400 ) {
				memset(usageline,0,sizeof(usageline));
				strcpy(usageline,"Invalid rule line(invalid time range): ");
				strncat(usageline,instr,MAXLINE-strlen("Invalid rule line(invalid time range)): ")-1);
				usage(usageline);
				continue;
			}
			if( nowtime >= starttimes && nowtime <= endtimes ) {
#if DEBUG
				fprintf(stderr,"Current time <%04d> is within Start/End time range: <%04d-%04d>\n",nowtime,starttimes,endtimes);
				fflush(stderr);
#endif
				workptr=starttimesval;
				break;
			}
		}
		if( strlen(workptr) == 0 ) {
#if DEBUG
			fprintf(stderr,"Current time <%04d> is not within Start/End time range: <%04d-%04d>\n",nowtime,starttimes,endtimes);
			fflush(stderr);
#endif
			continue;
		}

dorcpts:
		/*
		 * Get recipients list to notify
		 */
#if DEBUG
		fprintf(stderr,"Recipients column: <%s>\n",ruleargs[6]);
		fflush(stderr);
#endif
		if( strlen(ruleargs[6]) == 0 ) {
			memset(usageline,0,sizeof(usageline));
			strcpy(usageline,"Invalid rule line(recipients undefined): ");
			strncat(usageline,instr,MAXLINE-strlen("Invalid rule line(recipients undefined): ")-1);
			usage(usageline);
			continue;
		}
		strcpy(workline,ruleargs[6]);
		workptr = workline;
		/* Expand host list with pg- entries from bbwarnsetup.cfg */
		while( *workptr ) {
			while( isspace(*workptr) ) {
				workptr++;
			}
			if( !*workptr ) {
				break;
			}
			sscanf(workptr,"%s",rcptentry);
			workptr += strlen(rcptentry);
			stripleadspaces(rcptentry);
			/* Make sure the recipient does not start with one */
			/* of the special qualifier characters */
			if( strspn(rcptentry,":^~-") > 0 ) {
				sprintf(usageline,"Invalid recipient: %s",rcptentry);
				usage(usageline);
				continue;
			}
#if DEBUG
			fprintf(stderr,"Validate recipient: <%s>\n",rcptentry);
			fflush(stderr);
#endif
			/*
			 * Take care of ignore recipients
			 */
			if( (ignore == 1) ) {
#if DEBUG
				fprintf(stderr,"This recipient <%s> has been defined to be ignored\n",rcptentry);
				fflush(stderr);
#endif
				if( *rcptentry == '*' ) {
#if DEBUG
					fprintf(stderr,"The <*> recipient matches all, don't notify\n");
					fflush(stderr);
#endif
					fclose(fp);
					return(done(0,&pginfo));
				}
				/*
				 * We don't care about qualifiers on ignored recipients
				 */
				overrideptr = strchr(rcptentry,':');
				if( overrideptr != NULL ) {
#if DEBUG
					fprintf(stderr,"This recipient <%s> has been redefined as ",rcptentry);
					fflush(stderr);
#endif
					*overrideptr = '\0';
#if DEBUG
					fprintf(stderr,"<%s>\n",rcptentry);
					fflush(stderr);
#endif
				}
			}
			/*
			 * Validate overriding qualifier if any
			 */
			memset(overrideval,'\0',sizeof(overrideval));
			overrideptr = strchr(rcptentry,':');
			if( overrideptr != NULL ) {
#if DEBUG
				fprintf(stderr,"This recipient <%s> has an overidding qualifier, is it valid ?\n",rcptentry);
				fflush(stderr);
#endif
				strcpy(rcptentry1,rcptentry);
				*overrideptr = '\0';
				overrideptr++;
				/* Don't accept rcpt: */
				if( !(*overrideptr && !isspace(*overrideptr)) ) {
					overrideptr = NULL;
					sprintf(usageline,"Invalid recipient: <%s>, overidding qualifier ignored",rcptentry1);
					usage(usageline);
					continue;
				}
				else {
					/*
					 * Qualifier can only start with [~^0-9]
					 */
#if REGEXEC
					if( match(overrideptr,"[~^]?[0-9]+",REG_FULL) ||
						match(overrideptr,"[~^]?[0-9]+-[0-9]+",REG_FULL) ) {
#else
#if REGEX
					if( match(overrideptr,"[~^]{0,1}[0-9]{1,}",REG_FULL) ||
						match(overrideptr,"[~^]{0,1}[0-9]{1,}-[0-9]{1,}",REG_FULL) ) {
#else
#if RE_EXEC
					if( match(overrideptr,"[0-9][0-9]*",REG_FULL) ||
						match(overrideptr,"[~^][0-9][0-9]*",REG_FULL) ||
						match(overrideptr,"[~^][0-9][0-9]*-[0-9][0-9]*",REG_FULL) ) {
#else
					if( 0 ) {
#endif
#endif
#endif
						strcpy(overrideval,overrideptr);
#if DEBUG
						fprintf(stderr,"This recipient <%s> has a valid overidding qualifier\n",rcptentry1);
						fflush(stderr);
#endif
					}
					else {
						sprintf(usageline,"Invalid recipient: <%s>, invalid overidding qualifier ",rcptentry1);
						usage(usageline);
						overrideptr = NULL;
						continue;
					}
				}
			}

			/*	
			 * Deal with pager group
			 */
			if( strncmp(rcptentry,"pg-",strlen("pg-")) == 0 ) {
				/*
				 * Do we have an overriding parameter ?
				 * if we do then every recipient in the list must be set with it
				 */
#if DEBUG
				fprintf(stderr,"This recipient <%s> is a page group\n",rcptentry);
				fflush(stderr);
#endif
				getsetup(pgrcpts,rcptentry,sizeof(pgrcpts));
#if DEBUG
				fprintf(stderr,"The page group <%s> is defined by <%s>\n",rcptentry,pgrcpts);
				fflush(stderr);
#endif
				space_sep(pgrcpts);
				if( overrideptr != NULL ) {
					pgptr = pgrcpts;
					pgpager[0] = '\0';
					memset(pgpager,'\0',sizeof(pgpager));
					while( *pgptr ) {
						while( isspace(*pgptr) ) {
							pgptr++;
						}
						if( !*pgptr ) {
							break;
						}
						sscanf(pgptr,"%s",pgpager);
						pgptr += strlen(pgpager);
						overrideptr = strchr(pgpager,':');
						if( overrideptr != NULL ) {
							*overrideptr = '\0';
						}
						/* Thanks to valankar@ifxcorp.com */
						/* for finding a bug where ignored recipient list */
						/* wasn't built properly (the 2nd ptrpagers arg was previously defined as pagers) */
						sprintf(ptrpagers,"%s %s:%s",ptrpagers,pgpager,overrideval);
					}
				}
				else {
					sprintf(ptrpagers,"%s %s",ptrpagers,pgrcpts);
				}
			}
			else {
				if( overrideptr != NULL ) {
					sprintf(ptrpagers,"%s %s:%s",ptrpagers,rcptentry,overrideval);
				}
				else {
					sprintf(ptrpagers,"%s %s",ptrpagers,rcptentry);
				}
			}
#if DEBUG
			fprintf(stderr,"The list of recipients to notify is now: <%s>\n",pagers);
			fprintf(stderr,"The list of recipients to ignore is now: <%s>\n",ignpagers);
			fflush(stderr);
#endif
		}

		/* I know for a fact that it starts with a space */
		stripleadspaces(ptrpagers);
		space_sep(ptrpagers);
#if DEBUG
		fprintf(stderr,"The final list of recipients is: <%s>\n",pagers);
		fflush(stderr);
#endif

	} /* Reading bbwarnrules.cfg */

	fclose(fp);

	/*
	 * If we don't have any recipients, we're done
	 */
	if( strlen(pagers) == 0 ) {
#if DEBUG
		fprintf(stderr,"Oh well, no recipients were determined, we're done\n");
		fflush(stderr);
#endif
		return(done(0,&pginfo));
	}

#if DEBUG
	fprintf(stderr,"Preliminary recipients list <%s>\n",pagers);
	fflush(stderr);
#endif

	/*
	 * Remove any recipients that were on a !rule
	 */
	if( strlen(ignpagers) > 0 ) {
#if DEBUG
		fprintf(stderr,"Remove these recipients <%s> from the recipients list <%s>\n",ignpagers,pagers);
		fflush(stderr);
#endif
		memset(workline,'\0',sizeof(workline));
		strncpy(workline,ignpagers,sizeof(workline)-1);
		workptr = workline;
		while( *workptr ) {
			while( isspace(*workptr) ) {
				workptr++;
			}
			if( !*workptr ) {
				break;
			}
			sscanf(workptr,"%s",rcptentry);
			workptr += strlen(rcptentry);
#if DEBUG
			fprintf(stderr,"Remove this recipient <%s> from the recipients list <%s>\n",rcptentry,pagers);
			fflush(stderr);
#endif
			stripleadspaces(workptr);
			ignpager = strstr(pagers,rcptentry);
			while( ignpager != NULL ) {
				sscanf(ignpager,"%s",rcptentry1);
				pgptr = ignpager + strlen(rcptentry);
				if( isspace(*pgptr) || (*pgptr == ':') || (*pgptr == '\0') ) {
					pgptr = ignpager + strlen(rcptentry1);
					if( *pgptr != '\0' ) {
						strcpy(ignpager,  pgptr);
					}
					else {
						*ignpager = '\0';
					}
					ignpager = strstr(pagers,rcptentry);
				}
				else {
					ignpager = strstr(ignpager+1,rcptentry);
				}
			}
#if DEBUG
			fprintf(stderr,"New recipients list <%s>\n",pagers);
			fflush(stderr);
#endif
		}
	}
	space_sep(pagers);
	stripleadtrailspaces(pagers);

	if( strlen(pagers) == 0 ) {
#if DEBUG
		fprintf(stderr,"We have no recipients, we're done\n");
		fflush(stderr);
#endif
		return(done(0,&pginfo));
	}

	/*
	 * Keep only one recipient definition
	 * The definition with the lowest delay is kept
	 */
	strcat(pagers," ");	/* we'll search on recipient[ :] */
	memset(workline,0,sizeof(workline));
	memset(ignpagers,0,sizeof(ignpagers));
	strncpy(workline,pagers,sizeof(workline)-1);
	workptr = workline;
#if DEBUG
	fprintf(stderr,"Keep only one recipient definition per recipient\n");
	fprintf(stderr,"Our recipients list is <%s>\n",pagers);
	fflush(stderr);
#endif
	/*
	 * For each recipient choose the one with the smallest delay
	 */
	while( *workptr ) {
		while( isspace(*workptr) ) {
			workptr++;
		}
		if( !*workptr ) {
			break;
		}
		sscanf(workptr,"%s",rcptentry1);
		workptr += strlen(rcptentry1);
		stripleadspaces(workptr);
#if DEBUG
		fprintf(stderr,"Working on recipient <%s>\n",rcptentry1);
		fflush(stderr);
#endif
		strcpy(rcptentry,rcptentry1);
		getdelay(rcptentry1,&initdelay1,&delay1,&type1,pginfo.pagedelay);
		if( (overrideptr1 = strchr(rcptentry1,':')) != NULL ) {
			*overrideptr1 = '\0';
#if DEBUG
			fprintf(stderr,"Recipient <%s> has an overriding delay <%s>\n",rcptentry1,overrideptr1+1);
			fflush(stderr);
#endif
		}
		/*
		 * Is the recipient been defined more than once
		 */
		pgptr = workptr;
		while( sscanf(pgptr,"%s",rcptentry2) > 0 ) {
			/* Is it the same recipient ? */
			if( strncmp(rcptentry2,rcptentry1,strlen(rcptentry1)) == 0 ) {
				/* Is it really the same recipient ? */
				if( (rcptentry2[strlen(rcptentry1)] != ':')
					&& (rcptentry2[strlen(rcptentry1)] != '\0') ) {
					/* nope, keep going */
					pgptr = strstr(pgptr,rcptentry2) + strlen(rcptentry2);
					continue;
				}
			}
			else {
				/* nope, keep going */
				pgptr = strstr(pgptr,rcptentry2) + strlen(rcptentry2);
				continue;
			}
			/* Remove this new recipient from the workline */
			strcpy(pgptr,strstr(pgptr,rcptentry2)+strlen(rcptentry2));
			getdelay(rcptentry2,&initdelay2,&delay2,&type2,pginfo.pagedelay);
			/*
			 * We are dealing with the same recipient
			 *
			 * rcpt:15 has priority of rcpt:~15 or rcpt:^15
			 * rcpt:^15 has priority over rcpt:~15
			 */
#if DEBUG
			fprintf(stderr,"Comparing recipient <%s> to recipient <%s>\n",rcptentry,rcptentry2);
			fflush(stderr);
#endif
			if( type2 < type1 ) {
				initdelay1 = initdelay2;
				delay1 = delay2;
				type1 = type2;
				strcpy(rcptentry,rcptentry2);
			}
			else if ( (type2 == type1) && (initdelay2 < initdelay1) ) {
				initdelay1 = initdelay2;
				delay1 = delay2;
				strcpy(rcptentry,rcptentry2);
			}
			else if ( (type2 == type1) && (initdelay2 == initdelay1) && (delay2 < delay1) ) {
				delay1 = delay2;
				strcpy(rcptentry,rcptentry2);
			}
#if DEBUG
			fprintf(stderr,"Current recipient definition <%s>\n",rcptentry);
			fflush(stderr);
#endif
		}
		sprintf(ignpagers,"%s %s",ignpagers,rcptentry);
#if DEBUG
		fprintf(stderr,"Adding recipient <%s> to recipient list\n",rcptentry);
		fflush(stderr);
#endif
	}
	strcpy(pagers,ignpagers);
	stripleadtrailspaces(pagers);
	space_sep(pagers);

#if DEBUG
	fprintf(stderr,"Final recipients list <%s>\n",pagers);
	fflush(stderr);
#endif

	sprintf(pginfo.pagemsgfile,"%s/pagemsg.%d",bbtmpdir,getpid());

	sprintf(bbnumeric,"%s%s",svcerr,machip);
#if DEBUG
	fprintf(stderr,"bbnumeric set to <%s>\n",bbnumeric);
	fflush(stderr);
#endif

	getsetup(prefix, "prefix", sizeof(prefix));
#if DEBUG
	fprintf(stderr,"The prefix is set to <%s>\n",prefix);
	fflush(stderr);
#endif

	getsetup(suffix, "suffix", sizeof(suffix));
#if DEBUG
	fprintf(stderr,"The suffix is set to <%s>\n",suffix);
	fflush(stderr);
#endif

	getsetup(pagelevels, "pagelevels", sizeof(pagelevels));
	replacestr(pagelevels,sizeof(pagelevels),"\t"," ");
#if DEBUG
	fprintf(stderr,"The pagelevels is set to <%s>\n",pagelevels);
	fflush(stderr);
#endif
	strcat(pagelevels," ");	/* Add " " so we can search using <color > */

	getsetup(pagelevelsmail, "pagelevelsmail", sizeof(pagelevelsmail));
	replacestr(pagelevelsmail,sizeof(pagelevelsmail),"\t"," ");
#if DEBUG
	fprintf(stderr,"The pagelevelsmail is set to <%s>\n",pagelevelsmail);
	fflush(stderr);
#endif
	strcat(pagelevelsmail," ");	/* Add " " so we can search using <color > */

	getsetup(pagetype, "pagetype", sizeof(pagetype));
#if DEBUG
	fprintf(stderr,"The pagetype is set to <%s>\n",pagetype);
	fflush(stderr);
#endif
	
	getsetup(pageaddhtmlpath, "pageaddhtmlpath", sizeof(pageaddhtmlpath));
#if DEBUG
	fprintf(stderr,"The pageaddhtmlpath is set to <%s>\n",pageaddhtmlpath);
	fflush(stderr);
#endif

	getsetup(briefrcpts, "briefrcpt", sizeof(briefrcpts));
#if DEBUG
	fprintf(stderr,"The briefrcpt token is set to <%s>\n",briefrcpts);
	fflush(stderr);
#endif

	expand_briefrcpts(briefrcpts,sizeof(briefrcpts));
#if DEBUG
	fprintf(stderr,"The briefrcpt token after expansion <%s>\n",briefrcpts);
	fflush(stderr);
#endif
	/*
	 * Determine the hosts's group name
	 */
	if( strcmp(pagetype,"GROUP") == 0 ) {
#if DEBUG
		fprintf(stderr,"pagetype=GROUP, determine the hosts's group name\n");
		fflush(stderr);
#endif
		memset(bbgroup,0,sizeof(bbgroup));
	}

	/*
	 * Remove recipients that have an np_* file associated with them
	 * but haven't been notified because they are in the state of
	 * an initial delay or the waiting period before been escalated to
	 */
	if( recovered == 1 ) {
#if DEBUG
		fprintf(stderr,"Recovery message: remove recipients which haven't been notified (in delay)\n");
		fprintf(stderr,"Recipients list: <%s>\n",pagers);
		fflush(stderr);
#endif
		memset(ignpagers,0,sizeof(ignpagers));
		memset(workline,0,sizeof(workline));
		strcpy(workline,pagers);
		workptr = workline;
		while( *workptr ) {
			/* Get recipient */
			while( isspace(*workptr) ) {
				workptr++;
			}
			if( !*workptr ) {
				break;
			}
			sscanf(workptr,"%s",rcptentry);
			workptr += strlen(rcptentry);
			while( isspace(*workptr) ) {
				workptr++;
			}
			/* Remove overriding delay definition if any */
			workptr1 = strchr(rcptentry,':');
			if( workptr1 ) {
				*workptr1 = '\0';
			}

			if( strstr(ignpagers,rcptentry) != NULL ) {
#if DEBUG
				fprintf(stderr,"Recipient <%s> already in list\n",rcptentry);
				fflush(stderr);
#endif
				continue;
			}
#if DEBUG
			fprintf(stderr,"Checking recipient <%s>\n",rcptentry);
			fflush(stderr);
#endif
			/* Get each np_file file that match tmp/np_<recipient>* */
			/* Changed how np_ file is search. Map on all np_ */
			/*  files and match the name.  the match() function doesn't */
			/*  like the + character without a reg exp preceeding it. */
			/*  Thanks to Christian Perrier which fell into this bug */
			strcpy(filemask,"np_*");
			dirinfo = NULL;
			rc = getdirfirst(&dirinfo,bbtmpdir,filemask,npfilename,GETDIR_FILE,&ftype);
			while( rc == 1 ) {
#if DEBUG
				fprintf(stderr,"Is recipient <%s> associated with <%s> ?\n",rcptentry,npfilename);
				fflush(stderr);
#endif
				if( strncmp(npfilename+3,rcptentry,strlen(rcptentry)) == 0 ) {
					/* Get file content */
					sprintf(workfilename,"%s/%s",bbtmpdir,npfilename);
#if DEBUG		
					fprintf(stderr,"<%s> is associated with <%s>\n",rcptentry,workfilename);
					fflush(stderr);
#endif
					if( stat(workfilename,&statinfo) == 0 ) {
						if( (npfilecontents=calloc(1,statinfo.st_size+1)) != NULL) {
							if( (fp=fopen(workfilename,"r")) != NULL ) {
								if( fread(npfilecontents,statinfo.st_size,1,fp) > 0 ) {
									/* Is this file related to the recipient ? */
									if( strstr(npfilecontents,rcptentry) != NULL ) {
										/* Is this file related to this event ? */
										if( strstr(npfilecontents,bbhostsvc) != NULL ) {
											/* Has the recipient already notified ? */
											if( strstr(npfilecontents,"000000") == NULL ) {
#if DEBUG		
												fprintf(stderr,"Yes, add recipient <%s>\n",rcptentry);
												fflush(stderr);
#endif
												sprintf(ignpagers,"%s %s",ignpagers,rcptentry);
												fclose(fp);
												free(npfilecontents);
												break;
											}
										}
									}
								}
								else {
									sprintf(usageline,"The contents of <%s> could not be read",workfilename);
									usage(usageline);
								}
								fclose(fp);
							}
							else {
								sprintf(usageline,"The file <%s> could not be opened",workfilename);
								usage(usageline);
							}
							free(npfilecontents);
						}
						else {
							usage("Could not allocate memory");
						}
					}
					else {
						sprintf(usageline,"<%s> has suddenly disappeared ...",workfilename);
						usage(usageline);
					}
				}
				rc = getdirnext(dirinfo,bbtmpdir,filemask,npfilename,GETDIR_FILE,&ftype);
			}
			getdirdone(dirinfo);
		}
		stripleadtrailspaces(ignpagers);
		if( strlen(ignpagers) == 0 ) {
#if DEBUG
			fprintf(stderr,"All recipients had not been notified yet, we're done: <%s>\n",pagers);
			fflush(stderr);
#endif
			return(done(0,&pginfo));
		}
		strcpy(pagers,ignpagers);
#if DEBUG
		fprintf(stderr,"Only <%s> are to be notified about this recovery message\n",pagers);
		fflush(stderr);
#endif
	}

	bblogstatus = getenv("BBLOGSTATUS");
	if( !bblogstatus ) {
		bblogstatus = "";
	}

	bbwebhtmllogs = getenv("BBWEBHTMLLOGS");
	if( !bbwebhtmllogs ) {
		bbwebhtmllogs = "";
	}

	cgibinurl = getenv("CGIBINURL");
	if( !cgibinurl ) {
		cgibinurl = "";
	}

	bbwebhost = getenv("BBWEBHOST");
	if( !bbwebhost ) {
		bbwebhost = "";
	}

	bbwebhosturl = getenv("BBWEBHOSTURL");
	if( !bbwebhosturl ) {
		bbwebhosturl = "";
	}

#if DEBUG
	fprintf(stderr,"BBLOGSTATUS: <%s>\n",bblogstatus);
	fprintf(stderr,"BBWEBHTMLLOGS: <%s>\n",bbwebhtmllogs);
	fprintf(stderr,"CGIBINURL: <%s>\n",cgibinurl);
	fprintf(stderr,"BBWEBHOST: <%s>\n",bbwebhost);
	fprintf(stderr,"BBWEBHOSTURL: <%s>\n",bbwebhosturl);
	fflush(stderr);
#endif

	rcptnum = 10;	/* no need for leading zeros */
	memset(workline,0,sizeof(workline));
	strcpy(workline,pagers);
	workptr = workline;
	while( strlen(workptr) > 0 ) {
		while( isspace(*workptr) ) {
			workptr++;
		}
		if( !*workptr ) {
			break;
		}
		sscanf(workptr,"%s",rcptentry);
		randval = -1;
#if DEBUG
		fprintf(stderr,"Notifying <%s>\n",rcptentry);
		fflush(stderr);
#endif
		workptr += strlen(rcptentry);
		stripleadtrailspaces(workptr);
		getdelay(rcptentry,&initdelay1,&delay1,&type1,pginfo.pagedelay);
#if DEBUG
		fprintf(stderr,"Recipient <%s> initdelay <%d> delay <%d> type <%d>\n",rcptentry,initdelay1,delay1,type1);
		fflush(stderr);
#endif
		if( (pgptr=strchr(rcptentry,':')) != NULL ) {
			*pgptr = '\0';
		}

		if( (strncmp(bbnumeric,"911",3) != 0) && recovered != 1 ) {
			if( strstr(pagelevelsmail,color) != NULL ) {
#if DEBUG
				fprintf(stderr,"Only send to an e-mail recipient: <%s> in <%s>\n",color, pagelevelsmail);
				fflush(stderr);
#endif
				if( (match(rcptentry,".*@.*",REG_FULL) == 1) && (match(rcptentry,"ep-.*",REG_FULL) == 0)
					&& (match(rcptentry,"ext-.*",REG_FULL) == 0) ) {
#if DEBUG
					fprintf(stderr,"<%s> is an e-mail recipient\n",rcptentry);
					fflush(stderr);
#endif
				}
				else {
#if DEBUG
					fprintf(stderr,"<%s> is *not* an e-mail recipient\n",rcptentry);
					fflush(stderr);
#endif
					continue;
				}
			}
			time(&timenow);
			memset(workfilename,0,sizeof(workfilename));
			sprintf(workfilename,"%s/np_%s",bbtmpdir,rcptentry);
			if( strcmp(pagetype,"EVENT") == 0 ) {
				strcat(workfilename,"_");
				strcat(workfilename,bbhostsvc);
			}
			else if( strcmp(pagetype,"GROUP") == 0 ) {
				strcat(workfilename,"_");
				strcat(workfilename,bbgroup);
			}
			else if( strcmp(pagetype,"HOST") == 0 ) {
				strcat(workfilename,"_");
				strcat(workfilename,machip);
			}
#if DEBUG
			fprintf(stderr,"Notification tag file: <%s>\n",workfilename);
			fflush(stderr);
#endif
			/*
			 * Check if a tag file already exists
			 */
			if( stat(workfilename,&statinfo) == 0 ) {
#if DEBUG
				fprintf(stderr,"Last modification time: <%d>, time now: <%d>\n",statinfo.st_mtime,timenow);
				fflush(stderr);
#endif
				if( statinfo.st_mtime > timenow ) {
#if DEBUG
					fprintf(stderr,"Delay hasn't expired, disregard <%s>\n",rcptentry);
					fflush(stderr);
#endif
					continue;
				}
				np_exists = 1;
			}
			else {
				np_exists = 0;
			}
			randval = getpid() % 100000;
			if( randval < 10 ) {
				randval *= 1000000;
			}
			else if( randval < 100 ) {
				randval *= 100000;
			}
			else if( randval < 1000 ) {
				randval *= 10000;
			}
			else if( randval < 10000 ) {
				randval *= 1000;
			}
			else {
				randval *= 100;
			}
			randval += rcptnum;
#if DEBUG
			fprintf(stderr,"randval <%d>\n",randval);
			fprintf(stderr,"Recipient ID <%d>\n",rcptnum);
			fflush(stderr);
#endif
			rcptnum++;

			if( type1 & (PAGE_ESCALATE|PAGE_INITDELAY) ) {
				/*
				 * If the np_ file does not exist
				 * or if an np_ file is older than 10 minutes 
				 * (or the PURPLEDELAY value if it's a purple)
				 * then it is considered inactive and is resetted
				 * (unless pagetype is EVENT, all np_ files are active)
				 */
				if( (np_exists == 0)
					|| ((np_exists == 1) &&
						(statinfo.st_mtime < (timenow - (strcmp(color,"purple") ? 600 : purpleoffset)))
							&& (strcmp(pagetype,"EVENT") != 0)) ) {
					if( type1 & PAGE_INITDELAY) {
						sprintf(workline1,"%7d0000000 %s %s %s\n",randval,bbhostsvc,color,rcptentry);
					}
					else {
						sprintf(workline1,"0000000 %s %s %s\n",bbhostsvc,color,rcptentry);
					}
					savefile(workfilename,workline1);
					touchtime(workfilename,initdelay1);
#if DEBUG
					fprintf(stderr,"Toggle file <%s> created with a initial delay of <%d> minutes\n",workfilename,initdelay1);
					fprintf(stderr,"Do not notify immediately\n",workfilename,initdelay1);
					fflush(stderr);
#endif
					continue;
				}
			}
			/* When using pagetype EVENT, reuse ACK ids as it is certain */
			/* that it is unique to that recipient/event */

			if( strcmp(pagetype,"EVENT") == 0 ) {
#if DEBUG
				fprintf(stderr,"Reuse ACK id ? np_file is <%s>\n",workfilename);
				fflush(stderr);
#endif
				if( (npfilecontents = readfile(workfilename)) != NULL ) {
#if DEBUG
					fprintf(stderr,"Contents of <%s>: <%s>\n",workfilename,npfilecontents);
					fflush(stderr);
#endif
					replacestr(npfilecontents,strlen(npfilecontents),"0000000","");
					if( match(npfilecontents,"[0-9][0-9][0-9][0-9][0-9][0-9][0-9][ 	]",REG_BOL) == 1 ) {
						memset(tmprandvalstr,0,sizeof(tmprandvalstr));
						strncpy(tmprandvalstr,npfilecontents,7);
#if DEBUG
						fprintf(stderr,"<%s> has a proper ACK ID: <%s>\n",workfilename,tmprandvalstr);
						fflush(stderr);
#endif
						tmprandvalstr[7] = '\0';
						tmprandval = atoi(tmprandvalstr);
#if DEBUG
						fprintf(stderr,"Current ACK id of <%s> is <%s>\n",workfilename,tmprandvalstr);
						fflush(stderr);
#endif
						if( tmprandval > 0 ) {
#if DEBUG
							fprintf(stderr,"ACK id of <%s> will be used\n",workfilename,tmprandvalstr);
							fflush(stderr);
#endif
							randval = tmprandval;
						}
					}
					free(npfilecontents);
				}
			}

			sprintf(workline1,"%7d %s %s %s\n",randval,bbhostsvc,color,rcptentry);
			savefile(workfilename,workline1);
			touchtime(workfilename,delay1);
#if DEBUG
			fprintf(stderr,"Toggle file <%s> created with a delay of <%d> minutes\n",workfilename,delay1);
			fprintf(stderr,"Go on and notify immediately\n",workfilename,initdelay1);
			fflush(stderr);
#endif
		} /* Not a 911 notification || a recovery message */

		if( recovered == 1 ) {
			randval = 0;
		}

		memset(randvalstr,0,sizeof(randvalstr));
		memset(randvaltag,0,sizeof(randvaltag));
		memset(randvalsubjtag,0,sizeof(randvalsubjtag));
		if( randval >= 0 ) {
			sprintf(randvalstr,"%07d ",randval);
			sprintf(randvaltag,"[%07d] ",randval);
			sprintf(randvalsubjtag," - %07d",randval);
		}
#if DEBUG
		fprintf(stderr,"randvaltag: <%s>  randvalsubjtag: <%s>\n",randvaltag,randvalsubjtag);
		fflush(stderr);
#endif
		memset(htmllink,0,sizeof(htmllink));
		if( strcmp(pageaddhtmlpath,"TRUE") == 0 ) {
#if DEBUG
			fprintf(stderr,"pageaddhtmlpath is set to TRUE\n");
			fflush(stderr);
#endif
			if( (strncmp(hostsvc,"notify-admin",strlen("notify-admin")) == 0)
				|| (strncmp(hostsvc,"unmatched-",strlen("unmatched-")) == 0) ) {
				/* do nothing */
			}
			else {
				if( strcmp(bblogstatus,"DYNAMIC") == 0 ) {
					/* Does CGIBINURL already have the BBWEBHOST path defined ? */
					if( strncmp(bbwebhost,cgibinurl,strlen(bbwebhost)) != 0 ) {
						/* Nope */
						sprintf(htmllink,"\n\nPlease see: %s%s/bb-hostsvc.sh?HOSTSVC=%s",bbwebhost,cgibinurl,hostsvc);
					}
					else {
						/* Yup */
						sprintf(htmllink,"\n\nPlease see: %s/bb-hostsvc.sh?HOSTSVC=%s",cgibinurl,hostsvc);
					}
				}
				else if( strcmp(bblogstatus,"TEXT") == 0 ) {
					sprintf(htmllink,"\n\nPlease see: %s/logs/%s",bbwebhosturl,hostsvc);
				}
				else {
					/* Default is STATIC */
					sprintf(htmllink,"\n\nPlease see: %s/%s.html",bbwebhtmllogs,bbhostsvc);
				}
			}
		}
#if DEBUG
		fprintf(stderr,"htmllink: <%s>\n",htmllink);
		fflush(stderr);
#endif

#if DEBUG
		fprintf(stderr,"BBWEBHOSTURL: <%s>\n",bbwebhosturl);
		fflush(stderr);
#endif
		memset(downsecsmsg,0,sizeof(downsecsmsg));
		memset(downsecsval,0,sizeof(downsecsval));
		if( recovered == 1 ) {
			memset(workline1,0,sizeof(workline1));
			workptr1 = strstr(msg," seconds");
			if( workptr1 ) {
				while( isspace(*workptr1) && workptr1 > msg ) {
					workptr1--;
				}
				while( isdigit(*workptr1) && workptr1 > msg ) {
					workptr1--;
				}
				sscanf(workptr1,"%s",workline1);
			}
			sprintf(downsecsmsg,"-- Event Duration: %s seconds",workline1);
			strcpy(downsecsval,workline1);
#if DEBUG
			fprintf(stderr,"downsecsmsg: <%s>\n",downsecsmsg);
			fflush(stderr);
#endif
		}

		memset(bbalpha,0,sizeof(bbalpha));
		if( strstr(briefrcpts,rcptentry) ) {
			sprintf(bbalpha,"%s - %s - %s\n%s\n",bbhostsvc,bbnumeric,randvaltag,htmllink);
#if DEBUG
			fprintf(stderr,"Brief message: <%s>\n",bbalpha);
			fflush(stderr);
#endif
		}
		else {
#if DEBUG
			fprintf(stderr,"randvaltag: <%s>\n",randvaltag);
			fprintf(stderr,"msg: <%s>\n",msg);
			fprintf(stderr,"htmllink: <%s>\n",htmllink);
			fflush(stderr);
#endif
			strcpy(bbalpha,randvaltag);
			strncat(bbalpha," ",sizeof(bbalpha)-strlen(bbalpha)-2);
			strncat(bbalpha,bbhostsvc,sizeof(bbalpha)-strlen(bbalpha)-2);
			strncat(bbalpha," ",sizeof(bbalpha)-strlen(bbalpha)-2);
			strncat(bbalpha,msg,sizeof(bbalpha)-strlen(bbalpha)-2);
			strncat(bbalpha,htmllink,sizeof(bbalpha)-strlen(bbalpha)-2);
			strcat(bbalpha,"\n");
#if DEBUG
			fprintf(stderr,"Regular message: <%s>\n",bbalpha);
			fflush(stderr);
#endif
		}


#ifndef ZOMBIE          
		signal(SIGCHLD, SIG_IGN);
#endif /* NO ZOMBIE */  

		memset(numcode,0,sizeof(numcode));
		sprintf(numcode,"%s%s",bbnumeric,randvalstr);
		save_notification = 0;

		if( match(rcptentry,"ext-.*",REG_FULL) == 1 ) {
#if DEBUG
			fprintf(stderr,"<%s> is an user defined recipient, trying custom notification in ext/pg/\n",rcptentry);
			fflush(stderr);
#endif
			bb_putenv("BBALPHAMSG",bbalpha,bbalphamsg_env,sizeof(bbalphamsg_env));
			bb_putenv("ACKCODE",randvalstr,ackcode_env,sizeof(ackcode_env));
			bb_putenv("BBHOSTSVC",bbhostsvc,bbhostsvc_env,sizeof(bbhostsvc_env));
			bb_putenv("BBHOSTNAME",redhost,bbhostname_env,sizeof(bbhostname_env));
			bb_putenv("MACHIP",machip,machip_env,sizeof(machip_env));
			bb_putenv("BBSVCNUM",svcerr,bbsvcnum_env,sizeof(bbsvcnum_env));
			bb_putenv("BBSVCNAME",redsvc,bbsvcname_env,sizeof(bbsvcname_env));
			bb_putenv("BBNUMERIC",numcode,bbnumeric_env,sizeof(bbnumeric_env));
			bb_putenv("BBCOLORLEVEL",color,bbcolorlevel_env,sizeof(bbcolorlevel_env));
			bb_putenv("BBHOSTSVCDOTS",bbhostsvc,bbhostsvcdots_env,sizeof(bbhostsvcdots_env));
			bb_putenv("BBHOSTSVCCOMMAS",hostsvc,bbhostsvccommas_env,sizeof(bbhostsvccommas_env));
			bb_putenv("DOWNSECSMSG",downsecsmsg,downsecsmsg_env,sizeof(downsecsmsg_env));
			bb_putenv("DOWNSECS",downsecsval,downsecs_env,sizeof(downsecs_env));
			bb_putenv("RECOVERED",(recovered == 1 ? "1" : "0"),recovered_env,sizeof(recovered_env));

			save_notification = send_extpage(rcptentry);
		}
		else if( match(rcptentry,"ep-.*",REG_FULL) == 1 ) {
#if DEBUG
			fprintf(stderr,"<%s> is an e-page recipient\n",rcptentry);
			fflush(stderr);
#endif
			sprintf(bbalpha,"!BB%s! %s - %s",randvalsubjtag,bbhostsvc,bbnumeric);
			strcpy(mailsubject,"BB");
			save_notification = send_mail(bbalpha,mailsubject,rcptentry);
		}
		else if( match(rcptentry,".*@.*",REG_FULL) == 1 ) {
#if DEBUG
			fprintf(stderr,"<%s> is an e-mail recipient\n",rcptentry);
			fflush(stderr);
#endif
			sprintf(mailsubject,"!BB%s! %s - %s",randvalsubjtag,bbhostsvc,bbnumeric);
			save_notification = send_mail(bbalpha,mailsubject,rcptentry);
		}
		else if( match(rcptentry,"[0-9]",REG_BOL) == 1 ) {
#if DEBUG
			fprintf(stderr,"<%s> is a numeric recipient\n",rcptentry);
			fflush(stderr);
#endif
			save_notification = send_numeric(numcode,prefix,suffix,rcptentry);
		}
		else if( match(rcptentry,"sms-.*",REG_FULL) == 1 ) {
#if DEBUG
			fprintf(stderr,"<%s> is an sms recipient\n",rcptentry);
			fflush(stderr);
#endif
			save_notification = send_sms(bbalpha,rcptentry);
		}
		else if( match(rcptentry,"alpha-.*",REG_FULL) == 1 ) {
#if DEBUG
			fprintf(stderr,"<%s> is an alpha msg recipient\n",rcptentry);
			fflush(stderr);
#endif
			save_notification = send_alpha(bbalpha,rcptentry);
		}
		else if( match(rcptentry,"qp-.*",REG_FULL) == 1 ) {
#if DEBUG
			fprintf(stderr,"<%s> is an qpage recipient\n",rcptentry);
			fflush(stderr);
#endif
			save_notification = send_qpage(bbalpha,rcptentry);
		}
		else if( (match(rcptentry,"sp-.*",REG_FULL) == 1)
				|| (match(rcptentry,"hsp-.*",REG_FULL) == 1) ) {
#if DEBUG
			fprintf(stderr,"<%s> is an sendpage recipient\n",rcptentry);
			fflush(stderr);
#endif
			save_notification = send_sendpage(bbalpha,rcptentry);
		}
		else if( match(rcptentry,"trap-.*",REG_FULL) == 1 ) {
#if DEBUG
			fprintf(stderr,"<%s> is an SNMP trap recipient\n",rcptentry);
			fflush(stderr);
#endif
			save_notification = send_snmptrap(bbalpha,rcptentry,redhostip,redsvc,recovered);
		}
		else if( match(rcptentry,"smsclient-.*",REG_FULL) == 1 ) {
#if DEBUG
			fprintf(stderr,"<%s> is an smsclient recipient\n",rcptentry);
			fflush(stderr);
#endif
			save_notification = send_smsclient(bbalpha,rcptentry);
		}
		else {
			sprintf(errormsg,"Unknown recipient <%s> - it may need to be prefixed with pg-",rcptentry);
			bb_errmsg("bbpage",errormsg);
		}

		if( save_notification == 1 ) {
			save_notif(bbhostsvc,machip,rcptentry,svcerr,downsecsmsg,recovered);
		}

	} /* For each recipient */

	cleanup(&pginfo);

	return(0);
}

#ifdef MAIN
int main(argc,argv) 
int argc;
char *argv[];
{
	if( argc != 2 ) {
		usage("wrong argument count");
		exit(1);
	}

	bb_page(argv[1]);

	exit(0);
}
#endif

/*
 * Process "ack" message type
 *
 * Format:
 *
 *   ack_event <ack #> <delay> [message]
 *   rm_event <host[.domain].service> <seconds down>
 */

void bb_doack(req)
char *req;
{
char	acktype[MAXLINE];
char	workreq[MAXLINE];
char	errormsg[MAXLINE*2];
char	acknumber[MAXLINE],acknum[MAXLINE];
char	delay[MAXLINE],downsecs[MAXLINE];
int	acknumber_int,delay_int,downsecs_int;
char	message[MAXLINE];
char	*workptr;
char	filemask[MAXLINE],hostsvc[MAXLINE],event[MAXLINE];
DIR	*dirinfo;
FILE	*fp;
int	rc,ftype,rcptid;
char	npfilename[MAXLINE],workfilename[MAXLINE],ackfilename[MAXLINE],ackfilemsg[MAXLINE];
char	np_acknumber[MAXLINE],np_host[MAXLINE],np_color[MAXLINE],np_recipient[MAXLINE];
struct	stat statinfo;
char	*npfilecontents;
char	pagetype[MAXLINE],pagerecovered[MAXLINE];
char	taginfo[MAXLINE],*commaptr,*dotptr;
char	request[MAXLINE],rm_npfiles[MAXLINE];
struct	stat ackfilestat;
int	statres;
time_t	timenow;
char	timenowbuf[32];
char    bbmsg[MAXLINE];
extern char bb[],*bbdisp,*bbdisplays;
#ifdef SCO3
pid_t child;
#else
int child;
#endif
int	status;

	if( req == NULL ) {
		errmsg("ack","NULL request for bb_doack()");
		return;
	}

	if( strlen(req) == 0 ) {
		errmsg("ack","Empty request for bb_doack()");
		return;
	}

#if DEBUG
	fprintf(stderr,"Ack request: <%s>\n",req);
	fflush(stderr);
#endif

	if( strlen(req) >= sizeof(workreq) ) {
		sprintf(errormsg,"Truncating ack request. Is %d chars, max %d characters allowed.",strlen(req),sizeof(workreq)-1); 
		errmsg("ack",errormsg);
	}

	memset(workreq,0,sizeof(workreq));
	strncpy(workreq,req,sizeof(workreq)-1);

	stripleadtrailspaces(workreq);

	memset(acktype,0,sizeof(acktype));
	sscanf(workreq,"%s",acktype);
	workptr = strstr(workreq,acktype) + strlen(acktype);
	stripleadspaces(workptr);

	if( strcmp(acktype,"ack_event") == 0 ) {
#if DEBUG
		fprintf(stderr,"Acking event\n");
		fflush(stderr);
#endif
		if( strlen(workptr) == 0 ) {
			errmsg("ack:ack_event","ack_event message is missing Ack number and delay");
			return;
		}
		memset(acknumber,0,sizeof(acknumber));
		sscanf(workptr,"%s",acknumber);
#if DEBUG
		fprintf(stderr,"Ack number: <%s>\n",acknumber);
		fflush(stderr);
#endif
		if( strlen(acknumber) == 0 ) {
			errmsg("ack:ack_event","ack_event message is missing the Ack number");
			return;
		}
		acknumber_int = 0;
		acknumber_int = atoi(acknumber);
		if( acknumber_int <= 0 || acknumber_int == 99 ||
			acknumber_int > 9999999 || strlen(acknumber) != 7 ) {
			sprintf(errormsg,"Invalid Ack number <%s>",acknumber);
			errmsg("ack:ack_event",errormsg);
			return;
		}

		workptr = strstr(workptr,acknumber) + strlen(acknumber);
		stripleadspaces(workptr);

		if( strlen(workptr) == 0 ) {
			errmsg("ack:ack_event","ack_event message is missing the delay value");
			return;
		}

		memset(delay,0,sizeof(delay));
		sscanf(workptr,"%s",delay);
#if DEBUG
		fprintf(stderr,"Delay <%s>\n",delay);
		fflush(stderr);
#endif
		delay_int = -1;
		delay_int = atoi(delay);
		if( delay_int < 0 ) {
			sprintf(errormsg,"Invalid delay <%s>",delay);
			errmsg("ack:ack_event",errormsg);
			return;
		}
		/*
		 * Point to message if any
		 */
		workptr = strstr(workptr,delay) + strlen(delay);
		stripleadspaces(workptr);

		memset(message,0,sizeof(message));
		if( strlen(workptr) != 0 ) {
			strncpy(message,workptr,sizeof(message)-1);
			replacestr(message,sizeof(message),"+"," ");
		}
#if DEBUG
		fprintf(stderr,"Message <%s>\n",message);
		fflush(stderr);
#endif

		/*
		 * Now go thru the list of pagin tag files
		 * and find out which one is associated with the number
		 * if the ack # ends with 99 then all tagfiles with
		 * the same prefix (without the 99) will be acknowledged
		 */
	
		/*
		 * if the ack # ends with 99 then all tagfiles with
		 * the same prefix (without the 99) will be acknowledged
		 */

		memset(acknum,0,sizeof(acknum));
		rcptid = acknumber_int % 100;
		if( rcptid == 99 ) {
			strncpy(acknum,acknumber,5);
		}
		else {
			strcpy(acknum,acknumber);
		}

		/* Get each np_file file that match tmp/np_* */
		strcpy(filemask,"np_*");
		dirinfo = NULL;
		rc = getdirfirst(&dirinfo,bbtmpdir,filemask,npfilename,GETDIR_FILE,&ftype);
		while( rc == 1 ) {
#if DEBUG
			fprintf(stderr,"Is acknumber <%s> associated with <%s> ?\n",acknumber,npfilename);
			fflush(stderr);
#endif
			/*
			 * Get file contents
			 */
			sprintf(workfilename,"%s/%s",bbtmpdir,npfilename);
			if( stat(workfilename,&statinfo) == 0 ) {
				if( (npfilecontents=calloc(1,statinfo.st_size+1)) != NULL) {
					if( (fp=fopen(workfilename,"r")) != NULL ) {
						if( fread(npfilecontents,statinfo.st_size,1,fp) > 0 ) {
							/*
							 * Is this file related to the acknum ?
							 */
							if( strncmp(npfilecontents,acknum,strlen(acknum)) == 0 ) {
								memset(np_acknumber,0,sizeof(np_acknumber));
								memset(np_host,0,sizeof(np_host));
								memset(np_color,0,sizeof(np_color));
								memset(np_recipient,0,sizeof(np_recipient));
								sscanf(npfilecontents,"%32s %512s %16s %512s",np_acknumber,np_host,np_color,np_recipient);
								if( strlen(np_host) == 0 ) {
									strcpy(np_host,"host.not.found.in.tagfile");
								}
								if( strlen(np_color) == 0 ) {
									strcpy(np_color,"color.not.found.in.tagfile");
								}
								if( strlen(np_recipient) == 0 ) {
									strcpy(np_recipient,"recipient.not.found.in.tagfile");
								}
								/*
								 * Adjust for the delay
								 */
#if DEBUG
								fprintf(stderr,"Ack # <%s> for <%s> delayed for <%s> mins\n",acknumber,np_host,delay);
								fflush(stderr);
#endif
								touchtime(workfilename,delay_int);
								convert_web_str(message);
								save_acklog(np_acknumber,delay,acknumber,npfilename,np_host,np_color,message);

								/*
								 * Save an ack tag file to display a different gif
								 */
								timenow = time(NULL);
								sprintf(timenowbuf,"%d",timenow);

								memset(ackfilemsg,0,sizeof(ackfilemsg));
								strncpy(ackfilemsg,np_host,sizeof(ackfilemsg)-1);
								strncat(ackfilemsg," ",sizeof(ackfilemsg)-strlen(ackfilemsg)-1);
								if( rcptid == 99 ) {
									strncat(ackfilemsg,"global-ack",sizeof(ackfilemsg)-strlen(ackfilemsg)-1);
								}
								else {
									strncat(ackfilemsg,np_recipient,sizeof(ackfilemsg)-strlen(ackfilemsg)-1);
								}
								strncat(ackfilemsg," ",sizeof(ackfilemsg)-strlen(ackfilemsg)-1);
								strncat(ackfilemsg,acknumber,sizeof(ackfilemsg)-strlen(ackfilemsg)-1);
								strncat(ackfilemsg," ",sizeof(ackfilemsg)-strlen(ackfilemsg)-1);
								strncat(ackfilemsg,delay,sizeof(ackfilemsg)-strlen(ackfilemsg)-1);
								strncat(ackfilemsg," ",sizeof(ackfilemsg)-strlen(ackfilemsg)-1);
								strncat(ackfilemsg,timenowbuf,sizeof(ackfilemsg)-strlen(ackfilemsg)-1);
								strncat(ackfilemsg," ",sizeof(ackfilemsg)-strlen(ackfilemsg)-1);
								strncat(ackfilemsg,message,sizeof(ackfilemsg)-strlen(ackfilemsg)-1);
								strncat(ackfilemsg,"\n",sizeof(ackfilemsg)-strlen(ackfilemsg)-1);

								/* send addtag_event message here */
								/* To all known BBDISPLAYS ... */
								if ((child = fork()) < 0) bbd_die("fork error");
								if (child == 0) {                       /* THE CHILD */
									/* Build message to send */
									sprintf(bbmsg,"ack addtag_event %s %s ",np_host, delay);
									strncat(bbmsg,ackfilemsg,sizeof(bbmsg)-strlen(bbmsg)-1);
									/* For ZOMBIE prone OSes, use the bb exec instead of bbsend() */
									/* The reason is if bbsend() gets stuck, then the whole bbd */
									/* waits for the child process to end */
#ifdef ZOMBIE
									execlp(bb, bb, bbdisp, bbmsg, (char *)NULL);
#else
									rc = bbsend(bbdisp,bbdisplays,bbmsg);
									exit(rc);
#endif 
								}
								/* Parent continues */
#ifdef ZOMBIE
								wait(&status);
#endif
							}
						}
						else {
							sprintf(errormsg,"The contents of <%s> could not be read",workfilename);
							errmsg("ack:ack_event",errormsg);
						}
						fclose(fp);
					}
					else {
						sprintf(errormsg,"The file <%s> could not be opened",workfilename);
						errmsg("ack:ack_event",errormsg);
					}
					free(npfilecontents);
				}
				else {
					errmsg("ack:ack_event","Could not allocate memory");
				}
			}
			else {
				sprintf(errormsg,"<%s> has suddenly disappeared ...",workfilename);
				errmsg("ack:ack_event",errormsg);
			}
			rc = getdirnext(dirinfo,bbtmpdir,filemask,npfilename,GETDIR_FILE,&ftype);
		}
		getdirdone(dirinfo);
	}
	else if( strcmp(acktype,"rm_event") == 0 ) {
#if DEBUG
		fprintf(stderr,"ack type: <%s>\n",acktype);
		fflush(stderr);
#endif
		if( strlen(workptr) == 0 ) {
			errmsg("ack:rm_event","message is missing host.service & event duration");
			return;
		}
		memset(hostsvc,0,sizeof(hostsvc));
		sscanf(workptr,"%s",hostsvc);
#if DEBUG
		fprintf(stderr,"host.service <%s>\n",hostsvc);
		fflush(stderr);
#endif
		if( valid_logname(hostsvc) != 1 ) {
			sprintf(errormsg,"Invalid hostname: <%s>\n",hostsvc);
			errmsg("ack:rm_event",errormsg);
			return;
		}

		workptr = strstr(workptr,hostsvc) + strlen(hostsvc);
		stripleadspaces(workptr);
		if( strlen(workptr) == 0 ) {
			errmsg("ack:rm_event","message is missing event duration");
			return;
		}
		memset(downsecs,0,sizeof(downsecs));
		sscanf(workptr,"%s",downsecs);
#if DEBUG
		fprintf(stderr,"Duration <%s>\n",downsecs);
		fflush(stderr);
#endif

		downsecs_int = -1;
		downsecs_int = atoi(downsecs);
		if( downsecs_int < 0) {
			sprintf(errormsg,"Invalid event duration <%s>",downsecs);
			errmsg("ack:rm_event",errormsg);
			return;
		}

		workptr = strstr(workptr,downsecs) + strlen(downsecs);
		stripleadspaces(workptr);

		if( strlen(workptr) > 0 ) {
			errmsg("ack:rm_event","Message contains invalid arguments");
			return;
		}

		memset(taginfo,0,sizeof(taginfo));
                if( fqdn == 0 ) {
                	strcpy(event,hostsvc);
                        commaptr = strchr(event,',');   
			if( commaptr ) {
				*commaptr = '\0';
				strcpy(taginfo,event);
				commaptr++;
				dotptr = strrchr(commaptr,'.');
				if( dotptr ) {
					strcat(taginfo,dotptr);
				}
				else {
					/* Error, not supposed to happend */
					/* but just in case */
					sprintf(errormsg,"invalid host.service <%s>\n",hostsvc);
					errmsg("ack:rm_event",errormsg);
					return;
				}
			}
			else {
				strcpy(taginfo,hostsvc);
			}
                }
                else {
                        strcpy(taginfo,hostsvc);
			replacestr(taginfo,sizeof(taginfo),",",".");
                }

		getsetup(pagetype,"pagetype", sizeof(pagetype));
		if( strlen(pagetype) == 0 ) {
			errmsg("ack:rm_event","pagetype token is not defined in bbwarnsetup.cfg");
		}
#if DEBUG
		fprintf(stderr,"pagetype: <%s>\n",pagetype);
		fflush(stderr);
#endif
		if( (strcmp(pagetype,"RCPT") != 0) && (strcmp(pagetype,"GROUP") != 0)
			&&  (strcmp(pagetype,"HOST") != 0) &&  (strcmp(pagetype,"EVENT") != 0) ) {
			sprintf(errormsg,"pagetype <%s> is invalid\n",pagetype);
			errmsg("ack:rm_event",errormsg);
		}

		getsetup(pagerecovered,"pagerecovered", sizeof(pagerecovered));
		if( strlen(pagerecovered) == 0 ) {
			errmsg("ack:rm_event","pagerecovered token is not defined in bbwarnsetup.cfg");
		}
#if DEBUG
		fprintf(stderr,"pagerecovered: <%s>\n",pagerecovered);
		fflush(stderr);
#endif
		/*
		 * A recovery msg is to be sent out
		 */
		if( strcmp(pagerecovered,"TRUE") == 0 ) {
			sprintf(request,"%s recovered %s Problem has been resolved after %d seconds",hostsvc,gettimestr(),downsecs_int);
			/*
			 * If not the first one to deal with this
			 * then bb_page() will exit (no need to remove associated np_ files)
			 */
#if DEBUG
			fprintf(stderr,"bb_page() <%s>\n",request);
			fflush(stderr);
#endif
			if( bb_page(request) == 100 ) {
#if DEBUG
				fprintf(stderr,"bb_page() already doing recovery for <%s>\n",hostsvc);
				fflush(stderr);
#endif
				return;
			}
		}

		/* send rmtag_event message here */
		/* To all known BBDISPLAYS ... */
		if ((child = fork()) < 0) bbd_die("fork error");
		if (child == 0) {                       /* THE CHILD */
			/* Build message to send */
			sprintf(bbmsg,"ack rmtag_event %s",taginfo);
			/* For ZOMBIE prone OSes, use the bb exec instead of bbsend() */
			/* The reason is if bbsend() gets stuck, then the whole bbd */
			/* waits for the child process to end */
#ifdef ZOMBIE
			execlp(bb, bb, bbdisp, bbmsg, (char *)NULL);
#else
			rc = bbsend(bbdisp,bbdisplays,bbmsg);
			exit(rc);
#endif 
		}
		/* Parent continues */
#ifdef ZOMBIE
		wait(&status);
#endif

		dotptr = strrchr(taginfo,'.');
		*dotptr = '\0';
		dotptr++;
		save_recoveries(taginfo,dotptr,downsecs_int);
		dotptr--;
		*dotptr = '.';

		/*
		 * Remove associated np_* with recovery
		 * Do only when pagetype == EVENT
		 * Because we know in that case that np_ file is unique
		 * to recovered event
		 */
		if( strcmp(pagetype,"EVENT") == 0 ) {
			/* Get each np_file file that match tmp/np_* */
			memset(rm_npfiles,0,sizeof(rm_npfiles));
			strcpy(filemask,"np_*");
			dirinfo = NULL;
			rc = getdirfirst(&dirinfo,bbtmpdir,filemask,npfilename,GETDIR_FILE,&ftype);
			while( rc == 1 ) {
#if DEBUG
				fprintf(stderr,"Is recovery event <%s> associated with <%s> ?\n",taginfo,npfilename);
				fflush(stderr);
#endif
				/*
				 * Get file contents
				 */
				sprintf(workfilename,"%s/%s",bbtmpdir,npfilename);
				if( stat(workfilename,&statinfo) == 0 ) {
					if( (npfilecontents=calloc(1,statinfo.st_size+1)) != NULL) {
						if( (fp=fopen(workfilename,"r")) != NULL ) {
							if( fread(npfilecontents,statinfo.st_size,1,fp) > 0 ) {
								/*
								 * Is this file related to the acknum ?
								 */
								fclose(fp);
#if DEBUG
								fprintf(stderr,"<%s> contents <%s>\n",npfilename,npfilecontents);
								fflush(stderr);
#endif
								if( strstr(npfilecontents,taginfo) != NULL ) {
									if( (strlen(rm_npfiles)+strlen(workfilename)+1) < (sizeof(rm_npfiles)-1) ) {
										strcat(rm_npfiles,workfilename);
										strcat(rm_npfiles," ");
#if DEBUG
										fprintf(stderr,"rm_npfiles <%s>\n",rm_npfiles);
										fflush(stderr);
#endif
									}
									else {
										strcpy(errormsg,"The rm_npfiles hold buffer is too small");
										errmsg("ack:rm_event",errormsg);
									}
								}
							}
							else {
								sprintf(errormsg,"The contents of <%s> could not be read",workfilename);
								errmsg("ack:rm_event",errormsg);
								fclose(fp);
							}
						}
						else {
							sprintf(errormsg,"The file <%s> could not be opened",workfilename);
							errmsg("ack:rm_event",errormsg);
						}
						free(npfilecontents);
					}
					else {
						errmsg("ack:rm_event","Could not allocate memory");
					}
				}
				else {
					sprintf(errormsg,"<%s> has suddenly disappeared ...",workfilename);
					errmsg("ack:rm_event",errormsg);
				}
				rc = getdirnext(dirinfo,bbtmpdir,filemask,npfilename,GETDIR_FILE,&ftype);
			}
			getdirdone(dirinfo);
			/*
			 * Now remove the matched np_ files
			 */
			stripleadtrailspaces(rm_npfiles);
			workptr = rm_npfiles;
			while( strlen(workptr) > 0 ) {
				sscanf(workptr,"%512s",workfilename);
				workptr += strlen(workfilename);
				stripleadspaces(workptr);
#if DEBUG
				fprintf(stderr,"removing <%s>\n",workfilename);
				fflush(stderr);
#endif
				unlink(workfilename);
			}
		}
	}
	else if( strcmp(acktype,"addtag_event") == 0 ) {
#if DEBUG
		fprintf(stderr,"ack type: <%s>\n",acktype);
		fflush(stderr);
#endif
		if( strlen(workptr) == 0 ) {
			errmsg("ack:addtag_event","message details are missing");
			return;
		}
		/* Create ack file for checkmark display if need be */
		timenow = time(NULL);
		sprintf(timenowbuf,"%d",timenow);
		/* Message should be in the form "host.service delay filecontents" */
		/* Get host.service */
		memset(np_host,0,sizeof(np_host));
		sscanf(workptr,"%s",np_host);
		workptr = strstr(workptr,np_host);
		workptr += strlen(np_host) + 1;
		/* Get delay */
		memset(delay,0,sizeof(delay));
		sscanf(workptr,"%s",delay);
		workptr = strstr(workptr,delay);
		workptr += strlen(delay) + 1;
		delay_int = atoi(delay);
		/* workptr now points to the beginning of the message */
		memset(ackfilename,0,sizeof(ackfilename));
		strncpy(ackfilename,bbacksdir,sizeof(ackfilename)-2);
		strcat(ackfilename,"/ack.");
		strncat(ackfilename,np_host,sizeof(ackfilename)-strlen(ackfilename)-1);
		memset(&ackfilestat,0,sizeof(ackfilestat));
		statres = stat(ackfilename,&ackfilestat);
		if( statres == -1 || (ackfilestat.st_mtime < (timenow+delay_int)) ) {
			savefile(ackfilename,workptr);
			touchtime(ackfilename,delay_int);
		}
	}
	else if( strcmp(acktype,"rmtag_event") == 0 ) {
#if DEBUG
		fprintf(stderr,"ack type: <%s>\n",acktype);
		fflush(stderr);
#endif
		if( strlen(workptr) == 0 ) {
			errmsg("ack:rmtag_event","message is missing host.service");
			return;
		}
		/* Message should be in the form "host.service" */
		memset(hostsvc,0,sizeof(hostsvc));
		sscanf(workptr,"%s",hostsvc);
		if( valid_logname(hostsvc) != 1 ) {
			sprintf(errormsg,"Invalid hostname: <%s>\n",hostsvc);
			errmsg("ack:rmtag_event",errormsg);
			return;
		}
		memset(ackfilename,0,sizeof(ackfilename));
		strncpy(ackfilename,bbacksdir,sizeof(ackfilename)-7);
		strcat(ackfilename,"/ack.");
		strncat(ackfilename,hostsvc,sizeof(ackfilename)-strlen(ackfilename)-1);
		unlink(ackfilename);
	}
	else {
		sprintf(errormsg,"Invalid ack type: <%s>\n",acktype);
		errmsg("ack:rm_event",errormsg);
	}

	return;
}
