root/lm-sensors/trunk/prog/sensord/sensord.c @ 732

Revision 732, 9.2 KB (checked in by mds, 14 years ago)

(mds) -Wall cleanup.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2 * sensord
3 *
4 * A daemon that logs all sensor information to /var/log/sensors
5 * every 5 minutes.
6 *
7 * Copyright (c) 1999 Merlin Hughes <merlin@merlin.org>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27#include <signal.h>
28#include <fcntl.h>
29#include <errno.h>
30#include <dirent.h>
31#include <unistd.h>
32#include <syslog.h>
33#include <sys/types.h>
34#include <sys/time.h>
35#include <sys/wait.h>
36#include <sys/stat.h>
37
38#include "lib/sensors.h"
39
40#include "sensord.h"
41
42static const char *version = "0.2.0";
43
44static const char *sensorsCfgPaths[] = {
45  "/etc", "/usr/lib/sensors", "/usr/local/lib/sensors", "/usr/lib", "/usr/local/lib", NULL
46};
47static const char *sensorsCfgFile = "sensors.conf";
48static const char *sensorsLogFile = "/var/log/sensors";
49static int sleepTime = 5 * 60;
50
51static int cfgLoaded = 0;
52time_t cfgLastModified;
53
54static FILE *sensorsLog = NULL;
55
56static volatile sig_atomic_t done = 0;
57static volatile sig_atomic_t rotate = 0;
58
59static void
60signalHandler
61(int sig) {
62  signal (sig, signalHandler);
63  switch (sig) {
64    case SIGHUP:
65      rotate = 1;
66      break;
67    case SIGTERM:
68      done = 1;
69      break;
70  }
71}
72
73static void
74initSignals
75(void) {
76  /* I should use sigaction but... */
77  signal (SIGHUP, signalHandler);
78  signal (SIGTERM, signalHandler);
79}
80
81static char *
82nowf
83(void) {
84  time_t now;
85  char *str;
86  int len;
87  static char buff[1024];
88
89  time (&now);
90  str = ctime (&now);
91  len = strlen (str);
92  memcpy (buff, str, len - 1);
93  buff[len - 1] = '\0';
94
95  return buff;
96}
97
98static int
99readUnknownChip
100(const sensors_chip_name *chip) {
101  const sensors_feature_data *sensor;
102  int index0 = 0, index1 = 0;
103  int ret = 0;
104
105  while (!done && (ret == 0) && ((sensor = sensors_get_all_features (*chip, &index0, &index1)) != NULL)) {
106    char *label = NULL;
107    double value;
108   
109    if (sensors_get_label (*chip, sensor->number, &label)) {
110      syslog (LOG_ERR, "Error getting sensor label: %s/%s", chip->prefix, sensor->name);
111      ret = 20;
112    } else if (!(sensor->mode & SENSORS_MODE_R)) {
113      fprintf (sensorsLog, "\t%s: %s\n", sensor->name, label);
114    } else if (sensors_get_feature (*chip, sensor->number, &value)) {
115      syslog (LOG_ERR, "Error getting sensor data: %s/%s", chip->prefix, sensor->name);
116      ret = 21;
117    } else {
118      fprintf (sensorsLog, "\t%s%s: %s: %.2f\n", (sensor->mapping == SENSORS_NO_MAPPING) ? "" : "-", sensor->name, label, value);
119    }
120    if (label)
121      free (label);
122  }
123 
124  return ret;
125}
126
127static int
128readKnownChip
129(const sensors_chip_name *chip, ChipDescriptor *descriptor) {
130  FeatureDescriptor *features = descriptor->features;
131  int index0, subindex;
132  int ret = 0;
133
134  for (index0 = 0; !done && (ret == 0) && features[index0].format; ++ index0) {
135    FeatureDescriptor *feature = features + index0;
136    char *label = NULL;
137    double values[MAX_DATA];
138   
139    if (sensors_get_label (*chip, feature->labelNumber, &label)) {
140      syslog (LOG_ERR, "Error getting sensor label: %s/#%d", chip->prefix, feature->labelNumber);
141      ret = 20;
142    }
143    for (subindex = 0; !done && (ret == 0) && (feature->dataNumbers[subindex] >= 0); ++ subindex) {
144      if (sensors_get_feature (*chip, feature->dataNumbers[subindex], values + subindex)) {
145        syslog (LOG_ERR, "Error getting sensor data: %s/#%d", chip->prefix, feature->dataNumbers[subindex]);
146        ret = 21;
147      }
148    }
149    if (!done && (ret == 0))
150      fprintf (sensorsLog, "\t%s: %s\n"/*, sensor->name*/, label, feature->format (values));
151    if (label)
152      free (label);
153  }
154  return ret;
155}
156
157static int
158readChip
159(const sensors_chip_name *chip) {
160  const char *adapter, *algorithm;
161  int index0, subindex, chipindex = -1;
162  int ret = 0;
163
164  if (chip->bus == SENSORS_CHIP_NAME_BUS_ISA)
165    fprintf (sensorsLog, "%s: Chip: %s-isa-%04x\n", nowf(), chip->prefix, chip->addr);
166  else
167    fprintf (sensorsLog, "%s: Chip: %s-i2c-%d-%02x\n", nowf(), chip->prefix, chip->bus, chip->addr);
168  adapter = sensors_get_adapter_name (chip->bus);
169  if (adapter)
170    fprintf (sensorsLog, "%s: Adapter: %s\n", nowf(), adapter);
171  algorithm = sensors_get_algorithm_name (chip->bus);
172  if (algorithm)
173    fprintf (sensorsLog, "%s: Algorithm: %s\n", nowf(), algorithm);
174  /* assert adapter || algorithm */
175
176  for (index0 = 0; knownChips[index0].names; ++ index0)
177    for (subindex = 0; knownChips[index0].names[subindex]; ++ subindex)
178      if (!strcmp (chip->prefix, knownChips[index0].names[subindex]))
179        chipindex = index0;
180 
181  if (chipindex >= 0)
182    ret = readKnownChip (chip, knownChips + chipindex);
183  else
184    ret = readUnknownChip (chip);
185
186  return ret;
187}
188
189static int
190readChips
191(void) {
192  const sensors_chip_name *chip;
193  int index0 = 0;
194  int ret = 0;
195
196  fprintf (sensorsLog, "%s: Sense.\n", nowf());
197  fflush (sensorsLog);
198
199  while (!done && (ret == 0) && ((chip = sensors_get_detected_chips (&index0)) != NULL)) {
200    ret = readChip (chip);
201  }
202
203  fprintf (sensorsLog, "%s: Done.\n", nowf());
204  fflush (sensorsLog);
205
206  return ret;
207}
208
209static int
210rotateLog
211(void) {
212  int ret = 0;
213
214  if (sensorsLog != NULL) {
215    fprintf (sensorsLog, "%s: Rotate.\n", nowf());
216    fclose (sensorsLog);
217  }
218  if (!(sensorsLog = fopen (sensorsLogFile, "a"))) {
219    syslog (LOG_ERR, "Error opening sensors log: %s", sensorsLogFile);
220    ret = 1;
221  } else {
222    fprintf (sensorsLog, "%s: Started.\n", nowf());
223    fflush (sensorsLog);
224  }
225  rotate = 0;
226
227  return ret;
228}
229
230char cfgPath[4096] = "";
231
232static int
233initSensors
234(void) {
235  struct stat stats;
236  FILE *cfg = NULL;
237  int ret = 0;
238
239  if (!cfgPath[0]) {
240    if (sensorsCfgFile[0] == '/') {
241      strcpy (cfgPath, sensorsCfgFile);
242    } else {
243      int index0;
244      for (index0 = 0; sensorsCfgPaths[index0]; ++ index0) {
245        sprintf (cfgPath, "%s/%s", sensorsCfgPaths[index0], sensorsCfgFile);
246        if (stat (cfgPath, &stats) == 0)
247          break;
248      }
249      if (!sensorsCfgPaths[index0]) {
250        syslog (LOG_ERR, "Error locating sensors configuration: %s", sensorsCfgFile);
251        return 9;
252      }
253    }
254  }
255   
256  if (stat (cfgPath, &stats) < 0) {
257    syslog (LOG_ERR, "Error stating sensors configuration: %s", cfgPath);
258    ret = 10;
259  } else if (!cfgLoaded || (difftime (stats.st_mtime, cfgLastModified) > 0.0)) {
260    if (!(cfg = fopen (cfgPath, "r"))) {
261      syslog (LOG_ERR, "Error opening sensors configuration: %s", cfgPath);
262      ret = 11;
263    } else if (sensors_init (cfg)) {
264      syslog (LOG_ERR, "Error loading sensors configuration: %s", cfgPath);
265      ret = 11;
266    } else {
267      cfgLastModified = stats.st_mtime;
268      cfgLoaded = 1;
269    }
270    if (cfg)
271      fclose (cfg);
272  }
273
274  return ret;
275}
276
277static int
278sensord
279(void) {
280  int ret = 0;
281
282  openlog ("sensord", 0, LOG_DAEMON);
283 
284  initSignals ();
285
286  while (!done && (ret == 0)) {
287    if (rotate || (sensorsLog == NULL))
288      ret = rotateLog ();
289    if (ret == 0)
290      ret = initSensors ();
291    if (ret == 0)
292      ret = readChips ();
293    if (!done && !rotate && (ret == 0))
294      sleep (sleepTime);
295  }
296
297  if (cfgLoaded)
298    sensors_cleanup ();
299
300  if (sensorsLog) {
301    fprintf (sensorsLog, "%s: %s.\n", nowf(), ret ? "Failed" : "Stopped");
302    fclose (sensorsLog);
303  }
304
305  closelog ();
306
307  return ret;
308}
309
310static void
311syntaxError
312(void) {
313  printf ("Syntax: sensord [options]\n"
314          "\t-i <interval>     -- seconds between samples (default 300)\n"
315          "\t-l <log-file>     -- log file (default /var/log/sensors)\n"
316          "\t-c <config-file>  -- configuration file (default /etc/sensors.conf)\n"
317          "\t-v                -- display version and exit\n"
318          "\t-h                -- display help and exit\n");
319  exit (EXIT_FAILURE);
320}
321
322static void
323parseArgs
324(int argc, char **argv) {
325  int i;
326
327  for (i = 1; i < argc; ++ i) {
328    if (!strcmp (argv[i], "-i") && (i < argc - 1)) {
329      sleepTime = atoi (argv[++ i]);
330    } else if (!strcmp (argv[i], "-l") && (i < argc - 1)) {
331      sensorsLogFile = argv[++ i];
332    } else if (!strcmp (argv[i], "-c") && (i < argc - 1)) {
333      sensorsCfgFile = argv[++ i];
334    } else if (!strcmp (argv[i], "-v")) {
335      printf ("sensord version %s\n", version);
336      exit (EXIT_SUCCESS);
337    } else {
338      syntaxError ();
339    }
340  }
341}
342
343static void
344daemonize
345(void) {
346  int pid;
347
348  if ((pid = fork ()) == -1) {
349    fprintf (stderr, "Error forking daemon\n");
350    exit (EXIT_FAILURE);
351  } else if (pid != 0) {
352    exit (EXIT_SUCCESS);
353  }
354
355  if (chdir ("/") < 0) {
356    perror ("chdir()");
357    exit (EXIT_FAILURE);
358  }
359
360  if (setsid () < 0) {
361    perror ("setsid()");
362    exit (EXIT_FAILURE);
363  }
364
365  close (STDIN_FILENO);
366  close (STDOUT_FILENO);
367  close (STDERR_FILENO);
368}
369
370int
371main
372(int argc, char **argv) {
373  parseArgs (argc, argv);
374  daemonize ();
375  return sensord ();
376}
Note: See TracBrowser for help on using the browser.