"Fossies" - the Fresh Open Source Software Archive 
Member "vnstat-2.9/src/vnstatd.c" (23 Jan 2022, 11462 Bytes) of package /linux/misc/vnstat-2.9.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "vnstatd.c" see the
Fossies "Dox" file reference documentation and the latest
Fossies "Diffs" side-by-side code changes report:
2.8_vs_2.9.
1 /*
2 vnStat daemon - Copyright (C) 2008-2022 Teemu Toivola <tst@iki.fi>
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; version 2 dated June, 1991.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License along
14 with this program; if not, write to the Free Software Foundation, Inc.,
15 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16 */
17
18 #include "common.h"
19 #include "datacache.h"
20 #include "dbsql.h"
21 #include "cfg.h"
22 #include "ibw.h"
23 #include "id.h"
24 #include "misc.h"
25 #include "daemon.h"
26 #include "vnstatd.h"
27
28 int main(int argc, char *argv[])
29 {
30 int currentarg;
31 uint32_t previflisthash;
32 uint64_t temp;
33 DSTATE s;
34
35 initdstate(&s);
36
37 /* early check for debug and config parameter */
38 if (argc > 1) {
39 for (currentarg = 1; currentarg < argc; currentarg++) {
40 if ((strcmp(argv[currentarg], "-D") == 0) || (strcmp(argv[currentarg], "--debug") == 0)) {
41 debug = 1;
42 printf("Debug enabled, vnstatd %s\n", VERSION);
43 } else if (strcmp(argv[currentarg], "--config") == 0) {
44 if (currentarg + 1 < argc) {
45 strncpy_nt(s.cfgfile, argv[currentarg + 1], 512);
46 if (debug)
47 printf("Used config file: %s\n", s.cfgfile);
48 currentarg++;
49 } else {
50 printf("Error: File for --config missing.\n");
51 return 1;
52 }
53 }
54 }
55 }
56
57 timeused_debug("daemon_startup", 1);
58
59 /* load config if available */
60 if (!loadcfg(s.cfgfile, CT_Daemon)) {
61 return 1;
62 }
63 if (!ibwloadcfg(s.cfgfile)) {
64 return 1;
65 }
66
67 /* init config settings */
68 strncpy_nt(s.user, cfg.daemonuser, 33);
69 strncpy_nt(s.group, cfg.daemongroup, 33);
70 s.updateinterval = cfg.updateinterval;
71 s.saveinterval = cfg.saveinterval * 60;
72
73 parseargs(&s, argc, argv);
74
75 preparedirs(&s);
76
77 /* set user and/or group if requested */
78 setgroup(s.group);
79 setuser(s.user);
80
81 if (!db_open_rw(1)) {
82 printf("Error: Failed to open database \"%s/%s\" in read/write mode.\n", cfg.dbdir, DATABASEFILE);
83 printf("Exiting...\n");
84 exit(EXIT_FAILURE);
85 }
86
87 if (s.initdb) {
88 db_close();
89 if (debug) {
90 printf("--initdb complete, exiting...\n");
91 }
92 exit(EXIT_SUCCESS);
93 }
94
95 detectboot(&s);
96 preparedatabase(&s);
97
98 if (!db_removeoldentries()) {
99 printf("Error: Database \"%s/%s\" cleanup failed: %s\n", cfg.dbdir, DATABASEFILE, strerror(errno));
100 printf("Exiting...\n");
101 exit(EXIT_FAILURE);
102 }
103
104 setsignaltraps();
105
106 /* start as daemon if requested, debug can't be enabled at the same time */
107 if (s.rundaemon && !debug) {
108 if (!db_close()) {
109 printf("Error: Failed to close database \"%s/%s\" before starting daemon: %s\n", cfg.dbdir, DATABASEFILE, strerror(errno));
110 printf("Exiting...\n");
111 exit(EXIT_FAILURE);
112 }
113 noexit++;
114 daemonize();
115 if (!db_open_rw(0)) {
116 snprintf(errorstring, 1024, "Failed to reopen database \"%s/%s\": %s", cfg.dbdir, DATABASEFILE, strerror(errno));
117 printe(PT_Error);
118 exit(EXIT_FAILURE);
119 }
120 }
121
122 timeused_debug("daemon_startup", 0);
123 s.running = 1;
124
125 #if defined(__linux__) && HAVE_LINUX_RTNETLINK_H
126 #if HAVE_DECL_IFLA_STATS64
127 snprintf(errorstring, 1024, "vnStat daemon %s started. (pid:%d uid:%d gid:%d 64-bit)", getversion(), (int)getpid(), (int)getuid(), (int)getgid());
128 #else
129 snprintf(errorstring, 1024, "vnStat daemon %s started. (pid:%d uid:%d gid:%d 32-bit)", getversion(), (int)getpid(), (int)getuid(), (int)getgid());
130 #endif
131 #else
132 snprintf(errorstring, 1024, "vnStat daemon %s started. (pid:%d uid:%d gid:%d)", getversion(), (int)getpid(), (int)getuid(), (int)getgid());
133 #endif
134 printe(PT_Info);
135
136 #if !HAVE_DECL_SQLITE_CHECKPOINT_RESTART
137 if (cfg.waldb) {
138 snprintf(errorstring, 1024, "DatabaseWriteAheadLogging is enabled but used libsqlite3 does not support it");
139 printe(PT_Warning);
140 }
141 #endif
142
143 /* warmup */
144 if (s.dbifcount == 0) {
145 filldatabaselist(&s);
146 s.prevdbsave = 0;
147 }
148 while (s.running && s.dbifcount && waittimesync(&s)) {
149 if (intsignal) {
150 handleintsignals(&s);
151 } else {
152 sleep(5);
153 }
154 }
155
156 /* main loop */
157 while (s.running) {
158
159 s.current = time(NULL);
160
161 /* track interface status only if at least one database exists */
162 if (s.dbifcount != 0) {
163 previflisthash = s.iflisthash;
164 interfacechangecheck(&s);
165 if (cfg.alwaysadd && s.iflisthash != previflisthash && previflisthash != 0) {
166 temp = s.dbifcount;
167 s.dbifcount += addinterfaces(&s);
168 if (temp != s.dbifcount) {
169 datacache_status(&s.dcache);
170 }
171 }
172 }
173
174 /* do update only if enough time has passed since the previous update */
175 if ((s.current - s.prevdbupdate) >= s.updateinterval) {
176
177 s.updateinterval = cfg.updateinterval;
178
179 if (debug) {
180 debugtimestamp();
181 datacache_debug(&s.dcache);
182 ibwlist();
183 }
184
185 /* fill database list if cache is empty */
186 if (s.dbifcount == 0) {
187 filldatabaselist(&s);
188
189 /* update data cache */
190 } else {
191 s.prevdbupdate = s.current - (s.current % s.updateinterval);
192
193 adjustsaveinterval(&s);
194 checkdbsaveneed(&s);
195
196 processdatacache(&s);
197
198 #if HAVE_DECL_SQLITE_CHECKPOINT_RESTART
199 if (cfg.waldb && (s.current - s.prevwaldbcheckpoint) >= WALDBCHECKPOINTINTERVALMINS * 60) {
200 db_walcheckpoint();
201 s.prevwaldbcheckpoint = s.current;
202 }
203 #endif
204
205 if (debug) {
206 printf("\n");
207 }
208 }
209 }
210
211 if (s.running && intsignal == 0) {
212 sleep((unsigned int)(cfg.pollinterval - (time(NULL) % cfg.pollinterval)));
213 }
214
215 if (intsignal) {
216 handleintsignals(&s);
217 }
218 }
219
220 flushcachetodisk(&s);
221 db_close();
222
223 datacache_clear(&s.dcache);
224 ibwflush();
225
226 if (s.rundaemon && !debug) {
227 close(pidfile);
228 unlink(cfg.pidfile);
229 }
230
231 return 0;
232 }
233
234 void showhelp(void)
235 {
236 printf("vnStat daemon %s by Teemu Toivola <tst at iki dot fi>\n\n", getversion());
237
238 printf(" -d, --daemon fork process to background\n");
239 printf(" -n, --nodaemon stay in foreground attached to the terminal\n\n");
240
241 printf(" -s, --sync sync interface counters on first update\n");
242 printf(" -D, --debug show additional debug and disable daemon\n");
243 printf(" -?, --help show this help\n");
244 printf(" -v, --version show version\n");
245 printf(" -p, --pidfile <file> select used pid file\n");
246 printf(" -u, --user <user> set daemon process user\n");
247 printf(" -g, --group <group> set daemon process group\n");
248 printf(" -t, --timestamp add timestamp to prints when running in foreground\n");
249 printf(" --config <config file> select used config file\n");
250 printf(" --noadd prevent startup if database has no interfaces\n");
251 printf(" --alwaysadd [mode] automatically start monitoring all new interfaces\n");
252 printf(" --initdb create empty database and exit\n\n");
253
254 printf("See also \"man vnstatd\".\n");
255 }
256
257 void parseargs(DSTATE *s, int argc, char **argv)
258 {
259 int currentarg, pidfiledefined = 0;
260
261 /* parse parameters, maybe not the best way but... */
262 for (currentarg = 1; currentarg < argc; currentarg++) {
263 if (debug)
264 printf("arg %d: \"%s\"\n", currentarg, argv[currentarg]);
265 if ((strcmp(argv[currentarg], "-?") == 0) || (strcmp(argv[currentarg], "--help") == 0)) {
266 break;
267 } else if (strcmp(argv[currentarg], "--config") == 0) {
268 /* config has already been parsed earlier so nothing to do here */
269 currentarg++;
270 } else if ((strcmp(argv[currentarg], "-D") == 0) || (strcmp(argv[currentarg], "--debug") == 0)) {
271 debug = 1;
272 } else if ((strcmp(argv[currentarg], "-d") == 0) || (strcmp(argv[currentarg], "--daemon") == 0)) {
273 s->rundaemon = 1;
274 s->showhelp = 0;
275 } else if ((strcmp(argv[currentarg], "-n") == 0) || (strcmp(argv[currentarg], "--nodaemon") == 0)) {
276 s->showhelp = 0;
277 } else if ((strcmp(argv[currentarg], "-s") == 0) || (strcmp(argv[currentarg], "--sync") == 0)) {
278 s->sync = 1;
279 } else if ((strcmp(argv[currentarg], "-t") == 0) || (strcmp(argv[currentarg], "--timestamp") == 0)) {
280 cfg.timestampprints = 1;
281 } else if ((strcmp(argv[currentarg], "-u") == 0) || (strcmp(argv[currentarg], "--user") == 0)) {
282 if (currentarg + 1 < argc) {
283 strncpy_nt(s->user, argv[currentarg + 1], 33);
284 if (debug)
285 printf("Requested user: \"%s\"\n", s->user);
286 currentarg++;
287 } else {
288 printf("Error: User for --user missing.\n");
289 exit(EXIT_FAILURE);
290 }
291 } else if ((strcmp(argv[currentarg], "-g") == 0) || (strcmp(argv[currentarg], "--group") == 0)) {
292 if (currentarg + 1 < argc) {
293 strncpy_nt(s->group, argv[currentarg + 1], 33);
294 if (debug)
295 printf("Requested group: \"%s\"\n", s->group);
296 currentarg++;
297 } else {
298 printf("Error: Group for --group missing.\n");
299 exit(EXIT_FAILURE);
300 }
301 } else if (strcmp(argv[currentarg], "--noadd") == 0) {
302 s->noadd = 1;
303 } else if (strcmp(argv[currentarg], "--alwaysadd") == 0) {
304 if (currentarg + 1 < argc && (strlen(argv[currentarg + 1]) == 1 || ishelprequest(argv[currentarg + 1]))) {
305 if (!isdigit(argv[currentarg + 1][0]) || atoi(argv[currentarg + 1]) > 1 || atoi(argv[currentarg + 1]) < 0) {
306 if (!ishelprequest(argv[currentarg + 1]))
307 printf("Error: Invalid mode parameter \"%s\".\n", argv[currentarg + 1]);
308 printf(" Valid parameters for %s:\n", argv[currentarg]);
309 printf(" 0 - disabled");
310 if (!cfg.alwaysadd) {
311 printf(" (default)");
312 }
313 printf("\n 1 - enabled");
314 if (cfg.alwaysadd) {
315 printf(" (default)");
316 }
317 printf("\n No mode parameter results in feature being enabled.\n");
318 exit(EXIT_FAILURE);
319 }
320 cfg.alwaysadd = atoi(argv[currentarg + 1]);
321 currentarg++;
322 } else {
323 cfg.alwaysadd = 1;
324 }
325 } else if (strcmp(argv[currentarg], "--initdb") == 0) {
326 s->initdb = 1;
327 s->showhelp = 0;
328 } else if ((strcmp(argv[currentarg], "-v") == 0) || (strcmp(argv[currentarg], "--version") == 0)) {
329 printf("vnStat daemon %s by Teemu Toivola <tst at iki dot fi>\n", getversion());
330 exit(EXIT_SUCCESS);
331 } else if ((strcmp(argv[currentarg], "-p") == 0) || (strcmp(argv[currentarg], "--pidfile") == 0)) {
332 if (currentarg + 1 < argc) {
333 strncpy_nt(cfg.pidfile, argv[currentarg + 1], 512);
334 cfg.pidfile[511] = '\0';
335 if (debug)
336 printf("Used pid file: %s\n", cfg.pidfile);
337 currentarg++;
338 pidfiledefined = 1;
339 } else {
340 printf("Error: File for --pidfile missing.\n");
341 exit(EXIT_FAILURE);
342 }
343 } else {
344 printf("Unknown arg \"%s\". Use --help for help.\n", argv[currentarg]);
345 exit(EXIT_FAILURE);
346 }
347 }
348
349 if (s->noadd && cfg.alwaysadd) {
350 printf("Warning: --noadd and --alwaysadd can't both be enabled at the same time. --alwaysadd has been disabled.\n");
351 cfg.alwaysadd = 0;
352 }
353
354 if (s->rundaemon && debug) {
355 printf("Error: --daemon and --debug can't both be used at the same time.\n");
356 exit(EXIT_FAILURE);
357 }
358
359 if (s->rundaemon && s->initdb) {
360 printf("Error: --daemon and --initdb can't both be used at the same time.\n");
361 exit(EXIT_FAILURE);
362 }
363
364 /* show help if nothing else was asked to be done */
365 if (s->showhelp) {
366 showhelp();
367 exit(EXIT_SUCCESS);
368 }
369
370 if (!s->rundaemon && pidfiledefined) {
371 printf("Error: --pidfile can only be used together with --daemon\n");
372 exit(EXIT_FAILURE);
373 }
374 }