/*
 * copyright (c) 2003
 * the regents of the university of michigan
 * all rights reserved
 * 
 * permission is granted to use, copy, create derivative works and redistribute
 * this software and such derivative works for any purpose, so long as the name
 * of the university of michigan is not used in any advertising or publicity
 * pertaining to the use or distribution of this software without specific,
 * written prior authorization.  if the above copyright notice or any other
 * identification of the university of michigan is included in any copy of any
 * portion of this software, then the disclaimer below must also be included.
 * 
 * this software is provided as is, without representation from the university
 * of michigan as to its fitness for any purpose, and without warranty by the
 * university of michigan of any kind, either express or implied, including
 * without limitation the implied warranties of merchantability and fitness for
 * a particular purpose. the regents of the university of michigan shall not be
 * liable for any damages, including special, indirect, incidental, or
 * consequential damages, with respect to any claim arising out of or in
 * connection with the use of the software, even if it has been or is hereafter
 * advised of the possibility of such damages.
 */

/*
 * poll a TempTrax 2000 once every ten minutes and log the temperature
 *
 * -d (don't fork; write to stdout)
 * -s sleepytime (secs)
 * -t ttyno
 * -f logfile1
 * -l logfile2
 * -r 60.-85. (acceptable range)
 *
 * Jim Rees, CITI, April 2003
 * Modified be Zach Hyde, CITI, December 2006
 */

#include <sys/types.h>
#include <sys/file.h>
#include <sys/time.h>
#include <sys/errno.h>

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <termios.h>

#define LINE		"/dev/cua%02d"
#define LOGFILE1	"/var/log/templog"
#define LOGFILE2	"/var/log/templog2"
#define MAILCMD		"/usr/bin/mail -s 'Machine room temp warning' tempwarning"
#define WARNINTVL	3600

int sleepytime = 600;
float tlo = 60., thi = 85.;
char probe1[8], probe2[8], *mailmsg = "Machine room temperature is now %s\n";
int dflag;

FILE *openlog(char *logfname);
void closelog(FILE * logf);
char *gettemp(char *line);
int sendwarning(char *temp, time_t now);

int
main(int ac, char *av[])
{
    int i, ttyno = 0;
    char *logfname1 = NULL, *logfname2 = NULL, line[32], *temp;
    time_t now;
    FILE *logf;

    while ((i = getopt(ac, av, "dl:f:s:t:r:")) != -1) {
	switch (i) {
	case 'd':
	    dflag = 1;
	    break;
	case 'f':
	    logfname1 = optarg;
	    break;
	case 'l':
	    logfname2 = optarg;
	    break;
	case 's':
	    sleepytime = atoi(optarg);
	    break;
	case 't':
	    ttyno = atoi(optarg);
	    break;
	case 'r':
	    sscanf(optarg, "%f-%f", &tlo, &thi);
	    break;
	}
    }

    snprintf(line, sizeof line, LINE, ttyno);

    if (!dflag) {
	daemon(0, 0);
	if (logfname1 == NULL)
	    logfname1 = LOGFILE1;
	if (logfname2 == NULL)
	    logfname2 = LOGFILE2;
    }

    while (1) {
	if (dflag) {
	    printf("%s", "Enter: ");
	    getchar();
	} else {
	    sleep(sleepytime - time(NULL) % sleepytime);
	}
	time(&now);
	temp = gettemp(line);
	sscanf(temp, "%s %s", probe1, probe2);

	logf = openlog(logfname1);
	fprintf(logf, "%u %s\n", now, probe1);
	closelog(logf);

	logf = openlog(logfname2);
	fprintf(logf, "%u %s\n", now, probe2);
	closelog(logf);

	if (temp)
	    sendwarning(temp, now);
    }

    exit(0);
}

FILE *
openlog(char *logfname)
{
    FILE *logf;

    if (logfname == NULL)
	logf = stdout;
    else {
	if ((logf = fopen(logfname, "a")) == NULL) {
	    perror(logfname);
	    exit(2);
	}
	dup2(fileno(logf), fileno(stderr));
    }
    return logf;
}

void
closelog(FILE * logf)
{
    if (logf == stdout)
	fflush(logf);
    else
	fclose(logf);
}

char *
gettemp(char *line)
{
    int i = 0;
    char c;
    int fd;
    FILE *f;
    static char ibuf[12];
    struct termios t;
    fd_set fds;
    struct timeval tv;

    /* Open the port to the TempTrax and set tty modes */

    if ((fd = open(line, (O_RDWR | O_NDELAY))) < 0) {
	perror("open");
	exit(1);
    }

    if (tcgetattr(fd, &t) < 0) {
	perror("tcgetattr");
	close(fd);
	return NULL;
    }

    cfsetispeed(&t, B9600);
    cfsetospeed(&t, B9600);

    t.c_iflag &= ~(ISTRIP | INLCR | ICRNL | IXON);
    t.c_iflag |= (IGNBRK | IGNPAR | IGNCR);
    t.c_oflag &= ~OPOST;
    t.c_lflag &= ~(ECHO | ECHONL | ISIG);
    t.c_lflag |= (ICANON | IEXTEN);
    t.c_cflag &= ~(CSIZE | PARODD | PARENB | CSTOPB | CRTSCTS);
    t.c_cflag |= (CLOCAL | CS8);

    t.c_cc[VMIN] = 1;
    t.c_cc[VTIME] = 0;

    if (tcsetattr(fd, TCSANOW, &t) < 0) {
	perror("tcsetattr");
	close(fd);
	return NULL;
    }

    /* Wait for power-up, send a char, read temp */

    sleep(1);
    f = fdopen(fd, "r");
    write(fd, "\n", 1);

    FD_ZERO(&fds);
    FD_SET(fd, &fds);
    tv.tv_sec = 1;
    tv.tv_usec = 0;
    memset(ibuf, '\0', 12);
    select(fd + 1, &fds, NULL, NULL, &tv);

    for (i = 0; i < 11;) {
	c = fgetc(f);
	if (c == EOF) {
	    clearerr(f);
	} else {
	    if (dflag)
		printf("%d - <%c>\n", i, c);
	    ibuf[i] = c;
	    i++;
	}
    }

    fclose(f);
    return ibuf;
}

int
sendwarning(char *temp, time_t now)
{
    static time_t lastwarning;
    FILE *f;
    float t;
    int code = 0;

    sscanf(temp, "%f", &t);

    if ((t < tlo || t > thi) && now >= lastwarning + WARNINTVL) {
	f = popen(MAILCMD, "w");
	if (dflag)
	    printf(mailmsg, temp);
	fprintf(f, mailmsg, temp);
	lastwarning = now;
	code = pclose(f);
    }
    return code;
}
