~mmach/netext73/lm-sensors

« back to all changes in this revision

Viewing changes to prog/sensord/sensord.c

  • Committer: mmach
  • Date: 2020-02-05 20:28:34 UTC
  • Revision ID: netbit73@gmail.com-20200205202834-zc3sla47j9e700w5
3.6

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
39
static int logOpened = 0;
 
40
 
 
41
static volatile sig_atomic_t done = 0;
 
42
static volatile sig_atomic_t reload = 0;
 
43
 
 
44
#define LOG_BUFFER 4096
 
45
 
 
46
#include <stdarg.h>
 
47
 
 
48
void 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
 
 
66
static 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
 
 
78
static 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
 
 
143
static void openLog(void)
 
144
{
 
145
        openlog("sensord", 0, sensord_args.syslogFacility);
 
146
        logOpened = 1;
 
147
}
 
148
 
 
149
static 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
 
 
174
static 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
 
 
208
                freeChips();
 
209
                if (unloadLib())
 
210
                        exit(EXIT_FAILURE);
 
211
 
 
212
                exit(EXIT_SUCCESS);
 
213
        }
 
214
 
 
215
        if (setsid() < 0) {
 
216
                perror("setsid()");
 
217
                exit(EXIT_FAILURE);
 
218
        }
 
219
 
 
220
        fclose(file);
 
221
        close(STDIN_FILENO);
 
222
        close(STDOUT_FILENO);
 
223
        close(STDERR_FILENO);
 
224
}
 
225
 
 
226
static void undaemonize(void)
 
227
{
 
228
        unlink(sensord_args.pidFile);
 
229
        closelog();
 
230
}
 
231
 
 
232
int main(int argc, char **argv)
 
233
{
 
234
        int ret = 0;
 
235
 
 
236
        if (parseArgs(argc, argv) ||
 
237
            parseChips(argc, argv))
 
238
                exit(EXIT_FAILURE);
 
239
 
 
240
        if (loadLib(sensord_args.cfgFile)) {
 
241
                freeChips();
 
242
                exit(EXIT_FAILURE);
 
243
        }
 
244
 
 
245
        if (!sensord_args.doCGI)
 
246
                openLog();
 
247
 
 
248
        if (sensord_args.rrdFile) {
 
249
                ret = rrdInit();
 
250
                if (ret) {
 
251
                        freeChips();
 
252
                        exit(EXIT_FAILURE);
 
253
                }
 
254
        }
 
255
 
 
256
        if (sensord_args.doCGI) {
 
257
                ret = rrdCGI();
 
258
        } else {
 
259
                daemonize();
 
260
                ret = sensord();
 
261
                undaemonize();
 
262
        }
 
263
 
 
264
        freeChips();
 
265
        if (unloadLib())
 
266
                exit(EXIT_FAILURE);
 
267
 
 
268
        return ret;
 
269
}