root/lm-sensors/branches/lm-sensors-3.0.0/prog/sensord/sensord.c @ 4969

Revision 4969, 5.1 KB (checked in by khali, 7 years ago)

sensord: Reload config on SIGHUP rather than automatically.
Reloading the configuration on SIGHUP is common for daemons. Reloading
automatically is less efficient and can be confusing or even racy.

  • 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;
40static volatile sig_atomic_t reload = 0;
41
42#define LOG_BUFFER 4096
43
44#include <stdarg.h>
45
46void
47sensorLog
48(int priority, const char *fmt, ...) {
49  static char buffer[1 + LOG_BUFFER];
50  va_list ap;
51  va_start (ap, fmt);
52  vsnprintf (buffer, LOG_BUFFER, fmt, ap);
53  buffer[LOG_BUFFER] = '\0';
54  va_end (ap);
55  if (debug || (priority < LOG_DEBUG)) {
56    if (logOpened) {
57      syslog (priority, "%s", buffer);
58    } else {
59      fprintf (stderr, "%s\n", buffer);
60      fflush (stderr);
61    }
62  }
63}
64
65static void
66signalHandler
67(int sig) {
68  signal (sig, signalHandler);
69  switch (sig) {
70    case SIGTERM:
71      done = 1;
72      break;
73    case SIGHUP:
74      reload = 1;
75      break;
76  }
77}
78
79static int
80sensord
81(void) {
82  int ret = 0;
83  int scanValue = 0, logValue = 0;
84  /*
85   * First RRD update at next RRD timeslot to prevent failures due
86   * one timeslot updated twice on restart for example.
87   */
88  int rrdValue = rrdTime - time(NULL) % rrdTime;
89
90  sensorLog (LOG_INFO, "sensord started");
91
92  while (!done && (ret == 0)) {
93    if (reload) {
94      ret = reloadLib (sensorsCfgFile);
95      reload = 0;
96    }
97    if ((ret == 0) && scanTime) { /* should I scan on the read cycle? */
98      ret = scanChips ();
99      if (scanValue <= 0)
100        scanValue += scanTime;
101    }
102    if ((ret == 0) && logTime && (logValue <= 0)) {
103      ret = readChips ();
104      logValue += logTime;
105    }
106    if ((ret == 0) && rrdTime && rrdFile && (rrdValue <= 0)) {
107      ret = rrdUpdate ();
108      /*
109       * The amount of time to wait is computed using the same method as
110       * in RRD instead of simply adding the interval.
111       */
112      rrdValue = rrdTime - time(NULL) % rrdTime;
113    }
114    if (!done && (ret == 0)) {
115      int a = logTime ? logValue : INT_MAX;
116      int b = scanTime ? scanValue : INT_MAX;
117      int c = (rrdTime && rrdFile) ? rrdValue : INT_MAX;
118      int sleepTime = (a < b) ? ((a < c) ? a : c) : ((b < c) ? b : c);
119      sleep (sleepTime);
120      scanValue -= sleepTime;
121      logValue -= sleepTime;
122      rrdValue -= sleepTime;
123    }
124  }
125
126  if (ret)
127    sensorLog (LOG_INFO, "sensord failed (%d)", ret);
128  else
129    sensorLog (LOG_INFO, "sensord stopped");
130
131  return ret;
132}
133
134static void
135openLog
136(void) {
137  openlog ("sensord", 0, syslogFacility);
138  logOpened = 1; 
139}
140
141static void
142daemonize
143(void) {
144  int pid;
145  struct stat fileStat;
146  FILE *file;
147
148  if (chdir ("/") < 0) {
149    perror ("chdir()");
150    exit (EXIT_FAILURE);
151  }
152
153  if (!(stat (pidFile, &fileStat)) &&
154      ((!S_ISREG (fileStat.st_mode)) || (fileStat.st_size > 11))) {
155    fprintf (stderr, "Error: PID file `%s' already exists and looks suspicious.\n", pidFile);
156    exit (EXIT_FAILURE);
157  }
158 
159  if (!(file = fopen (pidFile, "w"))) {
160    fprintf (stderr, "fopen(\"%s\"): %s\n", pidFile, strerror (errno));
161    exit (EXIT_FAILURE);
162  }
163 
164  /* I should use sigaction but... */
165  if (signal (SIGTERM, signalHandler) == SIG_ERR ||
166      signal (SIGHUP, signalHandler) == SIG_ERR) {
167    perror ("signal");
168    exit (EXIT_FAILURE);
169  }
170
171  if ((pid = fork ()) == -1) {
172    perror ("fork()");
173    exit (EXIT_FAILURE);
174  } else if (pid != 0) {
175    fprintf (file, "%d\n", pid);
176    fclose (file);
177    unloadLib ();
178    exit (EXIT_SUCCESS);
179  }
180
181  if (setsid () < 0) {
182    perror ("setsid()");
183    exit (EXIT_FAILURE);
184  }
185
186  fclose (file);
187  close (STDIN_FILENO);
188  close (STDOUT_FILENO);
189  close (STDERR_FILENO);
190}
191
192static void 
193undaemonize
194(void) {
195  unlink (pidFile);
196  closelog ();
197}
198
199int
200main
201(int argc, char **argv) {
202  int ret = 0;
203 
204  if (parseArgs (argc, argv) ||
205      parseChips (argc, argv))
206    exit (EXIT_FAILURE);
207 
208  if (loadLib (sensorsCfgFile))
209    exit (EXIT_FAILURE);
210
211  if (isDaemon)
212    openLog ();
213  if (rrdFile)
214    ret = rrdInit ();
215 
216  if (ret) {
217  } else if (doCGI) {
218    ret = rrdCGI ();
219  } else if (isDaemon) {
220    daemonize ();
221    ret = sensord ();
222    undaemonize ();
223  } else {
224    if (doSet)
225      ret = setChips ();
226    else if (doScan)
227      ret = scanChips ();
228    else if (rrdFile)
229      ret = rrdUpdate ();
230    else
231      ret = readChips ();
232  }
233 
234  if (unloadLib ())
235    exit (EXIT_FAILURE);
236 
237  return ret;
238}
Note: See TracBrowser for help on using the browser.