Hello, guest. We have noticed that you are not registered at this bug tracker. Your experience will be greatly enhanced if you log in. To do so, you first must register by clicking on the Register tab at the top. If you are already registered, you can login at the Login tab.
Syndicate Syndicate Listing Display Search Login/Register
Bug Id ?
Reporter ?
Leo Smith
Product/Version ?
HardInfo / 0.5.1
Status ?
Unconfirmed
Severity ?
Moderate
Duplicate Of ?
- none -
Summary ?
hwmon module fails to parse sensors3.conf correctly - 2 issues
Report Time ?
February 20, 2013 01:38:49 PM
Assignment ?
- none -
Resolution ?
Open
Priority ?
Normal
Dependencies ?
- none -


Attachments
sensors3.conf sensors3.conf
sensors.h new sensors.h
Votes
For: 0 (0%)
Against: 0 (0%)
Total: 0

February 20, 2013 01:38:49 PM Leo Smith
System:

$uname -ar
Linux othello-mint 3.2.0-37-generic #58-Ubuntu SMP Thu Jan 24 15:28:10 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux

$hardinfo -v
HardInfo version 0.5.1
Copyright (C) 2003-2009 Leandro A. F. Pereira. See COPYING for details.

Compile-time options:
Release version: Yes (ARCH_x86_64)
BinReloc enabled: Yes
Data prefix: /usr/share/hardinfo/
Library prefix: /usr/lib/hardinfo/
Compiled on: Linux 3.2.0-37-generic (othello-mint)
Modules:
File Name Name Version
computer.so Computer 0.5.1
devices.so Devices 0.5.1
network.so Network 0.5.1
benchmark.so Benchmarks 0.5.1
============================================================================
Problem:
Hardinfo fails to correctly parse the file /etc/sensors3.conf and/or crashes when it does.
Problem #1:
sensors.h contains code to look at multiple drivers - in my case coretemp and w83267ehf - but only invokes the code to parse sensors3.conf once.

Viz although two drivers are invoked, once the variable 'sensor_labels' is initialised, no further invocations of read_sensor_lables occur.

----------------------------------------------------------------------------
if (!sensor_labels) // this seems wrong: only will invoke one pass.
{
read_sensor_labels(driver);
}
---------------------------------------------------------------------------
In my case coretemp is the driver that it invokes, but there are limited entries for coretemp so this has little or no effect. The coretemp temperature values are not picked up by the code at all.
Instead the values for w83267ehf are correctly detected but the results are never parsed using sensors3.conf

If I patch the code by setting hwmon to an initial value of 1, in read_sensors_hwmon(void), it does invoke the file passing w83627ehf as the driver, but the program crashes parsing the sensors3.conf file.
-----------------------------------------------------------------------
Invalid token: [,][44]
Invalid token: [,][44]
*** glibc detected *** hardinfo: munmap_chunk(): invalid pointer: 0x00007f8fbcae8060 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x7eb96)[0x7f8fc237bb96]
[.....many lines of trace...]
----------------------------------------------------------------------------------


This is an easy thing to do as the parsing software is not robust, and cannot for example cope with leading spaces on a 'chips' line definition.

To be frank, the code looks like it has been patched at some time in a hurry to deal with multiple drivers, and to use sensors3.conf but the job has not been done adequately. It doesn't correctly deal with multiple drivers and that alone hides the fact that it cant parse the conf file correctly!

I am almost capable of rewriting it, if I knew what exactly the constituents parts were supposed to be doing. I have source and its a quick compile.

Its a shame, because the other parts of the program are really excellent.

I think the things that are needed are as follows.

1/. firm up the parsing routines to make them bullet proof. I suspect that a generic filter to eliminate leading white space on all lines first would help with the 'chips' problem, and then the issue of the maths parsing crash could be handled as a second task.
2/. examine the whole logic of the way information is collected and concatenated:

Or alternatively use the lm-sensors package to sidestep all this and build the screen display from the output of that.

Best regards

Leo Smith

