/*
 *  sensor-alert.c by Adam Pierce <adam@doctort.org>
 *  v1.1  15-Jun-2006
 *
 *  This simple C program monitors the CPU and motherboard
 *  temperatures as reported by lm_sensors and shuts down
 *  the system if the maximum temperature is exceeded.
 *
 *  I would normally place this file in /usr/sbin and launch
 *  it once per minute using a crontab line like so:
 *
 *         * * * * * root /usr/sbin/sensor-alert
 *
 */

#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <string.h>

#define SENSORS  "/usr/bin/sensors"
#define SHUTDOWN "/sbin/halt -p"
#define LOGFILE  "/var/log/overheat.log"


/* This function is called when the system overheats. It logs the event
   and then initiates system shutdown. */
void overheat(char *SensorLine)
{
	FILE   *fLog;
	time_t  now;

	fLog = fopen(LOGFILE, "a");
	if(fLog != NULL)
	{
		now = time(NULL);
		fprintf(fLog, "%s %s", ctime(&now), SensorLine);
		fclose(fLog);
	}

	system(SHUTDOWN);
}

/* Looks at a line and finds any values (indicated by a + or - character).
   If the first value is higher than the second value, it returns 1.
   This results in a nonzero return if a temperature has been exceeded.

   You might have noticed the "ALARM" string which is sometimes output by
   sensors. This is not always a good indicator of the limits being exceeded
   so it is best to actually check the numbers. */
int analyze_line(char *line)
{
	int value[3];
	int n = 0;

	while(*line && n < 3)
	{
		if(*line == '+' || *line == '-')
			value[n++] = atoi(line + 1);
		line++;
	}

	if(n >= 2 && value[0] > value[1])
		return 1;

	return 0;
}

/* This works by capturing the output of the sensors utility and
   looking for any temperature items which have exceeded their
   limits. */
int main()
{
	FILE *p;
	char  buf[80];

	p = popen(SENSORS, "r");
	if(p == NULL)
		return 1;

	while(NULL != fgets(buf, 80, p))
	{
		if(strstr(buf, "Temp"))
		{
			if(analyze_line(buf))
			{
				overheat(buf);
				break;
			}
		}
	}

	pclose(p);
	return 0;
}
