1 #include "common.h"
2
3 /* global variables */
4 CFG cfg;
5 IFINFO ifinfo;
6 char errorstring[1024];
7 ibwnode *ifacebw;
8 int debug;
9 int noexit; /* = running as daemon if 2 */
10 int intsignal;
11 int pidfile;
12 int disableprints;
13
printe(const PrintType type)14 int printe(const PrintType type)
15 {
16 int result = 1;
17
18 if (disableprints) {
19 return 1;
20
21 /* daemon running but log not enabled */
22 } else if (noexit == 2 && cfg.uselogging == 0) {
23 return 1;
24
25 /* daemon running, log enabled */
26 } else if (noexit == 2) {
27
28 switch (type) {
29 case PT_Multiline:
30 break;
31 case PT_Info:
32 case PT_Infoless:
33 case PT_Warning:
34 case PT_Error:
35 case PT_Config:
36 case PT_ShortMultiline:
37 result = logprint(type);
38 break;
39 }
40
41 /* daemon isn't running */
42 } else {
43
44 switch (type) {
45 case PT_Info:
46 printf("Info: %s\n", errorstring);
47 break;
48 case PT_Infoless:
49 printf("%s\n", errorstring);
50 break;
51 case PT_Warning:
52 printf("Warning: %s\n", errorstring);
53 break;
54 case PT_Error:
55 printf("Error: %s\n", errorstring);
56 break;
57 case PT_Config:
58 printf("Config: %s\n", errorstring);
59 break;
60 case PT_Multiline:
61 printf("%s\n", errorstring);
62 break;
63 case PT_ShortMultiline:
64 break;
65 }
66 fflush(stdout);
67 }
68
69 return result;
70 }
71
logprint(const PrintType type)72 int logprint(const PrintType type)
73 {
74 /* buffer needs some extra space for timestamp + info compared to errorstring */
75 char timestamp[22], buffer[1060];
76 time_t current;
77 FILE *logfile;
78
79 buffer[0] = '\0';
80
81 /* logfile */
82 if (cfg.uselogging == 1) {
83
84 if (type == PT_Multiline) {
85 return 0;
86 }
87
88 if ((logfile = fopen(cfg.logfile, "a")) == NULL) {
89 return 0;
90 }
91
92 current = time(NULL);
93 strftime(timestamp, 22, DATETIMEFORMAT, localtime(¤t));
94
95 switch (type) {
96 case PT_Info:
97 case PT_Infoless:
98 snprintf(buffer, 1060, "[%s] %s\n", timestamp, errorstring);
99 break;
100 case PT_Warning:
101 snprintf(buffer, 1060, "[%s] Warning: %s\n", timestamp, errorstring);
102 break;
103 case PT_Error:
104 snprintf(buffer, 1060, "[%s] Error: %s\n", timestamp, errorstring);
105 break;
106 case PT_Config:
107 snprintf(buffer, 1060, "[%s] Config: %s\n", timestamp, errorstring);
108 break;
109 case PT_Multiline:
110 break;
111 case PT_ShortMultiline:
112 snprintf(buffer, 1060, "[%s] %s\n", timestamp, errorstring);
113 break;
114 }
115
116 if (fwrite(buffer, strlen(buffer), 1, logfile) != 1) {
117 fclose(logfile);
118 return 0;
119 }
120
121 fclose(logfile);
122 return 1;
123
124 /* syslog */
125 } else if (cfg.uselogging == 2) {
126
127 openlog("vnstatd", LOG_PID, LOG_DAEMON);
128
129 switch (type) {
130 case PT_Multiline:
131 break;
132 case PT_Warning:
133 syslog(LOG_WARNING, "Warning: %s", errorstring);
134 break;
135 case PT_Error:
136 syslog(LOG_ERR, "Error: %s", errorstring);
137 break;
138 case PT_Config:
139 syslog(LOG_ERR, "Config: %s", errorstring);
140 break;
141 case PT_Info:
142 case PT_Infoless:
143 case PT_ShortMultiline:
144 syslog(LOG_NOTICE, "%s", errorstring);
145 break;
146 }
147
148 closelog();
149 return 1;
150 }
151
152 return 0;
153 }
154
verifylogaccess(void)155 int verifylogaccess(void)
156 {
157 FILE *logfile;
158
159 /* only logfile logging can be verified */
160 if (cfg.uselogging == 1) {
161 if ((logfile = fopen(cfg.logfile, "a")) == NULL) {
162 return 0;
163 }
164 fclose(logfile);
165 }
166 return 1;
167 }
168
dmonth(const int month)169 int dmonth(const int month)
170 {
171 static int dmon[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
172 int year;
173 time_t current;
174
175 /* handle leap years */
176 if (month == 1) {
177 current = time(NULL);
178 year = localtime(¤t)->tm_year + 1900;
179 if (isleapyear(year)) {
180 return 29;
181 } else {
182 return 28;
183 }
184 } else {
185 return dmon[month];
186 }
187 }
188
isleapyear(const int year)189 int isleapyear(const int year)
190 {
191 if (year % 4 != 0) {
192 return 0;
193 } else if (year % 100 != 0) {
194 return 1;
195 } else if (year % 400 != 0) {
196 return 0;
197 }
198 return 1;
199 }
200
mosecs(time_t month,time_t updated)201 time_t mosecs(time_t month, time_t updated)
202 {
203 struct tm d;
204
205 if (localtime_r(&month, &d) == NULL) {
206 return 1;
207 }
208
209 d.tm_mday = cfg.monthrotate;
210 d.tm_hour = d.tm_min = d.tm_sec = 0;
211
212 if ((updated - month) > 0) {
213 return updated - mktime(&d);
214 } else {
215 return 1;
216 }
217 }
218
countercalc(const uint64_t * a,const uint64_t * b,const short is64bit)219 uint64_t countercalc(const uint64_t *a, const uint64_t *b, const short is64bit)
220 {
221 /* no rollover */
222 if (*b >= *a) {
223 if (debug)
224 printf("cc (%d): %" PRIu64 " - %" PRIu64 " = %" PRIu64 "\n", is64bit, *b, *a, *b - *a);
225 return *b - *a;
226
227 /* rollover exists */
228 } else {
229 /* counter is 64bit */
230 if (*a > MAX32 || *b > MAX32 || is64bit == 1) {
231 if (debug)
232 printf("cc64 (%d): uint64 - %" PRIu64 " + %" PRIu64 " = %" PRIu64 "\n", is64bit, *a, *b, (uint64_t)MAX64 - *a + *b);
233 return MAX64 - *a + *b;
234
235 /* counter is 32bit */
236 } else {
237 if (debug)
238 printf("cc32 (%d): uint32 - %" PRIu64 " + %" PRIu64 " = %" PRIu64 "\n", is64bit, *a, *b, (uint64_t)MAX32 - *a + *b);
239 return MAX32 - *a + *b;
240 }
241 }
242 }
243
244 /* strncpy with ensured null termination */
strncpy_nt(char * dest,const char * src,size_t n)245 char *strncpy_nt(char *dest, const char *src, size_t n)
246 {
247 strncpy(dest, src, n);
248 dest[n - 1] = '\0';
249 return dest;
250 }
251
isnumeric(const char * s)252 int isnumeric(const char *s)
253 {
254 size_t i, len = strlen(s);
255
256 if (!len) {
257 return 0;
258 }
259
260 for (i = 0; i < len; i++) {
261 if (!isdigit(s[i])) {
262 return 0;
263 }
264 }
265
266 return 1;
267 }
268
panicexit(const char * sourcefile,const int sourceline)269 __attribute__((noreturn)) void panicexit(const char *sourcefile, const int sourceline)
270 {
271 snprintf(errorstring, 1024, "Unexpected error (%s), exiting. (%s:%d)", strerror(errno), sourcefile, sourceline);
272 fprintf(stderr, "%s\n", errorstring);
273 printe(PT_Error);
274 exit(EXIT_FAILURE);
275 }
276
getversion(void)277 char *getversion(void)
278 {
279 int i;
280 static char versionbuffer[16];
281 strncpy_nt(versionbuffer, VERSION, 16);
282 for (i = 0; i < (int)strlen(versionbuffer); i++) {
283 if (versionbuffer[i] == '_') {
284 versionbuffer[i] = ' ';
285 }
286 }
287 return versionbuffer;
288 }
289
timeused(const char * func,const int reset)290 double timeused(const char *func, const int reset)
291 {
292 static struct timeval starttime;
293 struct timeval endtime;
294 double used_secs;
295
296 if (reset) {
297 gettimeofday(&starttime, NULL);
298 return 0.0;
299 }
300
301 if (gettimeofday(&endtime, NULL) != 0) {
302 return 0.0;
303 }
304
305 used_secs = (double)(endtime.tv_usec - starttime.tv_usec) / 1000000 + (double)(endtime.tv_sec - starttime.tv_sec);
306
307 if (debug) {
308 printf("%s() in %f s\n", func, used_secs);
309 }
310
311 return used_secs;
312 }
313
timeused_debug(const char * func,const int reset)314 void timeused_debug(const char *func, const int reset)
315 {
316 if (!debug) {
317 return;
318 }
319
320 timeused(func, reset);
321 }
322