Sisyphus repository
Last update: 1 october 2023 | SRPMs: 18631 | Visits: 37535147
en ru br
ALT Linux repos
S:0.6-alt0_0_git_b3c1f91
5.0: 0.4.2.3-alt1
4.1: 0.4.2.3-alt1
4.0: 0.4.1-alt0.1

Group :: System/Kernel and hardware
RPM: hardinfo

 Main   Changelog   Spec   Patches   Sources   Download   Gear   Bugs and FR  Repocop 

Patch: 05-fix-sensors-output.patch
Download


--- a/arch/linux/common/sensors.h	2009-04-06 17:43:15.000000000 +0400
+++ b/arch/linux/common/sensors.h	2013-09-16 23:57:42.000000000 +0400
@@ -15,242 +15,457 @@
  *    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;
-static GHashTable *sensor_labels = NULL;
-static GHashTable *sensor_compute = 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 read_sensor_labels(gchar * driver)
-{
-    FILE *conf;
-    gchar buf[256], *line, *p;
-    gboolean lock = FALSE;
+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;
-
-    sensor_labels = g_hash_table_new_full(g_str_hash, g_str_equal,
-					  g_free, g_free);
-    sensor_compute = g_hash_table_new(g_str_hash, g_str_equal);
-
-    /* Try to open lm-sensors config file sensors3.conf */
     conf = fopen("/etc/sensors3.conf", "r");
-
-    /* If it fails, try to open sensors.conf */
-    if (!conf) conf = fopen("/etc/sensors.conf", "r");
-
-    if (!conf) {
+    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;
-    }
-
-    while (fgets(buf, 256, conf)) {
-	line = buf;
-
-	remove_linefeed(line);
-	strend(line, '#');
-
-	if (*line == '\0') {
-	    continue;
-	} else if (lock && strstr(line, "label")) {	/* label lines */
-	    gchar **names = g_strsplit(strstr(line, "label") + 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);
-	    g_hash_table_insert(sensor_labels, name, value);
-
-	    g_strfreev(names);
-	} else if (lock && strstr(line, "ignore")) {	/* ignore lines */
-	    p = strstr(line, "ignore") + 6;
-	    if (!strchr(p, ' '))
-		continue;
-
-	    while (*p == ' ')
-		p++;
-	    g_hash_table_insert(sensor_labels, g_strdup(p), "ignore");
-	} else if (lock && strstr(line, "compute")) {	/* compute lines */
-	    gchar **formulas =
-		g_strsplit(strstr(line, "compute") + 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);
-	    }
-
-	    g_strfreev(formulas);
-	    g_hash_table_insert(sensor_compute, name,
-				math_string_to_postfix(formula));
-	} else if (g_str_has_prefix(line, "chip")) {	/* chip lines (delimiter) */
-	    if (lock == FALSE) {
-		gchar **chips = g_strsplit(line, " ", 0);
-
-		for (i = 1; chips[i]; i++) {
-		    strend(chips[i], '*');
-
-                     if (g_str_has_prefix(chips[i] + 1, driver)) {
-			lock = TRUE;
-			break;
-		    }
-		}
-
-		g_strfreev(chips);
-	    } else {
-		break;
-	    }
+        }
+	// 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 interst.
+			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);
 	}
-    }
-
-    fclose(conf);
-}
-
-static gchar *get_sensor_label(gchar * sensor)
-{
-    gchar *ret;
-
-    ret = g_hash_table_lookup(sensor_labels, sensor);
-    if (!ret)
-	ret = g_strdup(sensor);
-    else
-	ret = g_strdup(ret);
-
-    return ret;
-}
-
-static float adjust_sensor(gchar * name, float value)
-{
-    GSList *postfix;
-
-    postfix = g_hash_table_lookup(sensor_compute, name);
-    if (!postfix)
-	return value;
-
-    return math_postfix_eval(postfix, value);
-}
-
-
 static void read_sensors_hwmon(void)
-{
-    int hwmon, count;
-    gchar *path_hwmon, *path_sensor, *tmp, *driver, *name, *mon;
-    hwmon = 0;
-
-    path_hwmon = g_strdup_printf("/sys/class/hwmon/hwmon%d/device/", hwmon);
-    while (g_file_test(path_hwmon, G_FILE_TEST_EXISTS)) {
-	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;
-
-	if (!sensor_labels) {
-	    read_sensor_labels(driver);
-	}
-
-	sensors = g_strconcat(sensors, "[Cooling Fans]\n", NULL);
-	for (count = 1;; 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);
-		break;
-	    }
-
-	    mon = g_strdup_printf("fan%d", count);
-	    name = get_sensor_label(mon);
-	    if (!g_str_equal(name, "ignore")) {
-		sensors = h_strdup_cprintf("%s=%.0fRPM\n",
-					  sensors, name,
-					  adjust_sensor(mon, atof(tmp)));
-	    }
-
-	    g_free(name);
-	    g_free(mon);
-	    g_free(tmp);
-	    g_free(path_sensor);
-	}
-
-	sensors = g_strconcat(sensors, "[Temperatures]\n", NULL);
-	for (count = 1;; 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);
-		break;
-	    }
-
-	    mon = g_strdup_printf("temp%d", count);
-	    name = get_sensor_label(mon);
-	    if (!g_str_equal(name, "ignore")) {
-		sensors = h_strdup_cprintf("%s=%.2f\302\260C\n",
-					  sensors, name,
-					  adjust_sensor(mon,
-							atof(tmp) /
-							1000.0));
-	    }
-
-	    g_free(tmp);
-	    g_free(name);
-	    g_free(path_sensor);
-	    g_free(mon);
-	}
-
-	sensors = g_strconcat(sensors, "[Voltage Values]\n", NULL);
-	for (count = 0;; 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);
-		break;
-	    }
-
-
-	    mon = g_strdup_printf("in%d", count);
-	    name = get_sensor_label(mon);
-	    if (!g_str_equal(name, "ignore")) {
-		sensors = h_strdup_cprintf("%s=%.3fV\n",
-					  sensors, name,
-					  adjust_sensor(mon,
-							atof(tmp) /
-							1000.0));
-	    }
-
-	    g_free(tmp);
-	    g_free(mon);
-	    g_free(name);
-	    g_free(path_sensor);
+	{
+	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
+		// beyon 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();
 	}
 
-	g_free(path_hwmon);
-	g_free(driver);
-	path_hwmon =
-	    g_strdup_printf("/sys/class/hwmon/hwmon%d/device/", ++hwmon);
-    }
-
-    g_free(path_hwmon);
-
-}
 
 static void read_sensors_acpi(void)
 {
@@ -364,10 +579,8 @@
 static void __scan_sensors(void)
 {
     if (sensors)
-	g_free(sensors);
-
+		g_free(sensors);
     sensors = g_strdup("");
-
     read_sensors_hwmon();
     read_sensors_acpi();
     read_sensors_omnibook();
 
design & coding: Vladimir Lettiev aka crux © 2004-2005, Andrew Avramenko aka liks © 2007-2008
current maintainer: Michael Shigorin