My sensors3.conf file is included below.
==========================================
#
chip "w83627ehf-*" "w83627dhg-*"
ignore intrusion0
ignore cpu0_vid
# == VOLTAGES ==
# Vcore
label in0 "Vcore"
set in0_min 0.85
set in0_max 1.6
# +12V
label in1 "+12V"
compute in1 @*(75/10),@/(75/10)
set in1_min 10.2
set in1_max 13.8
# unused
ignore in2
# +3.3V
label in3 "+3.3V"
# this formula is stored in the ACPI, but it seems not to work
# compute in3 @*(68/34),@/(68/34)
set in3_min 2.97
set in3_max 3.63
# unused
ignore in4
# +5V
label in5 "5V"
compute in5 @*(40/10),@/(40/10)
set in5_min 4.5
set in5_max 5.5
# unused
ignore in6
ignore in7
ignore in8
ignore in9
# == TEMPERATURES ==
# Mainboard
label temp1 "Sys Temp"
set temp1_max 95
set temp1_max_hyst 60
# CPU
label temp2 "CPU Temp"
set temp2_max 95
set temp2_max_hyst 45
# unused
ignore temp3
# == FANS ==
# If you miss a certain fan set it to ignore
# Chassis 1
ignore fan1
label fan1 "Cha1 Fan"
set fan1_min 800
# CPU
# ignore fan2
label fan2 "CPU Fan"
set fan2_min 600

# Powersupply
ignore fan3
#label fan3 "Pwr Fan"
#set fan3_min 800
# unused
ignore fan4
# Chassis 2
ignore fan5
label fan5 "Cha2 Fan"
set fan5_min 800
# == CORE TEMPERATURES ==
# This requires the coretemp patch applied
# Maximums are autodetected by the driver depending on the CPU
# Core0
chip "coretemp-*"
label temp2 "Core0 Temp"
label temp3 "Core1 Temp"

========================================
also what sensors now shows

$ sensors
coretemp-isa-0000
Adapter: ISA adapter
Core0 Temp: +59.0°C (high = +86.0°C, crit = +100.0°C)
Core1 Temp: +62.0°C (high = +86.0°C, crit = +100.0°C)

w83627dhg-isa-0290
Adapter: ISA adapter
Vcore: +1.18 V (min = +0.85 V, max = +1.60 V)
+12V: +12.12 V (min = +10.20 V, max = +13.80 V)
+3.3V: +3.28 V (min = +2.98 V, max = +3.63 V)
5V: +5.02 V (min = +4.51 V, max = +5.50 V)
CPU Fan: 2220 RPM (min = 602 RPM, div = 16)
Sys Temp: +50.0°C (high = +95.0°C, hyst = +60.0°C) sensor = diode
CPU Temp: +54.0°C (high = +95.0°C, hyst = +45.0°C) sensor = diode




February 22, 2013 02:01:37 PM Leo Smith
I have traced all the issues and rewritten sensors.h to actually function correctly in my installation.

In the end there were several issues which forced a complete rewrite of this module.

Issue 1
=======
coretemp on my system did NOT start at temp1..it started at temp2 and used temp2 and temp3.
This meant that starting at 1 and aborting if not found was an unusable algorithm. I modified the code to start at 1 and count to 20, and simply use what was found.
Issue 2
=======
Coretemp also generates files called 'label' in the same place as the rest of its device files: Thee contain a more human readable label like 'Core 0' and 'core1'.
The code is adapted to search for these and if found, store the results.
Issue 3
=======
Use of the hash table to store results as name:value pairs results in collisions between coretemp which uses the same raw names (temp2 and temp3) as the other driver. To correct this I abandoned the hash table and instead built a simple linked list of senor entry structures that store not only the name, but also the corresponding driver name. This also had the advantage that the data could be output in a way that reflects grouping by type, rather than 'in the order read'. Now coretemp data is grouped with other temperature data.
Issue 4
=======
parsing of sensors3.conf was extremely fragile. Unexpected spaces, or lack of them, could cause the algorithms to fail This has been totally rewritten as a separate pass over the linked list of data, and is - in the case of my file at least - bombproof.

The new sensors.h file is included below

