Commit 1f8131bd authored by Daniel Graziotin's avatar Daniel Graziotin

Fixes #18. Seems ready for v1.4.0

parent 03ac2050
......@@ -3,8 +3,7 @@ Fan-Control-Daemon
Introduction
---------------------
This is an enhanced version of [rvega's Fan-Control-Daemon](https://github.com/rvega/Fan-Control-Daemon),
which itself is an enhanced version of [Allan McRae mbpfan](http://allanmcrae.com/2010/05/simple-macbook-pro-fan-daemon/)
This is an enhanced version of [Allan McRae mbpfan](http://allanmcrae.com/2010/05/simple-macbook-pro-fan-daemon/)
Fan-Control-Daemon is a daemon that uses input from coretemp module and sets the fan speed using the applesmc module.
This enhanced version assumes any number of processors and fans (max. 10).
......@@ -50,10 +49,6 @@ Compile with
make
Manually compile with
gcc -o bin/mbpfan src/mbpfan.c -lm
Install Instructions
--------------------
......
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
#!/bin/bash
# not maintained in this proejct
# Archlinux rc script
# not maintained in this project
# please, fix it and contribute back to the project
daemon_name=mbpfan
......
......@@ -34,10 +34,12 @@ int write_pid(int pid)
{
FILE *file = NULL;
file = fopen(program_pid, "w");
if(file != NULL) {
fprintf(file, "%d", pid);
fclose(file);
return 1;
} else {
return 0;
}
......@@ -48,11 +50,13 @@ int read_pid()
FILE *file = NULL;
int pid = -1;
file = fopen(program_pid, "r");
if(file != NULL) {
fscanf(file, "%d", &pid);
fclose(file);
return pid;
}
return -1;
}
......@@ -103,6 +107,7 @@ void go_daemon(void (*fan_control)())
if(verbose) {
setlogmask(LOG_UPTO(LOG_DEBUG));
openlog(program_name, LOG_CONS | LOG_NDELAY | LOG_PERROR | LOG_PID, LOG_USER);
} else {
setlogmask(LOG_UPTO(LOG_INFO));
openlog(program_name, LOG_CONS, LOG_USER);
......@@ -115,9 +120,11 @@ void go_daemon(void (*fan_control)())
if (daemonize) {
pid_slave = fork();
if (pid_slave < 0) {
exit(EXIT_FAILURE);
}
if (pid_slave > 0) {
// kill the father
exit(EXIT_SUCCESS);
......@@ -127,6 +134,7 @@ void go_daemon(void (*fan_control)())
// new sid_slave for the child process
sid_slave = setsid();
if (sid_slave < 0) {
exit(EXIT_FAILURE);
}
......@@ -151,23 +159,30 @@ void go_daemon(void (*fan_control)())
printf("Writing a new .pid file with value %d at: %s\n", current_pid, program_pid);
syslog(LOG_INFO, "Writing a new .pid file with value %d at: %s", current_pid, program_pid);
}
if (write_pid(current_pid) == 0) {
syslog(LOG_ERR, "Can not create a .pid file at: %s. Aborting", program_pid);
if (verbose) {
printf("ERROR: Can not create a .pid file at: %s. Aborting\n", program_pid);
}
exit(EXIT_FAILURE);
} else {
if (verbose) {
printf("Successfully written a new .pid file with value %d at: %s\n", current_pid, program_pid);
syslog(LOG_INFO, "Successfully written a new .pid file with value %d at: %s", current_pid, program_pid);
}
}
} else {
syslog(LOG_ERR, "A previously created .pid file exists at: %s. Aborting", program_pid);
if (verbose) {
printf("ERROR: a previously created .pid file exists at: %s.\n Aborting\n", program_pid);
}
exit(EXIT_FAILURE);
}
......
......@@ -13,6 +13,8 @@
*
*/
#ifndef _DAEMON_H_
#define _DAEMON_H_
/**
* Write the PID of the forked daemon to the
......@@ -47,4 +49,6 @@ void signal_handler(int signal);
/**
* Daemonizes
*/
int go_daemon(void (*function)());
\ No newline at end of file
int go_daemon(void (*function)());
#endif
\ No newline at end of file
#ifndef _GLOBAL_H_
#define _GLOBAL_H_
extern int daemonize;
extern int verbose;
extern const char* program_name;
extern const char* program_pid;
\ No newline at end of file
extern const char* program_pid;
struct s_sensors {
char* path;
char* fan_output_path;
char* fan_manual_path;
unsigned int temperature;
struct s_sensors *next;
};
typedef s_sensors t_sensors;
#endif
\ No newline at end of file
......@@ -13,6 +13,10 @@
*
*/
/**
* Code formatted with astyle -A3 -s --break-blocks=all --add-brackets *.c *.h
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
......@@ -46,6 +50,7 @@ int main(int argc, char *argv[])
{
int c;
while( (c = getopt(argc, argv, "hftv|help")) != -1) {
switch(c) {
case 'h':
......
......@@ -57,7 +57,7 @@ int max_temp = 86; // do not set it > 90
int polling_interval = 7;
/*
struct s_sensors {
char* path;
char* fan_output_path;
......@@ -65,6 +65,9 @@ struct s_sensors {
unsigned int temperature;
struct s_sensors *next;
};
*/
typedef struct s_sensors t_sensors;
t_sensors *retrieve_sensors()
......@@ -82,6 +85,7 @@ t_sensors *retrieve_sensors()
sprintf(number,"%d",0);
int i = 0;
for(i = 0; i<10; i++) {
path = (char*) malloc(sizeof( char ) * path_size);
......@@ -98,24 +102,33 @@ t_sensors *retrieve_sensors()
s->path = (char *) malloc(sizeof( char ) * path_size);
strcpy(s->path, path);
fscanf(file, "%d", &s->temperature);
if (sensors_head == NULL) {
sensors_head = s;
sensors_head->next = NULL;
} else {
t_sensors *tmp = sensors_head;
while (tmp->next != NULL) {
tmp = tmp->next;
}
tmp->next = s;
tmp->next->next = NULL;
}
fclose(file);
}
free(path);
path = NULL;
}
if(sensors_head != NULL)
if(sensors_head != NULL) {
find_fans(sensors_head);
}
return sensors_head;
}
......@@ -162,6 +175,7 @@ void find_fans(t_sensors* sensors)
tmp->fan_output_path = (char *) malloc(sizeof( char ) * path_min_size);
tmp->fan_manual_path = (char *) malloc(sizeof( char ) * path_man_size);
}
strcpy(tmp->fan_output_path, path_output);
strcpy(tmp->fan_manual_path, path_manual);
tmp = tmp->next;
......@@ -173,6 +187,7 @@ void find_fans(t_sensors* sensors)
if(verbose) {
printf("Found %d sensors and %d fans\n", n_sensors, n_fans);
if(daemonize) {
syslog(LOG_INFO, "Found %d sensors and %d fans", n_sensors, n_fans);
}
......@@ -189,12 +204,15 @@ void set_fans_man(t_sensors *sensors)
t_sensors *tmp = sensors;
FILE *file;
while(tmp != NULL) {
file = fopen(tmp->fan_manual_path, "rw+");
if(file != NULL) {
fprintf(file, "%d", 1);
fclose(file);
}
tmp = tmp->next;
}
}
......@@ -214,6 +232,7 @@ t_sensors *refresh_sensors(t_sensors *sensors)
tmp = tmp->next;
}
return sensors;
}
......@@ -223,8 +242,10 @@ void set_fan_speed(t_sensors* sensors, int speed)
{
t_sensors *tmp = sensors;
FILE *file;
while(tmp != NULL) {
file = fopen(tmp->fan_output_path, "rw+");
if(file != NULL) {
fprintf(file, "%d", speed);
fclose(file);
......@@ -243,10 +264,12 @@ unsigned short get_temp(t_sensors* sensors)
unsigned short temp = 0;
t_sensors* tmp = sensors;
while(tmp != NULL) {
sum_temp += tmp->temperature;
tmp = tmp->next;
}
temp = (unsigned short)( ceil( (float)( sum_temp ) / 2000. ) );
return temp;
}
......@@ -262,35 +285,63 @@ void retrieve_settings()
/* Could not open configfile */
if(verbose) {
printf("Couldn't open configfile, using defaults\n");
if(daemonize) {
syslog(LOG_INFO, "Couldn't open configfile, using defaults");
}
}
} else {
settings = settings_open(f);
fclose(f);
if (settings == NULL) {
/* Could not read configfile */
if(verbose) {
printf("Couldn't read configfile\n");
if(daemonize) {
syslog(LOG_INFO, "Couldn't read configfile");
}
}
} else {
/* Read configfile values */
result = settings_get_int(settings, "general", "min_fan_speed");
if (result != 0) min_fan_speed = result;
if (result != 0) {
min_fan_speed = result;
}
result = settings_get_int(settings, "general", "max_fan_speed");
if (result != 0) max_fan_speed = result;
if (result != 0) {
max_fan_speed = result;
}
result = settings_get_int(settings, "general", "low_temp");
if (result != 0) low_temp = result;
if (result != 0) {
low_temp = result;
}
result = settings_get_int(settings, "general", "high_temp");
if (result != 0) high_temp = result;
if (result != 0) {
high_temp = result;
}
result = settings_get_int(settings, "general", "max_temp");
if (result != 0) max_temp = result;
if (result != 0) {
max_temp = result;
}
result = settings_get_int(settings, "general", "polling_interval");
if (result != 0) polling_interval = result;
if (result != 0) {
polling_interval = result;
}
/* Destroy the settings object */
settings_delete(settings);
......@@ -316,10 +367,12 @@ void mbpfan()
if(verbose) {
printf("Sleeping for %d seconds\n", polling_interval);
if(daemonize) {
syslog(LOG_INFO, "Sleeping for %d seconds", polling_interval);
}
}
sleep(polling_interval);
step_up = (float)( max_fan_speed - min_fan_speed ) /
......@@ -354,6 +407,7 @@ void mbpfan()
if(verbose) {
printf("Old Temp %d: New Temp: %d, Fan Speed: %d\n", old_temp, new_temp, fan_speed);
if(daemonize) {
syslog(LOG_INFO, "Old Temp %d: New Temp: %d, Fan Speed: %d", old_temp, new_temp, fan_speed);
}
......@@ -363,10 +417,12 @@ void mbpfan()
if(verbose) {
printf("Sleeping for %d seconds\n", polling_interval);
if(daemonize) {
syslog(LOG_INFO, "Sleeping for %d seconds", polling_interval);
}
}
sleep(polling_interval);
}
}
......@@ -14,6 +14,9 @@
*
*/
#ifndef _MBPFAN_H_
#define _MBPFAN_H_
/** Basic fan speed parameters
*/
extern int min_fan_speed;
......@@ -82,4 +85,6 @@ unsigned short get_temp(t_sensors* sensors);
/**
* Main Program
*/
void mbpfan();
\ No newline at end of file
void mbpfan();
#endif
\ No newline at end of file
......@@ -3,6 +3,7 @@
#include <stdlib.h>
#include <time.h>
#include <limits.h>
#include "global.h"
#include "mbpfan.h"
#include "settings.h"
#include "minunit.h"
......@@ -10,32 +11,41 @@
int tests_run = 0;
static char *test_sensor_paths()
static const char *test_sensor_paths()
{
t_sensors* sensors = retrieve_sensors();
mu_assert("No sensors found", sensors != NULL);
t_sensors* tmp = sensors;
while(tmp != NULL) {
mu_assert("Sensor does not have a valid path", tmp->path != NULL);
if(tmp->path != NULL)
if(tmp->path != NULL) {
mu_assert("Sensor does not have valid temperature", tmp->temperature > 0);
}
tmp = tmp->next;
}
return 0;
}
static char *test_fan_paths()
static const char *test_fan_paths()
{
t_sensors* sensors = retrieve_sensors();
mu_assert("No sensors found", sensors != NULL);
t_sensors* tmp = sensors;
int found_fan_path = 0;
while(tmp != NULL) {
if(tmp->fan_output_path != NULL)
if(tmp->fan_output_path != NULL) {
found_fan_path++;
}
tmp = tmp->next;
}
mu_assert("No fans found", found_fan_path != 0);
return 0;
}
......@@ -46,8 +56,11 @@ unsigned time_seed()
unsigned char *p = (unsigned char *)&now;
unsigned seed = 0;
size_t i;
for ( i = 0; i < sizeof now; i++ )
for ( i = 0; i < sizeof now; i++ ) {
seed = seed * ( UCHAR_MAX + 2U ) + p[i];
}
return seed;
}
......@@ -56,17 +69,19 @@ unsigned time_seed()
int stress(int n)
{
int f = n;
while (f > 0) {
while(n > 0) {
srand ( time_seed() );
n--;
}
f--;
n = f;
}
}
static char *test_get_temp()
static const char *test_get_temp()
{
t_sensors* sensors = retrieve_sensors();
mu_assert("No sensors found", sensors != NULL);
......@@ -78,21 +93,24 @@ static char *test_get_temp()
return 0;
}
static char *test_config_file()
static const char *test_config_file()
{
FILE *f = NULL;
Settings *settings = NULL;
f = fopen("/etc/mbpfan.conf", "r");
mu_assert("No config file found", f != NULL);
if (f == NULL)
if (f == NULL) {
return 0;
}
settings = settings_open(f);
fclose(f);
mu_assert("Could not read settings from config file", settings != NULL);
if (settings == NULL)
if (settings == NULL) {
return 0;
}
mu_assert("Could not read min_fan_speed from config file",settings_get_int(settings, "general", "min_fan_speed") != 0);
mu_assert("Could not read max_fan_speed from config file",settings_get_int(settings, "general", "max_fan_speed") != 0);
......@@ -107,7 +125,7 @@ static char *test_config_file()
}
static char *all_tests()
static const char *all_tests()
{
mu_run_test(test_sensor_paths);
mu_run_test(test_fan_paths);
......@@ -120,12 +138,15 @@ int tests()
{
printf("Starting the tests..\n");
printf("It is normal for them to take a bit to finish.\n");
char *result = all_tests();
const char *result = all_tests();
if (result != 0) {
printf("%s \n", result);
} else {
printf("ALL TESTS PASSED\n");
}
printf("Tests run: %d\n", tests_run);
return result != 0;
......
/**
* This is the MinUnit testing framework - http://www.jera.com/techinfo/jtns/jtn002.html
*/
#define mu_assert(message, test) do { if (!(test)) return message; } while (0)
#define mu_run_test(test) do { char *message = test(); tests_run++; \
if (message) return message; } while (0)
struct s_sensors {
char* path;
char* fan_output_path;
char* fan_manual_path;
unsigned int temperature;
struct s_sensors *next;
};
typedef s_sensors t_sensors;
#ifndef _MINUNIT_H_
#define _MINUNIT_H_
#define mu_assert(message, test) do { if (!(test)) return message; } while (0)
#define mu_run_test(test) do { const char *message = test(); tests_run++; \
if (message) return message; } while (0)
extern int tests_run;
static char *test_sensor_paths();
static char *test_fan_paths();
static char *test_get_temp();
static char *test_config_file();
static const char *test_sensor_paths();
static const char *test_fan_paths();
static const char *test_get_temp();
static const char *test_config_file();
static const char *all_tests();
static char *all_tests();
int tests();
int tests();
\ No newline at end of file
#endif
\ No newline at end of file
This diff is collapsed.
......@@ -62,15 +62,19 @@ StrMap * sm_new(unsigned int capacity)
StrMap *map;
map = (StrMap*)malloc(sizeof(StrMap));
if (map == NULL) {
return NULL;
}
map->count = capacity;
map->buckets = (Bucket*)malloc(map->count * sizeof(Bucket));
if (map->buckets == NULL) {
free(map);
return NULL;
}
memset(map->buckets, 0, map->count * sizeof(Bucket));
return map;
}
......@@ -84,23 +88,28 @@ void sm_delete(StrMap *map)
if (map == NULL) {
return;
}
n = map->count;
bucket = map->buckets;
i = 0;
while (i < n) {
m = bucket->count;
pair = bucket->pairs;
j = 0;
while(j < m) {
free(pair->key);
free(pair->value);
pair++;
j++;
}
free(bucket->pairs);
bucket++;
i++;
}
free(map->buckets);
free(map);
}
......@@ -114,24 +123,31 @@ int sm_get(const StrMap *map, const char *key, char *out_buf, unsigned int n_out
if (map == NULL) {
return 0;
}
if (key == NULL) {
return 0;
}
index = hash(key) % map->count;
bucket = &(map->buckets[index]);
pair = get_pair(bucket, key);
if (pair == NULL) {
return 0;
}
if (out_buf == NULL && n_out_buf == 0) {
return strlen(pair->value) + 1;
}
if (out_buf == NULL) {
return 0;
}
if (strlen(pair->value) >= n_out_buf) {
return 0;
}
strcpy(out_buf, pair->value);
return 1;
}
......@@ -145,15 +161,19 @@ int sm_exists(const StrMap *map, const char *key)
if (map == NULL) {
return 0;
}
if (key == NULL) {
return 0;
}
index = hash(key) % map->count;
bucket = &(map->buckets[index]);
pair = get_pair(bucket, key);
if (pair == NULL) {
return 0;
}
return 1;
}
......@@ -168,14 +188,17 @@ int sm_put(StrMap *map, const char *key, const char *value)
if (map == NULL) {
return 0;
}
if (key == NULL || value == NULL) {
return 0;
}
key_len = strlen(key);
value_len = strlen(value);
/* Get a pointer to the bucket the key string hashes to */
index = hash(key) % map->count;
bucket = &(map->buckets[index]);
/* Check if we can handle insertion by simply replacing
* an existing value in a key-value pair in the bucket.
*/
......@@ -188,50 +211,64 @@ int sm_put(StrMap *map, const char *key, const char *value)
* space for the new larger value.
*/
tmp_value = (char*)realloc(pair->value, (value_len + 1) * sizeof(char));
if (tmp_value == NULL) {
return 0;
}
pair->value = tmp_value;
}
/* Copy the new value into the pair that matches the key */
strcpy(pair->value, value);
return 1;
}
/* Allocate space for a new key and value */
new_key = (char*)malloc((key_len + 1) * sizeof(char));
if (new_key == NULL) {
return 0;
}
new_value = (char*)malloc((value_len + 1) * sizeof(char));
if (new_value == NULL) {
free(new_key);
return 0;
}
/* Create a key-value pair */
if (bucket->count == 0) {
/* The bucket is empty, lazily allocate space for a single
* key-value pair.
*/
bucket->pairs = (Pair*)malloc(sizeof(Pair));
if (bucket->pairs == NULL) {
free(new_key);
free(new_value);
return 0;
}
bucket->count = 1;
} else {
/* The bucket wasn't empty but no pair existed that matches the provided
* key, so create a new key-value pair.
*/
tmp_pairs = (Pair*)realloc(bucket->pairs, (bucket->count + 1) * sizeof(Pair));
if (tmp_pairs == NULL) {
free(new_key);
free(new_value);
return 0;
}
bucket->pairs = tmp_pairs;
bucket->count++;
}
/* Get the last pair in the chain for the bucket */
pair = &(bucket->pairs[bucket->count - 1]);
pair->key = new_key;
......@@ -252,22 +289,27 @@ int sm_get_count(const StrMap *map)
if (map == NULL) {
return 0;
}
bucket = map->buckets;
n = map->count;
i = 0;
count = 0;
while (i < n) {
pair = bucket->pairs;
m = bucket->count;
j = 0;
while (j < m) {
count++;
pair++;
j++;
}
bucket++;
i++;
}
return count;
}
......@@ -280,24 +322,30 @@ int sm_enum(const StrMap *map, sm_enum_func enum_func, const void *obj)
if (map == NULL) {
return 0;
}
if (enum_func == NULL) {
return 0;
}
bucket = map->buckets;
n = map->count;
i = 0;
while (i < n) {
pair = bucket->pairs;
m = bucket->count;
j = 0;
while (j < m) {
enum_func(pair->key, pair->value, obj);
pair++;
j++;
}
bucket++;
i++;
}
return 1;
}
......@@ -311,20 +359,25 @@ static Pair * get_pair(Bucket *bucket, const char *key)
Pair *pair;
n = bucket->count;
if (n == 0) {
return NULL;
}
pair = bucket->pairs;
i = 0;
while (i < n) {
if (pair->key != NULL && pair->value != NULL) {
if (strcmp(pair->key, key) == 0) {
return pair;
}
}
pair++;
i++;
}
return NULL;
}
......@@ -339,6 +392,7 @@ static unsigned long hash(const char *str)
while (c = *str++) {
hash = ((hash << 5) + hash) + c;
}
return hash;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment