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(&current));
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(&current)->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