I am not sure how to get this tested beyond my installation, or into the release channel as this is my first stab at adding changes to a public domain system I hope that someone can pick up this and incorporate it.
=========================================
/*
* HardInfo - Displays System Information
* Copyright (C) 2003-2006 Leandro A. F. Pereira <leandro@hardinfo.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 2.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <ctype.h>
static gchar *sensors = NULL;
// structure to hold an individual sensor entry
struct sensor_entry
{
gchar *driver;
gchar *raw_name;
gchar *label;
gchar *cooked_name;
gchar *compute_string;
int ignore_flag;
float raw_value;
float cooked_value;
struct sensor_entry *next;
};
static void remove_lf(gchar *p)
{
while(*p)
{
if(*p=='\n')
*p=0;
p++;
}
}
static struct sensor_entry *first_sensor=NULL;
/* given a driver to match, return it if matched or null if not exists */
static gchar *sensor_driver_matched(gchar* driver)
{
struct sensor_entry *p;
for(p=first_sensor;p;p=p->next) // walk through list.
{
if (g_str_has_prefix(driver,p->driver)) // if this driver matches one in the list
return (p->driver);
}
return (gchar *) 0; //reached end no match.
}
static struct sensor_entry *find_sensor_entry(gchar *driver,gchar *raw_name)
{
struct sensor_entry *p;
for(p=first_sensor;p;p=p->next) // walk through list.
{
if(strcmp(driver, p->driver) || strcmp(raw_name,p->raw_name)) // no match
continue;
else return (p); // found it!!
}
return ((struct sensor_entry *)0);
}
static void add_sensor_entry(gchar *driver, gchar *raw_name, gchar *label, float raw_value)
{
struct sensor_entry *p,*new;
if(!first_sensor) // first entry
{
new=first_sensor=g_malloc(sizeof(struct sensor_entry));
new->driver=g_strdup(driver);
new->raw_name=g_strdup(raw_name);
if(label)
new->label=g_strdup(label);
else new->label=(gchar *)0;
new->raw_value=raw_value;
// next values null..filled in later after parsing sensors3.conf.
new->ignore_flag=0;
new->cooked_name=(gchar *)0;
new->compute_string=(gchar *)0;
new->cooked_value=0.0;
new->next = (struct sensor_entry *) 0;
return;
}
// otherwise scan to the end..
for(p=first_sensor;p;p=p->next) // walk through list.
{
if(!(p->next)) //last entry
{
new=g_malloc(sizeof(struct sensor_entry));
p->next=new;
new->driver=g_strdup(driver);
new->raw_name=g_strdup(raw_name);
if(label)
new->label=g_strdup(label);
else new->label=(gchar *)0;
new->raw_value=raw_value;
// next values null..filled in later after parsing sensors3.conf.
new->ignore_flag=0;
new->cooked_name=(gchar *)0;
new->compute_string=(gchar *)0;
new->cooked_value=0.0;
new->next = (struct sensor_entry *) 0;
return;
}
}
}
static void free_sensor_entry(struct sensor_entry *p)
{
if(!p)
return; // dont free blanks!
// clear all g_malloced strings
if(p->driver) g_free(p->driver);
if(p->raw_name) g_free(p->raw_name);
if(p->label) g_free(p->label);
if(p->cooked_name) g_free(p->cooked_name);
if(p->compute_string) g_free(p->compute_string);
//free up the structure itself
g_free(p);
}
static void free_all_sensor_entries()
{
struct sensor_entry *p,*next;
for(p=first_sensor;p;) // walk through list.
{
next=p->next;
free_sensor_entry(p);
p=next;
}
first_sensor=(struct sensor_entry *) 0;
}
static void update_sensor_entry_name(gchar*driver, gchar *raw_name, gchar *cooked_name)
{
struct sensor_entry *p;
if((p=find_sensor_entry(driver,raw_name)))
{
p->cooked_name=g_strdup(cooked_name);
}
}
static void ignore_sensor_entry(gchar*driver, gchar *raw_name)
{
struct sensor_entry *p;
if((p=find_sensor_entry(driver,raw_name)))
{
p->ignore_flag=1;
}
}

