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

Revision 5572, 5.1 KB (checked in by khali, 5 years ago)

Don't bail out on transient errors (#2330).

  • 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 periodically logs sensor information to syslog.
5 *
6 * Copyright (c) 1999-2002 Merlin Hughes <merlin@merlin.org>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU General Public 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, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <errno.h>
26#include <limits.h>
27#include <string.h>
28#include <signal.h>
29#include <syslog.h>
30#include <unistd.h>
31#include <time.h>
32#include <sys/types.h>
33#include <sys/stat.h>
34
35#include "sensord.h"
36
37static int logOpened = 0;
38
39static volatile sig_atomic_t done = 0;
40
41#define LOG_BUFFER 4096
42
43#include <stdarg.h>
44
45void
46sensorLog
47(int priority, const char *fmt, ...) {
48  static char buffer[1 + LOG_BUFFER];
49  va_list ap;
50  va_start (ap, fmt);
51  vsnprintf (buffer, LOG_BUFFER, fmt, ap);
52  buffer[LOG_BUFFER] = '\0';
53  va_end (ap);
54  if (debug || (priority < LOG_DEBUG)) {
55    if (logOpened) {
56      syslog (priority, "%s", buffer);
57    } else {
58      fprintf (stderr, "%s\n", buffer);
59      fflush (stderr);
60    }
61  }
62}
63
64static void
65signalHandler
66(int sig) {
67  signal (sig, signalHandler);
68  switch (sig) {
69    case SIGTERM:
70      done = 1;
71      break;
72  }
73}
74
75static int
76sensord
77(void) {
78  int ret = 0;
79  int scanValue = 0, logValue = 0;
80  /*
81   * First RRD update at next RRD timeslot to prevent failures due
82   * one timeslot updated twice on restart for example.
83   */
84  int rrdValue = rrdTime - time(NULL) % rrdTime;
85
86  sensorLog (LOG_INFO, "sensord started");
87
88  while (!done) {
89    ret = reloadLib ();
90    if (ret)
91      sensorLog (LOG_NOTICE, "config reload error (%d)", ret);
92    if (scanTime && (scanValue <= 0)) {
93      if ((ret = scanChips ()))
94        sensorLog (LOG_NOTICE, "sensor scan error (%d)", ret);
95      scanValue += scanTime;
96    }
97    if (logTime && (logValue <= 0)) {
98      if ((ret = readChips ()))
99        sensorLog (LOG_NOTICE, "sensor read error (%d)", ret);
100      logValue += logTime;
101    }
102    if (rrdTime && rrdFile && (rrdValue <= 0)) {
103      if ((ret = rrdUpdate ()))
104        sensorLog (LOG_NOTICE, "rrd update error (%d)", ret);
105      /*
106       * The amount of time to wait is computed using the same method as
107       * in RRD instead of simply adding the interval.
108       */
109      rrdValue = rrdTime - time(NULL) % rrdTime;
110    }
111    if (!done) {
112      int a = logTime ? logValue : INT_MAX;
113      int b = scanTime ? scanValue : INT_MAX;
114      int c = (rrdTime && rrdFile) ? rrdValue : INT_MAX;
115      int sleepTime = (a < b) ? ((a < c) ? a : c) : ((b < c) ? b : c);
116      sleep (sleepTime);
117      scanValue -= sleepTime;
118      logValue -= sleepTime;
119      rrdValue -= sleepTime;
120    }
121  }
122
123  sensorLog (LOG_INFO, "sensord stopped");
124
125  return ret;
126}
127
128static void
129openLog
130(void) {
131  openlog ("sensord", 0, syslogFacility);
132  logOpened = 1; 
133}
134
135static void
136daemonize
137(void) {
138  int pid;
139  struct stat fileStat;
140  FILE *file;
141
142  if (chdir ("/") < 0) {
143    perror ("chdir()");
144    exit (EXIT_FAILURE);
145  }
146
147  if (!(stat (pidFile, &fileStat)) &&
148      ((!S_ISREG (fileStat.st_mode)) || (fileStat.st_size > 11))) {
149    fprintf (stderr, "Error: PID file `%s' already exists and looks suspicious.\n", pidFile);
150    exit (EXIT_FAILURE);
151  }
152 
153  if (!(file = fopen (pidFile, "w"))) {
154    fprintf (stderr, "fopen(\"%s\"): %s\n", pidFile, strerror (errno));
155    exit (EXIT_FAILURE);
156  }
157 
158  /* I should use sigaction but... */
159  if (signal (SIGTERM, signalHandler) == SIG_ERR) {
160    perror ("signal(SIGTERM)");
161    exit (EXIT_FAILURE);
162  }
163
164  if ((pid = fork ()) == -1) {
165    perror ("fork()");
166    exit (EXIT_FAILURE);
167  } else if (pid != 0) {
168    fprintf (file, "%d\n", pid);
169    fclose (file);
170    unloadLib ();
171    exit (EXIT_SUCCESS);
172  }
173
174  if (setsid () < 0) {
175    perror ("setsid()");
176    exit (EXIT_FAILURE);
177  }
178
179  fclose (file);
180  close (STDIN_FILENO);
181  close (STDOUT_FILENO);
182  close (STDERR_FILENO);
183}
184
185static void 
186undaemonize
187(void) {
188  unlink (pidFile);
189  closelog ();
190}
191
192int
193main
194(int argc, char **argv) {
195  int ret = 0;
196 
197  if (parseArgs (argc, argv) ||
198      parseChips (argc, argv))
199    exit (EXIT_FAILURE);
200 
201  if (initLib () ||
202      loadLib ())
203    exit (EXIT_FAILURE);
204
205  if (isDaemon)
206    openLog ();
207  if (rrdFile)
208    ret = rrdInit ();
209 
210  if (ret) {
211  } else if (doCGI) {
212    ret = rrdCGI ();
213  } else if (isDaemon) {
214    daemonize ();
215    ret = sensord ();
216    undaemonize ();
217  } else {
218    if (doSet)
219      ret = setChips ();
220    else if (doScan)
221      ret = scanChips ();
222    else if (rrdFile)
223      ret = rrdUpdate ();
224    else
225      ret = readChips ();
226  }
227 
228  if (unloadLib ())
229    exit (EXIT_FAILURE);
230 
231  return ret;
232}
Note: See TracBrowser for help on using the browser.