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

Revision 5723, 5.5 KB (checked in by andy, 4 years ago)

Replace the deprecated signal() function by sigaction().

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