static void update_sensor_entry_compute_string(gchar *driver, gchar *raw_name, gchar* compute_string)
{
struct sensor_entry *p;
if((p=find_sensor_entry(driver,raw_name)))
{
p->compute_string=g_strdup(compute_string);
p->cooked_value=math_postfix_eval(math_string_to_postfix(compute_string),p->raw_value);
}
}
/**************************************************************************************
* This scans the linked list and outputs the relevant values to the sensors string *
**************************************************************************************/
static void print_sensors (void)
{
struct sensor_entry *p;
gchar *name;
float value;
gchar *header;
// start with Fans
header="[Cooling Fans]\n";
for(p=first_sensor;p;p=p->next)
{
// skip any ignored items or that aren't fans
if((!g_ascii_strncasecmp (p->raw_name, "fan", 3)) && (p->ignore_flag==0))
{
if(p->cooked_value !=0.0)
value=p->cooked_value;
else
value=p->raw_value;
if(p->cooked_name)
name=p->cooked_name;
else if (p->label)
name=p->label;
else name=p->raw_name;
sensors=h_strdup_cprintf("%s%s=%.0fRPM\n", sensors, header,name,value);
header=""; // dont reprint the header
}
}
// Temperatures
header="[Temperatures]\n";
for(p=first_sensor;p;p=p->next)
{
// skip any ignored items or that aren't temps
if((!g_ascii_strncasecmp (p->raw_name, "temp", 4)) && (p->ignore_flag==0))
{
if(p->cooked_value !=0.0)
value=p->cooked_value;
else
value=p->raw_value;
if(p->cooked_name)
name=p->cooked_name;
else if (p->label)
name=p->label;
else name=p->raw_name;
sensors=h_strdup_cprintf("%s%s=%.0f\302\260C\n", sensors, header,name,value);
header=""; // dont reprint the header
}
}
// voltages
header="[Voltages]\n";
for(p=first_sensor;p;p=p->next)
{
// skip any ignored items or that aren't voltages
if(!(g_ascii_strncasecmp (p->raw_name, "in", 2)) && (p->ignore_flag==0))
{
if(p->cooked_value !=0.0)
value=p->cooked_value;
else
value=p->raw_value;
if(p->cooked_name)
name=p->cooked_name;
else if (p->label)
name=p->label;
else name=p->raw_name;
sensors=h_strdup_cprintf("%s%s=%.3fV\n", sensors, header,name,value);
header=""; // dont reprint the header
}
}
}
/************************************************************************************
* reads the sensors[3].conf file and updates the linked list of items accordingly *
************************************************************************************/
static void cook_sensor_values(void)
{
FILE *conf;
gchar buf[2000], *line, *driver,*p;
gchar **chips;
int flag=0;
gint i;
conf = fopen("/etc/sensors3.conf", "r");
if (!conf)
{
printf(" failed to open /etc/sensors3.conf\n");
conf = fopen("/etc/sensors.conf", "r");
}
if (!conf)
{
/* Cannot open config file. */
printf("unable to open a config file\n");
return;
}
// file now open one presumes..so scan it.
while (fgets(buf, 2000, conf))
{
line=buf;
remove_linefeed(line);
while(*line && isspace(*line)) //strip leading space.
line++;
if(*line== '#' || !(*line))
continue; // skip lines beginning with hash or whitespace and then hash or all whitespace!
// Now test for chips match. We need to know that this is a chip we have a driver for.
// if it isn't we just keep skipping till it is.
if(!g_ascii_strncasecmp (line, "chip", 4))
{
chips = g_strsplit(line, " ", 0);
for (i = 1; chips[i]; i++)
{
strend(chips[i], '*'); // remove trailing asterisk
// if we have an entry in our list of sensors whose chippery matches get the exact name of the driver
if ((driver=sensor_driver_matched(chips[i] + 1)))
{
flag=1;
break;
}
else flag=0; // reset the flag if the chips don't match.
}
// ok this line is of no further interest.
g_strfreev(chips);
continue;
}
if(!flag)
continue; // until we have a matching chip entry.
// if we got this far, we have a matching driver and some kind of valid line beyond 'chip' so all lines are of interest.
if(!g_ascii_strncasecmp (line, "label", 5)) // a label line!
{
gchar **names = g_strsplit(line+ 5, " ", 0);
gchar *name = NULL, *value = NULL;

for (i = 0; names[i]; i++)
{
if (names[i][0] == '\0')
continue;
if (!name)
name = g_strdup(names[i]);
else if (!value)
value = g_strdup(names[i]);
else
value = g_strconcat(value, " ", names[i], NULL);
}
remove_quotes(value);
update_sensor_entry_name(driver, name, value); //update the list
g_free(name);
g_free(value);
g_strfreev(names);
}
else if (!g_ascii_strncasecmp (line, "ignore", 6)) // an ignore line
{
gchar **names = g_strsplit(line + 6, " ", 0);
gchar *name = NULL;
for (i = 0; names[i]; i++)
{
if (names[i][0] == '\0')
continue;
if (!name)
name = g_strdup(names[i]);
}
ignore_sensor_entry(driver, name);
g_free(name);
g_strfreev(names);
}
else if (!g_ascii_strncasecmp (line, "compute", 7)) // a compute line
{
// replace comma with \0 as we dont want the fag end of the line
for(p=line+7;*p;p++)
{
if(*p==',')
{
*p=0;
break;
}
}
gchar **formulas = g_strsplit(line + 7, " ", 0);
gchar *name = NULL, *formula = NULL;
for (i = 0; formulas[i]; i++)
{
if (formulas[i][0] == '\0')
continue;
if (formulas[i][0] == ',')
break;
if (!name)
name = g_strdup(formulas[i]);
else if (!formula)
formula = g_strdup(formulas[i]);
else
formula = g_strconcat(formula, formulas[i], NULL);
}
update_sensor_entry_compute_string(driver, name, formula);
g_free (name);
g_free (formula);
g_strfreev(formulas);
}
}
fclose(conf);
}
static void read_sensors_hwmon(void)
{
int hwmon, count;
gchar *path_hwmon, *path_sensor, *tmp, *driver, *name, *label;
float value;
hwmon = 0;
// see what drivers we have.
path_hwmon = g_strdup_printf("/sys/class/hwmon/hwmon%d/device/", hwmon);
while( g_file_test(path_hwmon, G_FILE_TEST_EXISTS))
{
// establish the driver name i.e. coretemp or w83627ehf etc etc.
tmp = g_strdup_printf("%sdriver", path_hwmon);
driver = g_file_read_link(tmp, NULL);
g_free(tmp);
tmp = g_path_get_basename(driver);
g_free(driver);
driver = tmp;
// Now see what we have in the directory making no assumptions.
// the old sensor.h relied on temperatures and in fact everything starting at eg temp1.
// but coretemp often uses values starting with temp2...so the safest thing is to simply make no assumptions
// beyond the fact that there won't be more the 20 of anything, and simply probe.
// coretemp also has temp[n]_label as a more human readable name for the parameter.
//fans
for(count=1;count<21;count++)
{
path_sensor = g_strdup_printf("%sfan%d_input", path_hwmon, count);
if (!g_file_get_contents(path_sensor, &tmp, NULL, NULL))
{
g_free(path_sensor);
continue; // its simply not there.
}
name = g_strdup_printf("fan%d", count);
value=atof(tmp);
g_free(tmp);
path_sensor = g_strdup_printf("%sfan%d_label", path_hwmon, count);
if (g_file_get_contents(path_sensor, &tmp, NULL, NULL))
{
remove_lf(tmp);
label=g_strdup(tmp);
g_free(tmp);
}
else label=(gchar *)0;
add_sensor_entry(driver, name, label, value); // insert this sensor into the linked list
if(label)
g_free(label);
g_free(name);
g_free(path_sensor);
}
// temperatures
for(count=1;count<21;count++)
{
path_sensor = g_strdup_printf("%stemp%d_input", path_hwmon, count);
if (!g_file_get_contents(path_sensor, &tmp, NULL, NULL))
{
g_free(path_sensor);
continue; // its simply not there.
}
name = g_strdup_printf("temp%d", count);
value=(atof(tmp))/1000;
g_free(tmp);
path_sensor = g_strdup_printf("%stemp%d_label", path_hwmon, count);
if (g_file_get_contents(path_sensor, &tmp, NULL, NULL))
{
remove_lf(tmp);
label=g_strdup(tmp);
g_free(tmp);
}
else label=(gchar *)0;
add_sensor_entry(driver, name, label, value); // insert this sensor into the linked list
if(label)
g_free(label);
g_free(name);
g_free(path_sensor);
}

// and voltages
for(count=1;count<21;count++)
{
path_sensor = g_strdup_printf("%sin%d_input", path_hwmon, count);
if (!g_file_get_contents(path_sensor, &tmp, NULL, NULL))
{
g_free(path_sensor);
continue; // its simply not there.
}
name = g_strdup_printf("in%d", count);
value=(atof(tmp))/1000;
g_free(tmp);
path_sensor = g_strdup_printf("%sin%d_label", path_hwmon, count);
if (g_file_get_contents(path_sensor, &tmp, NULL, NULL))
{
remove_lf(tmp);
label=g_strdup(tmp);
g_free(tmp);
}
else label=(gchar *)0;
add_sensor_entry(driver, name, label, value); // insert this sensor into the linked list
if(label)
g_free(label);
g_free(name);
g_free(path_sensor);
}
// clear the path and the driver string
g_free(path_hwmon);
g_free(driver);
hwmon++; // try next driver
path_hwmon = g_strdup_printf("/sys/class/hwmon/hwmon%d/device/", hwmon);
}
g_free(path_hwmon); // and clear the last path..
// now to adjust the values
cook_sensor_values();
// and now print the output values to the sensors string.
print_sensors();
// destroy the linked list..
free_all_sensor_entries();
}


