xosview  1.23
About: xosview is an X Windows based system monitor (cpu, memory, swap and network usage; interrupt and serial activities; load average).
  Fossies Dox: xosview-1.23.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

lmstemp.cc
Go to the documentation of this file.
1 //
2 // Copyright (c) 2000, 2006 by Leopold Toetsch <lt@toetsch.at>
3 //
4 // Read temperature entries from /proc/sys/dev/sensors/*/*
5 // and display actual and high temperature
6 // if actual >= high, actual temp changes color to indicate alarm
7 //
8 // File based on btrymeter.* by
9 // Copyright (c) 1997 by Mike Romberg ( mike.romberg@noaa.gov )
10 //
11 // This file may be distributed under terms of the GPL
12 //
13 //
14 //
15 #include "lmstemp.h"
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <math.h>
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <dirent.h>
23 #include <iostream>
24 #include <string>
25 #include <fstream>
26 
27 static const char PROC_SENSORS[] = "/proc/sys/dev/sensors";
28 static const char SYS_SENSORS[] = "/sys/class/hwmon";
29 
30 
31 LmsTemp::LmsTemp( XOSView *parent, const char *name, const char *tempfile,
32  const char *highfile, const char *lowfile, const char *label,
33  const char *caption, unsigned int nbr )
34  : SensorFieldMeter( parent, label, caption, 1, 1, 0 ){
35  _nbr = nbr;
36  _scale = 1.0;
38 
39  // Check if high is given as value
40  if ( highfile && sscanf(highfile, "%lf", &high_) > 0 ) {
41  has_high_ = _high_found = true;
42  highfile = NULL;
43  }
44  // Check if low is given as value
45  if ( lowfile && sscanf(lowfile, "%lf", &low_) > 0 ) {
46  has_low_ = _low_found = true;
47  lowfile = NULL;
48  }
49 
50  if ( !checksensors(name, tempfile, highfile, lowfile) ) {
51  if ( !_name_found &&
52  (( !_temp_found && tempfile[0] != '/' ) ||
53  ( !_high_found && (highfile && highfile[0] != '/') ) ||
54  ( !_low_found && (lowfile && lowfile[0] != '/') )) )
55  std::cerr << label << " : No sensor named " << name << " was found in "
56  << SYS_SENSORS << "." << std::endl;
57  else {
58  if (!_temp_found && tempfile[0] != '/') {
59  std::cerr << label << " : Could not find file " << tempfile << "{,_input}";
60  if (name)
61  std::cerr << " under " << name << " in " << SYS_SENSORS;
62  else
63  std::cerr << " under " << PROC_SENSORS << " or " << SYS_SENSORS;
64  std::cerr << "." << std::endl;
65  }
66  if (!_high_found && highfile && highfile[0] != '/') {
67  std::cerr << label << " : Could not find file " << highfile;
68  if (name)
69  std::cerr << " under " << name << " in " << SYS_SENSORS;
70  else
71  std::cerr << " under " << SYS_SENSORS;
72  std::cerr << "." << std::endl;
73  }
74  if (!_low_found && lowfile && lowfile[0] != '/') {
75  std::cerr << label << " : Could not find file " << lowfile;
76  if (name)
77  std::cerr << " under " << name << " in " << SYS_SENSORS;
78  else
79  std::cerr << " under " << SYS_SENSORS;
80  std::cerr << "." << std::endl;
81  }
82  }
83  parent_->done(1);
84  }
85 }
86 
88 }
89 
90 bool LmsTemp::checksensors( const char *name, const char *tempfile,
91  const char *highfile, const char *lowfile ) {
92 // Logic:
93 // 0) tempfile must always be found, highfile and lowfile only if given
94 // 1) absolute path in any filename must match as is
95 // 2) if name is given, only files in that sysfs node can match
96 // 3) any filename matches as is
97 // 4) tempfile + "_input" matches and tempfile + "_max" and/or
98 // tempfile + "_min" matches
99  DIR *dir;
100  struct dirent *ent;
101  struct stat buf;
102  std::string dirname, f, f2, n;
103 
104  /* First, check if absolute paths were given. */
105  if (tempfile[0] == '/') {
106  if ( stat(tempfile, &buf) == 0 && S_ISREG(buf.st_mode) ) {
107  _tempfile = tempfile;
108  _temp_found = true;
109  }
110  else
111  std::cerr << title() << " : Could not find file " << tempfile << "." << std::endl;
112  }
113  if (highfile && highfile[0] == '/') {
114  if ( stat(highfile, &buf) == 0 && S_ISREG(buf.st_mode) ) {
115  _highfile = highfile;
116  _high_found = true;
117  }
118  else
119  std::cerr << title() << " : Could not find file " << highfile << "." << std::endl;
120  }
121  if (lowfile && lowfile[0] == '/') {
122  if ( stat(lowfile, &buf) == 0 && S_ISREG(buf.st_mode) ) {
123  _lowfile = lowfile;
124  _low_found = true;
125  }
126  else
127  std::cerr << title() << " : Could not find file " << lowfile << "." << std::endl;
128  }
129 
130  if ( _temp_found && (_high_found || !highfile) && (_low_found || !lowfile) ) {
131  _isproc = ( strncmp(_tempfile.c_str(), "/proc", 5) ? false : true );
132  return true;
133  }
134 
135  /* Then, try to find the given file. */
136  /* Try /proc first. */
137  if ( (dir = opendir(PROC_SENSORS)) ) {
138  while ( !_temp_found && (ent = readdir(dir)) ) {
139  if ( !strncmp(ent->d_name, ".", 1) ||
140  !strncmp(ent->d_name, "..", 2) )
141  continue;
142 
143  dirname = PROC_SENSORS;
144  dirname += '/'; dirname += ent->d_name;
145  if ( stat(dirname.c_str(), &buf) == 0 && S_ISDIR(buf.st_mode) ) {
146  f = dirname + '/' + tempfile;
147  if ( stat(f.c_str(), &buf) == 0 && S_ISREG(buf.st_mode) ) {
148  _temp_found = true;
149  _tempfile = f;
150  _isproc = true;
151  }
152  }
153  }
154  closedir(dir);
155  if (_temp_found)
156  return true;
157  }
158 
159  /* Next, try /sys. */
160  if ( !(dir = opendir(SYS_SENSORS)) )
161  return false;
162 
163  while ( !(_temp_found && (_high_found || !highfile) && (_low_found || !lowfile) ) &&
164  (ent = readdir(dir)) ) {
165  if ( !strncmp(ent->d_name, ".", 1) ||
166  !strncmp(ent->d_name, "..", 2) )
167  continue;
168 
169  // Try every node under /sys/class/hwmon
170  dirname = SYS_SENSORS;
171  dirname += '/'; dirname += ent->d_name;
172 
173  int i = 0;
174  do {
175  if ( stat(dirname.c_str(), &buf) == 0 && S_ISDIR(buf.st_mode) ) {
176  // Try to get the sensor's name
177  f = dirname + "/name";
178  std::ifstream namefile( f.c_str() );
179  if ( namefile.good() ) {
180  namefile >> n;
181  namefile.close();
182  }
183  if (!name || n == name) {
184  // Either no name was given, or the name matches.
185  // Check if the files exist here.
186  _name_found = true;
187  if (highfile && !_high_found) {
188  f = dirname + '/' + highfile;
189  if ( stat(f.c_str(), &buf) == 0 && S_ISREG(buf.st_mode) ) {
190  _high_found = true;
191  _highfile = f;
192  }
193  }
194  if (lowfile && !_low_found) {
195  f = dirname + '/' + lowfile;
196  if ( stat(f.c_str(), &buf) == 0 && S_ISREG(buf.st_mode) ) {
197  _low_found = true;
198  _lowfile = f;
199  }
200  }
201  f = dirname + '/' + tempfile;
202  if ( stat(f.c_str(), &buf) == 0 && S_ISREG(buf.st_mode) ) {
203  _temp_found = true;
204  _tempfile = f;
205  }
206  else {
207  f2 = f + "_input";
208  if ( stat(f2.c_str(), &buf) == 0 && S_ISREG(buf.st_mode) ) {
209  _temp_found = true;
210  _tempfile = f2;
211  f2 = f + "_max";
212  if ( !_high_found && !highfile &&
213  stat(f2.c_str(), &buf) == 0 && S_ISREG(buf.st_mode) ) {
214  _high_found = true;
215  _highfile = f2;
216  }
217  f2 = f + "_min";
218  if ( !_low_found && !lowfile &&
219  stat(f2.c_str(), &buf) == 0 && S_ISREG(buf.st_mode) ) {
220  _low_found = true;
221  _lowfile = f2;
222  }
223  }
224  }
225  }
226  }
227 
228  // Some /sys sensors have the files in subdirectory /device
229  dirname += "/device";
230  } while ( ++i < 2 && !( _temp_found && (_high_found || !highfile) &&
231  (_low_found || !lowfile) ) );
232  }
233  closedir(dir);
234  // No highfile or lowfile is OK.
235  if (!highfile)
236  _high_found = true;
237  if (!lowfile)
238  _low_found = true;
239 
240  return (_temp_found & _high_found & _low_found);
241 }
242 
243 /* Adapted from libsensors. */
245  char type[16], subtype[32];
246  int n;
247  std::string basename = _tempfile.substr(_tempfile.find_last_of('/') + 1);
248  if ( sscanf(basename.c_str(), "%[a-z]%d_%s", type, &n, subtype) == 3 ) {
249  if (( !strncmp(type, "in", strlen(type)) &&
250  !strncmp(subtype, "input", strlen(subtype)) ) ||
251  ( !strncmp(type, "temp", strlen(type)) &&
252  !strncmp(subtype, "input", strlen(subtype)) ) ||
253  ( !strncmp(type, "temp", strlen(type)) &&
254  !strncmp(subtype, "offset", strlen(subtype)) ) ||
255  ( !strncmp(type, "curr", strlen(type)) &&
256  !strncmp(subtype, "input", strlen(subtype)) ) ||
257  ( !strncmp(type, "power", strlen(type)) &&
258  !strncmp(subtype, "average_interval", strlen(subtype)) ) ||
259  ( !strncmp(type, "cpu", strlen(type)) &&
260  !strncmp(subtype, "vid", strlen(subtype)) )) {
261  _scale = 1000.0;
262  return;
263  }
264  if (( !strncmp(type, "power", strlen(type)) &&
265  !strncmp(subtype, "average", strlen(subtype)) ) ||
266  ( !strncmp(type, "energy", strlen(type)) &&
267  !strncmp(subtype, "input", strlen(subtype)) )) {
268  _scale = 1000000.0;
269  return;
270  }
271  }
272  _scale = 1.0;
273 }
274 
276  char type[16], subtype[32];
277  int n;
278  std::string basename = _tempfile.substr(_tempfile.find_last_of('/') + 1);
279  if ( sscanf(basename.c_str(), "%[a-z]%d_%s", type, &n, subtype) == 3 ) {
280  if ( !strncmp(type, "temp", strlen(type)) )
281  strcpy(unit_, "\260C");
282  else if ( !strncmp(type, "in", strlen(type)) ||
283  !strncmp(subtype, "vid", strlen(type)) )
284  strcpy(unit_, "V");
285  else if ( !strncmp(type, "fan", strlen(type)) )
286  strcpy(unit_, "RPM");
287  else if ( !strncmp(type, "power", strlen(type)) ) {
288  if ( strncmp(subtype, "average_interval", strlen(type)) )
289  strcpy(unit_, "s");
290  else
291  strcpy(unit_, "W");
292  }
293  else if ( !strncmp(type, "energy", strlen(type)) )
294  strcpy(unit_, "J");
295  else if ( !strncmp(type, "curr", strlen(type)) )
296  strcpy(unit_, "A");
297  else if ( !strncmp(type, "humidity", strlen(type)) )
298  strcpy(unit_, "%");
299  }
300 }
301 
304 
305  char s[32];
306  const char *tmp = NULL;
307  actcolor_ = parent_->allocColor( parent_->getResource( "lmstempActColor" ) );
308  highcolor_ = parent_->allocColor( parent_->getResource( "lmstempHighColor" ) );
309  lowcolor_ = parent_->allocColor( parent_->getResource( "lmstempLowColor" ) );
310  setfieldcolor( 0, actcolor_ );
311  setfieldcolor( 1, parent_->getResource( "lmstempIdleColor") );
313  tmp = parent_->getResourceOrUseDefault( "lmstempHighest", "0" );
314  snprintf(s, 32, "lmstempHighest%d", _nbr);
315  total_ = fabs( atof( parent_->getResourceOrUseDefault(s, tmp) ) );
316  priority_ = atoi( parent_->getResource( "lmstempPriority" ) );
317  tmp = parent_->getResource( "lmstempUsedFormat" );
318  snprintf(s, 32, "lmstempUsedFormat%d", _nbr);
320 
321  if ( !_highfile.empty() )
322  has_high_ = true;
323  if ( !_lowfile.empty() )
324  has_low_ = true;
325 
326  if (!has_high_)
327  high_ = total_;
328  if (!has_low_)
329  low_ = 0;
330 
331  determineScale();
332  determineUnit();
333  updateLegend();
334 }
335 
336 void LmsTemp::checkevent( void ){
337  getlmstemp();
338 
339  drawfields();
340 }
341 
342 void LmsTemp::getlmstemp( void ){
343  double high = high_, low = low_;
344 
345  std::ifstream tempfile( _tempfile.c_str() );
346  if (!tempfile) {
347  std::cerr << "Can not open file : " << _tempfile << std::endl;
348  parent_->done(1);
349  return;
350  }
351 
352  if (_isproc)
353  tempfile >> high >> low >> fields_[0];
354  else {
355  tempfile >> fields_[0];
356  fields_[0] /= _scale;
357  if ( !_highfile.empty() ) {
358  std::ifstream highfile( _highfile.c_str() );
359  if (!highfile) {
360  std::cerr << "Can not open file : " << _highfile << std::endl;
361  parent_->done(1);
362  return;
363  }
364  highfile >> high;
365  high /= _scale;
366  }
367  if ( !_lowfile.empty() ) {
368  std::ifstream lowfile( _lowfile.c_str() );
369  if (!lowfile) {
370  std::cerr << "Can not open file : " << _lowfile << std::endl;
371  parent_->done(1);
372  return;
373  }
374  lowfile >> low;
375  low /= _scale;
376  }
377  }
378 
379  checkFields(low, high);
380 }
double total_
Definition: fieldmeter.h:41
virtual void checkResources(void)
Definition: fieldmeter.cc:54
void setfieldcolor(int field, const char *color)
Definition: fieldmeter.cc:108
virtual void drawfields(int mandatory=0)
Definition: fieldmeter.cc:221
double * fields_
Definition: fieldmeter.h:40
void SetUsedFormat(const char *const str)
Definition: fieldmeter.cc:60
void determineScale(void)
Definition: lmstemp.cc:244
void checkResources(void)
Definition: lmstemp.cc:302
std::string _lowfile
Definition: lmstemp.h:37
bool _temp_found
Definition: lmstemp.h:40
unsigned int _nbr
Definition: lmstemp.h:38
void determineUnit(void)
Definition: lmstemp.cc:275
std::string _tempfile
Definition: lmstemp.h:37
void checkevent(void)
Definition: lmstemp.cc:336
const char * name(void) const
Definition: lmstemp.h:26
bool checksensors(const char *name, const char *tempfile, const char *highfile, const char *lowfile)
Definition: lmstemp.cc:90
bool _high_found
Definition: lmstemp.h:40
~LmsTemp(void)
Definition: lmstemp.cc:87
std::string _highfile
Definition: lmstemp.h:37
void getlmstemp(void)
Definition: lmstemp.cc:342
bool _low_found
Definition: lmstemp.h:40
double _scale
Definition: lmstemp.h:39
bool _isproc
Definition: lmstemp.h:40
LmsTemp(XOSView *parent, const char *name, const char *tempfile, const char *highfile, const char *lowfile, const char *label, const char *caption, unsigned int nbr)
Definition: lmstemp.cc:31
bool _name_found
Definition: lmstemp.h:40
int priority_
Definition: meter.h:54
const char * title(void)
Definition: meter.h:25
XOSView * parent_
Definition: meter.h:52
void checkFields(double low, double high)
void updateLegend(void)
unsigned long actcolor_
unsigned long lowcolor_
unsigned long highcolor_
unsigned long allocColor(const char *name)
Definition: xwin.cc:383
const char * getResourceOrUseDefault(const char *name, const char *defaultVal)
Definition: xwin.cc:351
int done(void)
Definition: xwin.h:29
const char * getResource(const char *name)
Definition: xwin.cc:362
static const char PROC_SENSORS[]
Definition: lmstemp.cc:27
static const char SYS_SENSORS[]
Definition: lmstemp.cc:28