/* $Id: page.c,v 1.39 2000/06/07 15:08:56 jared Exp $ */
#include "config.h"

/*
 *
 */
char *translate_string(char *str, struct hostinfo *svc)
{
	int x;
        time_t t; /* used to get the time */
	char out[1024];
	char tmp[1024];
        char myhostname[80]; /* my hostname */
	float value, tmp1, tmp2;
	struct my_hostent *hp;

	if (str == NULL)
	{
		return NULL;
	}
	time(&t);

	memset(out, 0, 1024);	/* zero it out */
	memset(myhostname, 0, 80); /* zero it out */
        gethostname(myhostname, 80); /* get my hostname */

        /* parse str as follows:             */
        /* %m = My host Name                 */
	/* %H = dns name of %h               */
        /* %s = Service                      */
	/* %p = port number (numeric)	     */
	/* %T = Current Time hh:mm:ss        */
        /* %t = Current Time mmm dd hh:mm:ss */
        /* %d = downtime dd:hh:mm            */
        /* %D = downtime dd:hh:mm:ss         */
        /* %i = unique id for outage         */
	/* %I = IP of host down              */
        /* %w = warning/what                 */
        /* %u = translates error type 
		to string describing it      */
        /* %h = hostname with failure        */
	/* %r = reliability %                */
	/* %V = Verbose History              */
        /*                                   */

	hp = my_gethostbyname(svc->hostname);
	/* FIXME: what happens if hp == NULL */

        /* convert to page */
        for (x=0; x < strlen(str);x++)
        {
		/* Handle C style newline and CR for sending to
			e-mail */
		if (str[x] == '\\')
		{
			x++;
			switch(str[x])
			{
				case 'n':
					strcat(out, "\n");
					break;
				case 'r':
					strcat(out, "\r");
					break;
			}
			continue;
		} else if (str[x] == '%')
                {
                        x++;
                        switch (str[x])
                        {
                                case 'm':
                                        strcat(out, myhostname);
                                        break;
				case 'H':
					strcat(out, get_hostname(hp));
					break;
                                case 'd': /* downtime */
                                        strcat(out, str_difftime(svc->deathtime,t));
                                        break;
                                case 'D': /* downtime 2 */
                                        strcat(out, str_difftime_sec(svc->deathtime, t));
                                        break;
                                case 'i':
                                        snprintf(tmp, 1024, "%s%ld%p", out, svc->deathtime, svc);
					memcpy(out,tmp,1024);
                                        break;
				case 'I':
					snprintf(tmp, 1024, "%s%s", out, get_ip(hp));
					memcpy(out,tmp,1024);
					break;
				case 'p':
					snprintf(tmp, 1024, "%s %d", out, svc->port);
					memcpy(out,tmp,1024);
					break;
				case 'r':
					tmp1 = svc->totaldown;
					tmp2 = svc->totalchecked;
					value = ((tmp1/tmp2) * 100);
					snprintf(tmp, 1024, "%s %10.6f%%", out,value);
					memcpy(out,tmp,1024);
					break;
                                case 's':
                                        strcat(out, type_to_name(svc->type));
                                        break;
				case 'T':
					strcat(out, ctime(&t)+11);
					out[strlen(out)-6]='\0';
					break;
                                case 't':
                                        strcat(out, ctime(&t)+4);
                                        out[strlen(out)-6]='\0';
                                        /* time */
                                        break;
                                case 'u':
                                        strcat(out, errtostr(svc->lastcheck));
                                        break;
                                case 'w':
                                        strcat(out, svc->message);
                                        break;
				case 'V':
					/* add to out the following:

						% reliability
						last outage time (prior to this)
						times checked, times failed
					*/
					break;
                                case 'h':
                                        strcat(out, svc->hostname);
                                        break;
                        }
                } else {
                        strncat(out, str+x, 1);
		}
        }

	return strdup(out);
}

/*
 *
 */
void gen_msgid(char *our_msgid)
{
	gen_rand_ascii(our_msgid, 26);
}

/*
 *
 */
