Fixes #18. Seems ready for v1.4.0

This commit is contained in:
Daniel Graziotin 2012-08-23 22:32:49 +02:00
parent 03ac20500b
commit 1f8131bd9d
15 changed files with 323 additions and 47 deletions

View file

@ -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
--------------------

0
mbpfan.init.debian Executable file → Normal file
View file

0
mbpfan.init.gentoo Executable file → Normal file
View file

0
mbpfan.init.redhat Executable file → Normal file
View file

View file

@ -1,6 +1,7 @@
#!/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

View file

@ -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);
}

View file

@ -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)());
int go_daemon(void (*function)());
#endif

View file

@ -1,5 +1,19 @@
#ifndef _GLOBAL_H_
#define _GLOBAL_H_
extern int daemonize;
extern int verbose;
extern const char* program_name;
extern const char* program_pid;
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

View 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':

View file

@ -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);
}
}

View file

@ -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();
void mbpfan();
#endif

View 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;

View file

@ -1,27 +1,23 @@
/**
* This is the MinUnit testing framework - http://www.jera.com/techinfo/jtns/jtn002.html
*/
#ifndef _MINUNIT_H_
#define _MINUNIT_H_
#define mu_assert(message, test) do { if (!(test)) return message; } while (0)
#define mu_run_test(test) do { char *message = test(); tests_run++; \
#define mu_run_test(test) do { const 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;
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 char *all_tests();
static const char *all_tests();
int tests();
int tests();
#endif

View file

