1 /* GKrellM 2 | Copyright (C) 1999-2019 Bill Wilson 3 | 4 | Author: Bill Wilson billw@gkrellm.net 5 | Latest versions might be found at: http://gkrellm.net 6 | 7 | 8 | GKrellM is free software: you can redistribute it and/or modify it 9 | under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | GKrellM is distributed in the hope that it will be useful, but WITHOUT 14 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 15 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 16 | License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this program. If not, see http://www.gnu.org/licenses/ 20 | 21 | 22 | Additional permission under GNU GPL version 3 section 7 23 | 24 | If you modify this program, or any covered work, by linking or 25 | combining it with the OpenSSL project's OpenSSL library (or a 26 | modified version of that library), containing parts covered by 27 | the terms of the OpenSSL or SSLeay licenses, you are granted 28 | additional permission to convey the resulting work. 29 | Corresponding Source for a non-source form of such a combination 30 | shall include the source code for the parts of OpenSSL used as well 31 | as that of the covered work. 32 */ 33 34 35 36 /* A system dependent interface can include this file to get sensors 37 | from daemons that can run under different operating systems. 38 */ 39 40 #define SENSORS_COMMON 1 41 42 /* --------------- Interface to mbmon daemon sensor reading --------- 43 */ 44 typedef struct 45 { 46 gchar *name; 47 gfloat value; 48 } 49 MbmonSensor; 50 51 static GList *mbmon_list; 52 53 static gchar gkrellm_decimal_point, 54 mbmon_decimal_point; 55 static gboolean mbmon_need_decimal_point_fix; 56 57 static gboolean (*mbmon_check_func)(); 58 59 static gboolean 60 mbmon_decimal_point_fix(gchar *buf) 61 { 62 gchar *s; 63 64 for (s = buf; *s; ++s) 65 if (*s == mbmon_decimal_point) 66 { 67 *s = gkrellm_decimal_point; 68 return TRUE; 69 } 70 return FALSE; 71 } 72 73 static gboolean 74 mbmon_decimal_point_check(gchar *buf) 75 { 76 struct lconv *lc; 77 gchar *s; 78 79 lc = localeconv(); 80 gkrellm_decimal_point = *lc->decimal_point; 81 82 mbmon_decimal_point = (gkrellm_decimal_point == ',' ? '.' : ','); 83 84 s = g_strdup(buf); 85 if (mbmon_decimal_point_fix(s)) 86 { 87 mbmon_need_decimal_point_fix = TRUE; 88 gkrellm_debug(DEBUG_SENSORS, "mbmon_need_decimal_point_fix: %c -> %c\n", 89 mbmon_decimal_point, gkrellm_decimal_point); 90 } 91 g_free(s); 92 93 return mbmon_need_decimal_point_fix;; 94 } 95 96 static MbmonSensor * 97 mbmon_lookup(gchar *name) 98 { 99 GList *list; 100 MbmonSensor *mb; 101 102 for (list = mbmon_list; list; list = list->next) 103 { 104 mb = (MbmonSensor *) list->data; 105 if (!strcmp(name, mb->name)) 106 return mb; 107 } 108 return NULL; 109 } 110 111 /* Read sensor data from the mbmon daemon, which must be run with the 112 | -r option and no -f option: mbmon -r -P port 113 | and 'port' must be configured in the sensors config. 114 | With '-r' mbmon output will be: 115 | TEMP0 : 37.0 116 | TEMP1 : 35.5 117 | TEMP2 : 43.0 118 | FAN0 : 1704 119 | FAN1 : 2220 120 | FAN2 : 2057 121 | VC0 : +1.71 122 | VC1 : +2.51 123 | V33 : +3.22 124 | V50P : +4.87 125 | V12P : +11.80 126 | V12N : -12.12 127 | V50N : -5.25 128 */ 129 static gboolean 130 mbmon_daemon_read(void) 131 { 132 gchar *server = "127.0.0.1"; 133 MbmonSensor *mb; 134 gchar *default_label, *id_name; 135 gchar name[32], buf[256]; 136 gfloat value; 137 gint fd, n, type; 138 gboolean result = FALSE; 139 static GString *mbmon_gstring; 140 static gboolean decimal_point_check_done; 141 142 if ((fd = gkrellm_connect_to(server, _GK.mbmon_port)) < 0) 143 { 144 gkrellm_debug(DEBUG_SENSORS, 145 "mbmon_daemon_read: can't connect to %s:%d.\n", server, 146 _GK.mbmon_port); 147 return FALSE; 148 } 149 150 if (!mbmon_gstring) 151 mbmon_gstring = g_string_new(""); 152 mbmon_gstring = g_string_truncate(mbmon_gstring, 0); 153 154 while ((n = read(fd, buf, sizeof(buf) - 1)) > 0) 155 { 156 buf[n] = '\0'; 157 mbmon_gstring = g_string_append(mbmon_gstring, buf); 158 } 159 close(fd); 160 161 gkrellm_debug(DEBUG_SENSORS, "mbmon_daemon_read:\n%s\n", mbmon_gstring->str); 162 163 while (gkrellm_getline_from_gstring(&mbmon_gstring, buf, sizeof(buf))) 164 { 165 if (mbmon_need_decimal_point_fix) 166 mbmon_decimal_point_fix(buf); 167 if ( sscanf(buf, "%31s : %f", name, &value) != 2 168 || value == 0.0 /* Sensor not available */ 169 ) 170 continue; 171 if (name[0] == 'T') 172 type = SENSOR_TEMPERATURE; 173 else if (name[0] == 'F') 174 type = SENSOR_FAN; 175 else if (name[0] == 'V') 176 type = SENSOR_VOLTAGE; 177 else 178 continue; 179 180 if ( !decimal_point_check_done 181 && (type == SENSOR_TEMPERATURE || type == SENSOR_VOLTAGE) 182 ) 183 { 184 mbmon_decimal_point_check(buf); 185 decimal_point_check_done = TRUE; 186 } 187 188 if ((mb = mbmon_lookup(name)) == NULL) 189 { 190 mb = g_new0(MbmonSensor, 1); 191 mbmon_list = g_list_append(mbmon_list, mb); 192 mb->name = g_strdup(name); 193 default_label = name; 194 id_name = g_strdup_printf("mbmon/%s", name); 195 gkrellm_sensors_add_sensor(type, 196 name, id_name, 197 0, 0, MBMON_INTERFACE, 198 1.0, 0.0, NULL, default_label); 199 g_free(id_name); 200 } 201 mb->value = value; /* Assume centigrade, mbmon gives no units */ 202 result = TRUE; 203 } 204 return result; 205 } 206 207 208 gboolean 209 gkrellm_sys_sensors_mbmon_check(gboolean force) 210 { 211 GList *list; 212 MbmonSensor *mb; 213 gboolean result = TRUE; 214 static gint port; 215 static gint check_time = -1; 216 static gboolean tmp; 217 218 mbmon_check_func = gkrellm_sys_sensors_mbmon_check; 219 220 if (port > 0 && port != _GK.mbmon_port) 221 { 222 for (list = mbmon_list; list; list = list->next) 223 { 224 mb = (MbmonSensor *) list->data; 225 g_free(mb->name); 226 } 227 gkrellm_free_glist_and_data(&mbmon_list); 228 } 229 if (_GK.mbmon_port <= 0) 230 return FALSE; 231 port = _GK.mbmon_port; 232 if (check_time < _GK.time_now || force) 233 { 234 /* The first mbmon_daemon_read can set need_decimal_point_fix in 235 | which case don't update check_time so the mbmon daemon will be 236 | read again immediately at next call to this function. The first 237 | call of this function should be made from gkrellm_sys_sensors_init() 238 | function where we just want to get the sensors loaded into 239 | sensors.c and we don't actually use the mbmon sensor values. 240 */ 241 tmp = mbmon_need_decimal_point_fix; 242 result = mbmon_daemon_read(); 243 if (tmp == mbmon_need_decimal_point_fix) 244 check_time = _GK.time_now + 3; /* Interval < sensor update */ 245 } 246 return result; 247 } 248 249 250 gboolean 251 gkrellm_sys_sensors_mbmon_get_value(gchar *name, gfloat *value) 252 { 253 MbmonSensor *mb; 254 255 if ((mb = mbmon_lookup(name)) != NULL) 256 { 257 *value = mb->value; 258 return TRUE; 259 } 260 return FALSE; 261 } 262 263 264 265 /* --------------- Interface to hddtemp daemon sensor reading --------- 266 */ 267 /* Use hddtemp default port. Should make this configurable. 268 */ 269 #define HDDTEMP_PORT 7634 270 271 typedef struct 272 { 273 gchar *device; 274 gfloat value; 275 gchar unit; 276 } 277 HddtempSensor; 278 279 static GList *hddtemp_list; 280 281 static HddtempSensor * 282 hddtemp_lookup(gchar *device) 283 { 284 GList *list; 285 HddtempSensor *hdd; 286 287 for (list = hddtemp_list; list; list = list->next) 288 { 289 hdd = (HddtempSensor *) list->data; 290 if (!strcmp(device, hdd->device)) 291 return hdd; 292 } 293 return NULL; 294 } 295 296 /* Read output from the hddtemp daemon which must have been started in 297 | daemon mode: hddtemp -d /dev/hda /dev/hdb ... 298 | And example hddtemp output will be: 299 | 300 | |/dev/hda|SAMSUNG SP1614N|30|C||/dev/hdc|SAMSUNG SP1614N|30|C| 301 | 302 */ 303 static gboolean 304 hddtemp_daemon_read(void) 305 { 306 gchar *server = "127.0.0.1"; 307 gpointer sr; 308 HddtempSensor *hdd; 309 gchar **argv, **info, *id_name, *default_label; 310 gchar buf[256], sep; 311 gint fd, n, j; 312 static GString *hddtemp_gstring; 313 gboolean result = FALSE; 314 315 if ((fd = gkrellm_connect_to(server, HDDTEMP_PORT)) < 0) 316 { 317 gkrellm_debug(DEBUG_SENSORS, 318 "hddtemp_daemon_read: can't connect to %s:%d.\n", server, 319 HDDTEMP_PORT); 320 return FALSE; 321 } 322 323 if (!hddtemp_gstring) 324 hddtemp_gstring = g_string_new(""); 325 hddtemp_gstring = g_string_truncate(hddtemp_gstring, 0); 326 327 while ((n = read(fd, buf, sizeof(buf) - 1)) > 0) 328 { 329 buf[n] = '\0'; 330 hddtemp_gstring = g_string_append(hddtemp_gstring, buf); 331 } 332 close(fd); 333 334 gkrellm_debug(DEBUG_SENSORS, "hddtemp_daemon_read (once a minute):\n\t%s\n", 335 hddtemp_gstring->str); 336 337 sep = hddtemp_gstring->str[0]; 338 if (sep == '\0') 339 return FALSE; 340 sprintf(buf, "%c%c", sep, sep); 341 342 argv = g_strsplit(hddtemp_gstring->str + 1, buf, 20); 343 buf[1] = '\0'; 344 for (n = 0; argv[n] != NULL; ++n) 345 { 346 info = g_strsplit(argv[n], buf, 4); 347 for (j = 0; info[j] != NULL; ++j) 348 ; 349 if (j < 4) 350 { 351 g_strfreev(info); 352 continue; 353 } 354 if ((hdd = hddtemp_lookup(info[0])) == NULL) 355 { 356 hdd = g_new0(HddtempSensor, 1); 357 hddtemp_list = g_list_append(hddtemp_list, hdd); 358 hdd->device = g_strdup(info[0]); 359 default_label = strrchr(hdd->device, '/'); 360 if (default_label) 361 ++default_label; 362 else 363 default_label = hdd->device; 364 id_name = g_strdup_printf("hddtemp/%s", default_label); 365 sr = gkrellm_sensors_add_sensor(SENSOR_TEMPERATURE, 366 hdd->device, id_name, 367 0, 0, HDDTEMP_INTERFACE, 368 1.0, 0.0, NULL, default_label); 369 gkrellm_sensors_set_group(sr, SENSOR_GROUP_DISK); 370 g_free(id_name); 371 } 372 hdd->value = atof(info[2]); 373 if (*info[3] == 'F') 374 hdd->value = (hdd->value - 32.0) / 1.8; 375 g_strfreev(info); 376 result = TRUE; 377 } 378 g_strfreev(argv); 379 return result; 380 } 381 382 void 383 gkrellm_sys_sensors_hddtemp_check(void) 384 { 385 static gint check_time = -1; 386 387 /* hddtemp docs say shouldn't check more than once per minute. 388 */ 389 if (check_time < _GK.time_now) 390 { 391 hddtemp_daemon_read(); 392 check_time = _GK.time_now + 60; 393 } 394 } 395 396 gboolean 397 gkrellm_sys_sensors_hddtemp_get_value(gchar *name, gfloat *value) 398 { 399 HddtempSensor *hdd; 400 401 if ((hdd = hddtemp_lookup(name)) != NULL) 402 { 403 *value = hdd->value; 404 return TRUE; 405 } 406 return FALSE; 407 } 408 409