static void read_sensors_acpi(void)
{
const gchar *path_tz = "/proc/acpi/thermal_zone";

if (g_file_test(path_tz, G_FILE_TEST_EXISTS)) {
GDir *tz;

if ((tz = g_dir_open(path_tz, 0, NULL))) {
const gchar *entry;
gchar *temp = g_strdup("");


while ((entry = g_dir_read_name(tz))) {
gchar *path =
g_strdup_printf("%s/%s/temperature", path_tz, entry);
gchar *contents;

if (g_file_get_contents(path, &contents, NULL, NULL)) {
int temperature;

sscanf(contents, "temperature: %d C", &temperature);

temp = h_strdup_cprintf("\n%s=%d\302\260C\n",
temp, entry, temperature);

g_free(contents);
}
}

if (*temp != '\0')
sensors =
h_strdup_cprintf("\n[ACPI Thermal Zone]\n%s",
sensors, temp);

g_dir_close(tz);
}
}

}

static void read_sensors_omnibook(void)
{
const gchar *path_ob = "/proc/omnibook/temperature";
gchar *contents;

if (g_file_get_contents(path_ob, &contents, NULL, NULL)) {
int temperature;

sscanf(contents, "CPU temperature: %d C", &temperature);

sensors = h_strdup_cprintf("\n[Omnibook]\n"
"CPU temperature=%d\302\260C\n",
sensors, temperature);

g_free(contents);
}
}