void run_command_and_mail_output(struct hostinfo *svc)
{
	FILE *mail;
	FILE *cmd;
        struct passwd *pw; /* password structure */
	char *runme;
	uid_t myuid;
	char mailcmd[512];
	char buff[200];

	memset(buff, 0, 200);
	memset(mailcmd, 0, 512);

	if (fork() != 0)
	{
		return;
	}

	myuid = getuid();
	errno = 0;
	pw = getpwuid(myuid);

	if (pw == NULL)
	{
		perror("page.c:run_command_and_mail_output:getpwuid");
		return;
	}

	runme = translate_string(svc->command, svc);
	snprintf(mailcmd, 510, "%s -t", MAIL);

	if ((svc->contact == NULL) || (strlen(svc->contact) == 0))
	{
		system(runme+6);
		free(runme);
		exit(0);
	}

	if (debug)
	{
		print_err(0, "popening \"%s\"", runme+6);
	}

	errno = 0;
	cmd = popen(runme+6, "r");
	if (cmd == NULL)
	{
		perror("page.c:run_command_and_mail_output:popen cmd");
	}
	errno = 0;
	mail = popen(mailcmd, "w");
	if (mail == NULL)
	{
		perror("page.c:run_command_and_mail_output:popen mail");
        }

	/* The message */
	if (sender == NULL)
	{
		fprintf(mail, "From: System Monitor <%s@localhost>\n", 
			pw->pw_name);
	} else {
		fprintf(mail, "From: %s\n", sender);
	}
	fprintf(mail, "X-Sysmon-unique-id: %s\n", svc->unique_id);
	if (svc->hdr != NULL)
	{
		if (svc->hdrval != NULL)
			fprintf(mail, "%s: %s\n", svc->hdr, svc->hdrval);
		else
			fprintf(mail, "%s:\n", svc->hdr);
	}
	fprintf(mail, "To: %s\n", svc->contact);
	/* Insert Errors-To: headder if necessary */
	if (errorsto != NULL)
		fprintf(mail, "Errors-To: %s\n", errorsto);
	if (replyto != NULL)
		fprintf(mail, "Reply-To: %s\n", replyto);
	/* Insert Subject line */
	if (subject != NULL)
	{
		fprintf(mail, "Subject: %s is %s\n", svc->hostname, 
			errtostr(svc->lastcheck));
	} else {
		fprintf(mail, "\n");
	}

	/* Body of message */
	while (fgets(buff, 190, cmd) != NULL)
	{
		fprintf(mail, "%s", buff);
	}

	pclose(cmd);
	pclose(mail);
	free(runme);
	exit(0);
}

/* Tell someone that the host is down */
void page_someone(struct hostinfo *svc)
{
        FILE *fp; /* file handle used with popen */
	char command[512]; /* command for popen */
        struct passwd *pw; /* password structure */
        char *out;
	uid_t myuid;
	char myhostname[80]; /* my hostname */
	char msgid[256]; /* Our message-id */
	char *subjectline;

	/* Getuid can never fail per man page */
	myuid = getuid();

	if (gethostname(myhostname, 80) == -1)
	{
		perror("page.c:page_someone:gethostname");
		print_err(0, "page.c:page_someone:gethostname - unable to get our host name");
	}

	out = translate_string(pmesg, svc);

        syslogmsg(out);

	if (svc->command != NULL && donotify)
	{
		if (debug)
		{
			print_err(0, "We need to execute %s", 
				translate_string(svc->command, svc));
		}

		run_command_and_mail_output(svc);
		time(&svc->lastcontacted);
		svc->contacted = TRUE;
		free(out);
		return;
	}

	if (svc->contact == NULL)
	{
		svc->contacted = TRUE;
		free(out);
		return;
	} else if (strlen(svc->contact) == 0)
	{
		svc->contacted = TRUE;
		free(out);
		return;
	}

        if ((strlen(svc->contact) != 0) && (donotify))
        {
		errno = 0;
                pw = getpwuid(myuid);
		if (pw == NULL)
		{
			perror("page.c:page_someone:getpwuid");
			return;
		}

		/* set the time */
		time(&svc->lastcontacted);
                /* Set contacted */
                svc->contacted = TRUE;


		/* setup the command to call (sendmail) */
		snprintf(command, 500, "%s -t", MAIL);
		if (sender != NULL)
		{
			snprintf(command, 500, "%s -f%s -t", MAIL, sender);
		}

		errno = 0;
		/* open a connection to sendmail */
                fp = popen(command, "w");

		if (fp == NULL)
		{
			perror("page.c:page_someone:popen fp");
			free(out);
			return;
		}

		if (sender == NULL)
		{
			fprintf(fp, "From: System Monitor <%s@localhost>\n", 
				pw->pw_name);
		} else {
			fprintf(fp, "From: %s\n", sender);
		}
		fprintf(fp, "X-Sysmon-unique-id: %s\n", svc->unique_id);
	        if (svc->hdr != NULL)
	        {
			if (svc->hdrval != NULL)
				fprintf(fp, "%s: %s\n", svc->hdr, svc->hdrval);
			else
				fprintf(fp, "%s:\n", svc->hdr);
	        }

                fprintf(fp, "To: %s\n", svc->contact);
		/* Insert Errors-To: headder if necessary */
		if (errorsto != NULL)
		{
			fprintf(fp, "Errors-To: %s\n", errorsto);
		}
		if (replyto != NULL)
		{
			fprintf(fp, "Reply-To: %s\n", replyto);
		}

	/* Generate our own message-id for use in headders
	 * such that threading mail clients can be used easier
	 */
		gen_msgid(msgid);

		fprintf(fp, "Message-Id: <%s@%s>\n", msgid, "sysmon");
		if (strlen(svc->lastmsgid) != 0)
		{
			fprintf(fp, "In-Reply-To: <%s@%s>\n", svc->lastmsgid,
				"sysmon");
		}
	/* Save the current Message-ID */
		strcpy(svc->lastmsgid, msgid);

		subjectline = translate_string(subject, svc);
		/* Insert Subject line */
		if (subject != NULL)
		{
			fprintf(fp, "Subject: %s\n", subjectline);
		} else {
			fprintf(fp, "\n");
		}

		if (subjectline != NULL)
		{
			free (subjectline);
		}

		/* Body of message */
                fprintf(fp, "%s\n.\n", out);

		/* Close the PIPE */
                pclose(fp);

        }
	free(out);

	return;
}

