2015-03-16 09:00:32 +00:00
// vim:ts=4:sw=4:expandtab
2019-01-23 07:56:40 +00:00
# include <config.h>
2009-10-11 20:11:09 +00:00
# include <stdlib.h>
# include <limits.h>
2016-03-20 10:47:56 +00:00
# include <glob.h>
2009-10-11 20:11:09 +00:00
# include <stdio.h>
# include <string.h>
2012-03-25 18:55:55 +00:00
# include <yajl/yajl_gen.h>
2012-04-08 12:05:47 +00:00
# include <yajl/yajl_version.h>
2009-10-11 20:11:09 +00:00
# include "i3status.h"
2020-02-18 15:48:49 +00:00
# define STRING_SIZE 20
2014-08-04 14:54:08 +00:00
# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2009-10-11 20:11:09 +00:00
# include <err.h>
# include <sys/types.h>
# include <sys/sysctl.h>
2017-02-01 19:28:01 +00:00
# define TZ_ZEROC 2731
2015-03-16 09:00:32 +00:00
# define TZ_KELVTOC(x) (((x)-TZ_ZEROC) / 10), abs(((x)-TZ_ZEROC) % 10)
# define TZ_AVG(x) ((x)-TZ_ZEROC) / 10
2009-10-11 20:11:09 +00:00
# endif
2014-08-04 14:54:08 +00:00
# if defined(__DragonFly__)
# include <sys/sysctl.h>
# include <sys/types.h>
# include <sys/sensors.h>
# define MUKTOC(v) ((v - 273150000) / 1000000.0)
# endif
2012-04-29 14:59:39 +00:00
# if defined(__OpenBSD__)
# include <sys/param.h>
# include <sys/types.h>
# include <sys/sysctl.h>
# include <sys/sensors.h>
# include <errno.h>
# include <err.h>
2012-10-10 07:57:32 +00:00
# define MUKTOC(v) ((v - 273150000) / 1000000.0)
2012-04-29 14:59:39 +00:00
# endif
2013-10-06 21:18:53 +00:00
# if defined(__NetBSD__)
# include <fcntl.h>
# include <prop/proplib.h>
# include <sys/envsys.h>
# define MUKTOC(v) ((v - 273150000) / 1000000.0)
# endif
2016-11-14 20:10:19 +00:00
typedef struct temperature_s {
double raw_value ;
char formatted_value [ 20 ] ;
} temperature_t ;
# define ERROR_CODE 1
static int read_temperature ( char * thermal_zone , temperature_t * temperature ) {
2019-01-23 07:56:40 +00:00
# if defined(__linux__)
2016-11-14 20:10:19 +00:00
static char buf [ 16 ] ;
long int temp ;
if ( ! slurp ( thermal_zone , buf , sizeof ( buf ) ) )
return ERROR_CODE ;
temp = strtol ( buf , NULL , 10 ) ;
temperature - > raw_value = temp / 1000 ;
if ( temp = = LONG_MIN | | temp = = LONG_MAX | | temp < = 0 )
strcpy ( temperature - > formatted_value , " ? " ) ;
else
sprintf ( temperature - > formatted_value , " %ld " , ( temp / 1000 ) ) ;
# elif defined(__DragonFly__)
struct sensor th_sensor ;
size_t th_sensorlen ;
th_sensorlen = sizeof ( th_sensor ) ;
if ( sysctlbyname ( thermal_zone , & th_sensor , & th_sensorlen , NULL , 0 ) = = - 1 ) {
perror ( " sysctlbyname " ) ;
return ERROR_CODE ;
}
temperature - > raw_value = MUKTOC ( th_sensor . value ) ;
sprintf ( temperature - > formatted_value , " %.2f " , MUKTOC ( th_sensor . value ) ) ;
# elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
int sysctl_rslt ;
size_t sysctl_size = sizeof ( sysctl_rslt ) ;
if ( sysctlbyname ( thermal_zone , & sysctl_rslt , & sysctl_size , NULL , 0 ) )
return ERROR_CODE ;
temperature - > raw_value = TZ_AVG ( sysctl_rslt ) ;
sprintf ( temperature - > formatted_value , " %d.%d " , TZ_KELVTOC ( sysctl_rslt ) ) ;
# elif defined(__OpenBSD__)
struct sensordev sensordev ;
struct sensor sensor ;
size_t sdlen , slen ;
int dev , numt , mib [ 5 ] = { CTL_HW , HW_SENSORS , 0 , 0 , 0 } ;
sdlen = sizeof ( sensordev ) ;
slen = sizeof ( sensor ) ;
for ( dev = 0 ; ; dev + + ) {
mib [ 2 ] = dev ;
if ( sysctl ( mib , 3 , & sensordev , & sdlen , NULL , 0 ) = = - 1 ) {
if ( errno = = ENXIO )
continue ;
if ( errno = = ENOENT )
break ;
return ERROR_CODE ;
}
/* 'path' is the node within the full path (defaults to acpitz0). */
if ( BEGINS_WITH ( sensordev . xname , thermal_zone ) ) {
mib [ 3 ] = SENSOR_TEMP ;
2018-04-06 17:54:12 +00:00
/* Limit to temp0, but should retrieve from a full path... */
2016-11-14 20:10:19 +00:00
for ( numt = 0 ; numt < 1 /*sensordev.maxnumt[SENSOR_TEMP]*/ ; numt + + ) {
mib [ 4 ] = numt ;
if ( sysctl ( mib , 5 , & sensor , & slen , NULL , 0 ) = = - 1 ) {
if ( errno ! = ENOENT ) {
warn ( " sysctl " ) ;
continue ;
}
}
temperature - > raw_value = MUKTOC ( sensor . value ) ;
sprintf ( temperature - > formatted_value , " %.2f " , MUKTOC ( sensor . value ) ) ;
}
}
}
# elif defined(__NetBSD__)
int fd , rval ;
bool err = false ;
prop_dictionary_t dict ;
prop_array_t array ;
prop_object_iterator_t iter ;
prop_object_iterator_t iter2 ;
prop_object_t obj , obj2 , obj3 ;
fd = open ( " /dev/sysmon " , O_RDONLY ) ;
if ( fd = = - 1 )
return ERROR_CODE ;
rval = prop_dictionary_recv_ioctl ( fd , ENVSYS_GETDICTIONARY , & dict ) ;
if ( rval = = - 1 ) {
err = true ;
goto error_netbsd1 ;
}
/* No drivers registered? */
if ( prop_dictionary_count ( dict ) = = 0 ) {
err = true ;
goto error_netbsd2 ;
}
iter = prop_dictionary_iterator ( dict ) ;
if ( iter = = NULL ) {
err = true ;
goto error_netbsd2 ;
}
/* iterate over the dictionary returned by the kernel */
while ( ( obj = prop_object_iterator_next ( iter ) ) ! = NULL ) {
/* skip this dict if it's not what we're looking for */
if ( ( strlen ( prop_dictionary_keysym_cstring_nocopy ( obj ) ) ! = strlen ( thermal_zone ) ) | |
( strncmp ( thermal_zone ,
prop_dictionary_keysym_cstring_nocopy ( obj ) ,
strlen ( thermal_zone ) ) ! = 0 ) )
continue ;
array = prop_dictionary_get_keysym ( dict , obj ) ;
if ( prop_object_type ( array ) ! = PROP_TYPE_ARRAY ) {
err = true ;
goto error_netbsd3 ;
}
iter2 = prop_array_iterator ( array ) ;
if ( ! iter2 ) {
err = true ;
goto error_netbsd3 ;
}
/* iterate over array of dicts specific to target sensor */
while ( ( obj2 = prop_object_iterator_next ( iter2 ) ) ! = NULL ) {
obj3 = prop_dictionary_get ( obj2 , " cur-value " ) ;
float temp = MUKTOC ( prop_number_integer_value ( obj3 ) ) ;
temperature - > raw_value = temp ;
sprintf ( temperature - > formatted_value , " %.2f " , temp ) ;
break ;
}
prop_object_iterator_release ( iter2 ) ;
}
error_netbsd3 :
prop_object_iterator_release ( iter ) ;
error_netbsd2 :
prop_object_release ( dict ) ;
error_netbsd1 :
close ( fd ) ;
if ( err )
return ERROR_CODE ;
# endif
return 0 ;
}
2009-10-11 20:11:09 +00:00
/*
2014-02-25 19:43:48 +00:00
* Reads the CPU temperature from / sys / class / thermal / thermal_zone % d / temp ( or
2018-04-06 17:54:12 +00:00
* the user provided path ) and returns the temperature in degree celsius .
2009-10-11 20:11:09 +00:00
*
*/
2021-11-02 20:33:08 +00:00
void print_cpu_temperature_info ( cpu_temperature_ctx_t * ctx ) {
char * outwalk = ctx - > buf ;
2011-07-24 21:17:34 +00:00
# ifdef THERMAL_ZONE
2021-11-02 20:33:08 +00:00
const char * selected_format = ctx - > format ;
2015-03-16 09:00:32 +00:00
bool colorful_output = false ;
char * thermal_zone ;
2016-11-14 20:10:19 +00:00
temperature_t temperature ;
2018-04-06 17:54:12 +00:00
temperature . raw_value = 0 ;
sprintf ( temperature . formatted_value , " %.2f " , 0.0 ) ;
2009-10-11 20:11:09 +00:00
2021-11-02 20:33:08 +00:00
if ( ctx - > path = = NULL )
asprintf ( & thermal_zone , THERMAL_ZONE , ctx - > zone ) ;
2016-03-20 10:47:56 +00:00
else {
static glob_t globbuf ;
2021-11-02 20:33:08 +00:00
if ( glob ( ctx - > path , GLOB_NOCHECK | GLOB_TILDE , NULL , & globbuf ) ! = 0 )
2016-03-20 10:47:56 +00:00
die ( " glob() failed \n " ) ;
if ( globbuf . gl_pathc = = 0 ) {
/* No glob matches, the specified path does not contain a wildcard. */
2021-11-02 20:33:08 +00:00
asprintf ( & thermal_zone , ctx - > path , ctx - > zone ) ;
2016-03-20 10:47:56 +00:00
} else {
/* glob matched, we take the first match and ignore the others */
asprintf ( & thermal_zone , " %s " , globbuf . gl_pathv [ 0 ] ) ;
}
globfree ( & globbuf ) ;
}
2009-10-11 20:11:09 +00:00
2015-03-16 09:00:32 +00:00
INSTANCE ( thermal_zone ) ;
2012-02-16 23:29:29 +00:00
2016-11-14 20:10:19 +00:00
if ( read_temperature ( thermal_zone , & temperature ) ! = 0 )
goto error ;
2021-11-02 20:33:08 +00:00
if ( temperature . raw_value > = ctx - > max_threshold ) {
2016-11-14 20:10:19 +00:00
START_COLOR ( " color_bad " ) ;
colorful_output = true ;
2021-11-02 20:33:08 +00:00
if ( ctx - > format_above_threshold ! = NULL )
selected_format = ctx - > format_above_threshold ;
2016-11-14 20:10:19 +00:00
}
2020-02-18 15:48:49 +00:00
char string_degrees [ STRING_SIZE ] ;
snprintf ( string_degrees , STRING_SIZE , " %s " , temperature . formatted_value ) ;
placeholder_t placeholders [ ] = {
{ . name = " %degrees " , . value = string_degrees } } ;
2018-06-02 00:32:25 +00:00
2020-02-18 15:48:49 +00:00
const size_t num = sizeof ( placeholders ) / sizeof ( placeholder_t ) ;
2021-11-02 20:33:08 +00:00
char * formatted = format_placeholders ( selected_format , & placeholders [ 0 ] , num ) ;
OUTPUT_FORMATTED ;
free ( formatted ) ;
2014-02-25 19:43:48 +00:00
2016-11-14 20:10:19 +00:00
if ( colorful_output ) {
END_COLOR ;
colorful_output = false ;
}
2015-03-16 09:00:32 +00:00
free ( thermal_zone ) ;
2014-02-25 19:43:48 +00:00
2021-11-02 20:33:08 +00:00
OUTPUT_FULL_TEXT ( ctx - > buf ) ;
2015-03-16 09:00:32 +00:00
return ;
2011-08-25 21:24:06 +00:00
error :
2015-03-16 09:00:32 +00:00
free ( thermal_zone ) ;
2015-06-10 17:03:29 +00:00
# endif
2014-02-25 19:43:48 +00:00
2015-06-13 03:08:12 +00:00
OUTPUT_FULL_TEXT ( " can't read temp " ) ;
2015-03-16 09:00:32 +00:00
( void ) fputs ( " i3status: Cannot read temperature. Verify that you have a thermal zone in /sys/class/thermal or disable the cpu_temperature module in your i3status config. \n " , stderr ) ;
2009-10-11 20:11:09 +00:00
}