static void read_sensors_hddtemp(void)
{
Socket *s;
static gchar *old = NULL;
gchar buffer[1024];
gint len = 0;

if ((s = sock_connect("127.0.0.1", 7634))) {
while (!len)
len = sock_read(s, buffer, sizeof(buffer));
sock_close(s);

if (len > 2 && buffer[0] == '|' && buffer[1] == '/') {
gchar **disks;
int i;

if (old)
g_free(old);

old = g_strdup("[Hard Disk Temperature]\n");

disks = g_strsplit(buffer, "\n", 0);
for (i = 0; disks[i]; i++) {
gchar **fields = g_strsplit(disks[i] + 1, "|", 5);

/*
* 0 -> /dev/hda
* 1 -> FUJITSU MHV2080AH
* 2 -> 41
* 3 -> C
*/
old = h_strdup_cprintf("\n%s (%s)=%s\302\260%s\n",
old,
fields[1], fields[0],
fields[2], fields[3]);

g_strfreev(fields);
}

g_strfreev(disks);
}
} else {
g_free(old);
old = NULL;
}

if (old) {
sensors = g_strconcat(sensors, "\n", old, NULL);
}
}

static void __scan_sensors(void)
{
if (sensors)
g_free(sensors);
sensors = g_strdup("");
read_sensors_hwmon();
read_sensors_acpi();
read_sensors_omnibook();
read_sensors_hddtemp();

/* FIXME: Add support for ibm acpi and more sensors */
}
==========================================================


February 22, 2013 02:04:45 PM Leo Smith
My configuration file

February 22, 2013 02:06:44 PM Leo Smith
This is the completely rewritten sensors.h

February 22, 2013 02:09:47 PM Leo Smith
Final note. I see that pasting code into the message results in deep ugliness. See attached files for the configuration and the fixed sensors.h

February 27, 2013 01:02:43 PM Leandro Pereira
Thank you for contributing!

However, since the sensors code have been rewritten, please obtain the code from the Git repository (http://github.com/lpereira/hardinfo) and submit patches/pull requests. The current sensors code has been rewritten a while ago, and there has been a lot of code reorganization since 0.5.1, so your changed file won't work properly.