@ -97,9 +97,11 @@ Settings * settings_new()
Settings *settings;
settings = (Settings*)malloc(sizeof(Settings));
if (settings == NULL) {
return NULL;
}
settings->section_count = 0;
settings->sections = NULL;
return settings;
@ -113,17 +115,22 @@ void settings_delete(Settings *settings)
if (settings == NULL) {
return;
}
section = settings->sections;
n = settings->section_count;
i = 0;
while (i < n) {
sm_delete(section->map);
if (section->name != NULL) {
free(section->name);
}
section++;
i++;
}
free(settings->sections);
free(settings);
}
@ -139,20 +146,26 @@ Settings * settings_open(FILE *stream)
if (stream == NULL) {
return NULL;
}
settings = settings_new();
if (settings == NULL) {
return NULL;
}
parse_state.current_section = section_buf;
parse_state.current_section_n = sizeof(section_buf);
parse_state.has_section = 0;
trim_str("", trimmed_buf);
while (fgets(buf, MAX_LINECHARS, stream) != NULL) {
trim_str(buf, trimmed_buf);
if (!parse_str(settings, trimmed_buf, &parse_state)) {
return NULL;
}
}
return settings;
}
@ -165,12 +178,15 @@ int settings_save(const Settings *settings, FILE *stream)
if (settings == NULL) {
return 0;
}
if (stream == NULL) {
return 0;
}
section = settings->sections;
n = settings->section_count;
i = 0;
while (i < n) {
sprintf(buf, "[%s]\n", section->name);
fputs(buf, stream);
@ -179,6 +195,7 @@ int settings_save(const Settings *settings, FILE *stream)
i++;
fputs("\n", stream);
}
return 0;
}
@ -189,10 +206,13 @@ int settings_get(const Settings *settings, const char *section, const char *key,
if (settings == NULL) {
return 0;
}
s = get_section(settings->sections, settings->section_count, section);
if (s == NULL) {
return 0;
}
return sm_get(s->map, key, out_buf, n_out_buf);
}
@ -203,6 +223,7 @@ int settings_get_int(const Settings *settings, const char *section, const char *
if (get_converted_value(settings, section, key, CONVERT_MODE_INT, &i)) {
return i;
}
return 0;
}
@ -213,6 +234,7 @@ long settings_get_long(const Settings *settings, const char *section, const char
if (get_converted_value(settings, section, key, CONVERT_MODE_LONG, &l)) {
return l;
}
return 0;
}
@ -223,6 +245,7 @@ double settings_get_double(const Settings *settings, const char *section, const
if (get_converted_value(settings, section, key, CONVERT_MODE_DOUBLE, &d)) {
return d;
}
return 0;
}
@ -248,36 +271,47 @@ int settings_set(Settings *settings, const char *section, const char *key, const
if (settings == NULL) {
return 0;
}
if (section == NULL || key == NULL || value == NULL) {
return 0;
}
if (strlen(section) == 0) {
return 0;
}
/* Get a pointer to the section */
s = get_section(settings->sections, settings->section_count, section);
if (s == NULL) {
/* The section is not created---create it */
s = (Section*)realloc(settings->sections, (settings->section_count + 1) * sizeof(Section));
if (s == NULL) {
return 0;
}
settings->sections = s;
settings->section_count++;
s = &(settings->sections[settings->section_count - 1]);
s->map = sm_new(DEFAULT_STRMAP_CAPACITY);
if (s->map == NULL) {
free(s);
return 0;
}
s->name = (char*)malloc((strlen(section) + 1) * sizeof(char));
if (s->name == NULL) {
sm_delete(s->map);
free(s);
return 0;
}
strcpy(s->name, section);
}
return sm_put(s->map, key, value);
}
@ -288,10 +322,13 @@ int settings_section_get_count(const Settings *settings, const char *section)
if (settings == NULL) {
return 0;
}
sect = get_section(settings->sections, settings->section_count, section);
if (sect == NULL) {
return 0;
}
return sm_get_count(sect->map);
}
@ -300,9 +337,11 @@ int settings_section_enum(const Settings *settings, const char *section, setting
Section *sect;
sect = get_section(settings->sections, settings->section_count, section);
if (sect == NULL) {
return 0;
}
return sm_enum(sect->map, enum_func, obj);
}
@ -318,19 +357,24 @@ static void trim_str(const char *str, char *out_buf)
while (*str != '\0' && is_blank_char(*str)) {
str++;
}
s0 = str;
len = 0;
while (*str != '\0') {
len++;
str++;
}
if (len > 0) {
str--;
}
while (is_blank_char(*str)) {
str--;
len--;
}
memcpy(out_buf, s0, len);
out_buf[len] = '\0';
}
@ -355,39 +399,54 @@ static int parse_str(Settings *settings, char *str, ParseState *parse_state)
if (*str == '\0') {
return 1;
} else if (is_blank_str(str)) {
return 1;
} else if (is_comment_str(str)) {
return 1;
} else if (is_section_str(str)) {
result = get_section_from_str(str, buf, sizeof(buf));
if (!result) {
return 0;
}
if (strlen(buf) + 1 > parse_state->current_section_n) {
return 0;
}
strcpy(parse_state->current_section, buf);
parse_state->has_section = 1;
return 1;
} else if (is_key_value_str(str)) {
result = get_key_value_from_str(str, buf1, sizeof(buf1), buf2, sizeof(buf2));
if (!result) {
return 0;
}
if (!parse_state->has_section) {
return 0;
}
return settings_set(settings, parse_state->current_section, buf1, buf2);
} else if (is_key_without_value_str(str)) {
result = get_key_without_value_from_str(str, buf, sizeof(buf));
if (!result) {
return 0;
}
if (!parse_state->has_section) {
return 0;
}
return settings_set(settings, parse_state->current_section, buf, "");
} else {
return 0;
}
@ -410,8 +469,10 @@ static int is_blank_str(const char *str)
if (!is_blank_char(*str)) {
return 0;
}
str++;
}
return 1;
}
@ -426,6 +487,7 @@ static int is_comment_str(const char *str)
*/
return 1;
}
return 0;
}
@ -438,13 +500,16 @@ static int is_section_str(const char *str)
/* The first character must be the section start character */
return 0;
}
while (*str != '\0' && *str != SECTION_END_CHAR) {
str++;
}
if (*str != SECTION_END_CHAR) {
/* The section end character must be present somewhere thereafter */
return 0;
}
return 1;
}
@ -457,13 +522,16 @@ static int is_key_value_str(const char *str)
/* It is illegal to start with the key-value separator */
return 0;
}
while (*str != '\0' && *str != KEY_VALUE_SEPARATOR_CHAR) {
str++;
}
if (*str != KEY_VALUE_SEPARATOR_CHAR) {
/* The key-value separator must be present after the key part */
return 0;
}
return 1;
}
@ -476,13 +544,16 @@ static int is_key_without_value_str(const char *str)
/* It is illegal to start with the key-value separator */
return 0;
}
while (*str != '\0' && *str != KEY_VALUE_SEPARATOR_CHAR) {
str++;
}
if (*str == KEY_VALUE_SEPARATOR_CHAR) {
/* The key-value separator must not be present after the key part */
return 0;
}
return 1;
}
@ -497,20 +568,24 @@ static int get_section_from_str(const char *str, char *out_buf, unsigned int out
count = 0;
/* Jump past the section begin character */
str++;
while (*str != '\0' && *str != SECTION_END_CHAR) {
/* Read in the section name into the output buffer */
if (count == out_buf_n) {
return 0;
}
*out_buf = *str;
out_buf++;
str++;
count++;
}
/* Terminate the output buffer */
if (count == out_buf_n) {
return 0;
}
*out_buf = '\0';
return 1;
}
@ -526,6 +601,7 @@ static int get_key_value_from_str(const char *str, char *out_buf1, unsigned int
count1 = 0;
count2 = 0;
/* Read the key value from the input string and write it sequentially
* to the first output buffer by walking the input string until we either hit
* the null-terminator or the key-value separator.
@ -535,34 +611,42 @@ static int get_key_value_from_str(const char *str, char *out_buf1, unsigned int
if (count1 == out_buf1_n) {
return 0;
}
/* Copy the character to the first output buffer */
*out_buf1 = *str;
out_buf1++;
str++;
count1++;
}
/* Terminate the first output buffer */
if (count1 == out_buf1_n) {
return 0;
}
*out_buf1 = '\0';
/* Now trace the first input buffer backwards until we hit a non-blank character */
while (is_blank_char(*(out_buf1 - 1))) {
out_buf1--;
}
*out_buf1 = '\0';
/* Try to proceed one more character, past the last read key-value
* delimiter, in the input string.
*/
if (*str != '\0') {
str++;
}
/* Now find start of the value in the input string by walking the input
* string until we either hit the null-terminator or a blank character.
*/
while (*str != '\0' && is_blank_char(*str)) {
str++;
}
while (*str != '\0') {
/* Fail if there is a possibility that we are overwriting the second
* input buffer.
@ -570,16 +654,19 @@ static int get_key_value_from_str(const char *str, char *out_buf1, unsigned int
if (count2 == out_buf2_n) {
return 0;
}
/* Copy the character to the second output buffer */
*out_buf2 = *str;
out_buf2++;
str++;
count2++;
}
/* Terminate the second output buffer */
if (count2 == out_buf2_n) {
return 0;
}
*out_buf2 = '\0';
return 1;
}
@ -593,6 +680,7 @@ static int get_key_without_value_from_str(const char *str, char *out_buf, unsign
unsigned int count;
count = 0;
/* Now read the key value from the input string and write it sequentially
* to the output buffer by walking the input string until we either hit
* the null-terminator or the key-value separator.
@ -602,16 +690,19 @@ static int get_key_without_value_from_str(const char *str, char *out_buf, unsign
if (count == out_buf_n) {
return 0;
}
/* Copy the character to the input buffer */
*out_buf = *str;
out_buf++;
str++;
count++;
}
/* Terminate the output buffer */
if (count == out_buf_n) {
return 0;
}
*out_buf = '\0';
return 1;
}
@ -638,6 +729,7 @@ static const char * get_token(char *str, char delim, char **last)
char *s0;
s0 = str;
/* If we hit the null-terminator the string
* is exhausted and another token does not
* exist.
@ -645,17 +737,20 @@ static const char * get_token(char *str, char delim, char **last)
if (*str == '\0') {
return NULL;
}
/* Walk the string until we encounter a
* null-terminator or the delimiter.
*/
while (*str != '\0' && *str != delim) {
str++;
}
/* Terminate the return token, if necessary */
if (*str != '\0') {
*str = '\0';
str++;
}
*last = str;
return s0;
}
@ -673,6 +768,7 @@ static int get_converted_value(const Settings *settings, const char *section, co
if (!settings_get(settings, section, key, value, MAX_VALUECHARS)) {
return 0;
}
switch (mode) {
case CONVERT_MODE_INT:
*((int *)out) = atoi(value);
@ -684,6 +780,7 @@ static int get_converted_value(const Settings *settings, const char *section, co
*((double *)out) = atof(value);
return 1;
}
return 0;
}
@ -704,14 +801,18 @@ static int get_converted_tuple(const Settings *settings, const char *section, co
if (out == NULL) {
return 0;
}
if (n_out == 0) {
return 0;
}
if (!settings_get(settings, section, key, value, MAX_VALUECHARS)) {
return 0;
}
v = value;
count = 0;
/* Walk over all tokens in the value, and convert them and assign them
* to the output array as specified by the mode.
*/
@ -729,8 +830,10 @@ static int get_converted_tuple(const Settings *settings, const char *section, co
default:
return 0;
}
count++;
}
return 1;
}
@ -745,15 +848,19 @@ static Section * get_section(Section *sections, unsigned int n, const char *name
if (name == NULL) {
return NULL;
}
section = sections;
i = 0;
while (i < n) {
if (strcmp(section->name, name) == 0) {
return section;
}
section++;
i++;
}
return NULL;
}
@ -769,10 +876,13 @@ static void enum_map(const char *key, const char *value, const void *obj)
if (key == NULL || value == NULL) {
return;
}
if (obj == NULL) {
return;
}
stream = (FILE *)obj;
if (strlen(key) < MAX_KEYCHARS && strlen(value) < MAX_VALUECHARS) {
sprintf(buf, "%s%c%s\n", key, KEY_VALUE_SEPARATOR_CHAR, value);
fputs(buf, stream);

View file

@ -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;
}