Annotation of embedaddon/bmon/src/bmon.c, revision 1.1.1.1
1.1 misho 1: /*
2: * src/bmon.c Bandwidth Monitor
3: *
4: * Copyright (c) 2001-2005 Thomas Graf <tgraf@suug.ch>
5: *
6: * Permission is hereby granted, free of charge, to any person obtaining a
7: * copy of this software and associated documentation files (the "Software"),
8: * to deal in the Software without restriction, including without limitation
9: * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10: * and/or sell copies of the Software, and to permit persons to whom the
11: * Software is furnished to do so, subject to the following conditions:
12: *
13: * The above copyright notice and this permission notice shall be included
14: * in all copies or substantial portions of the Software.
15: *
16: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17: * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19: * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21: * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22: * DEALINGS IN THE SOFTWARE.
23: */
24:
25: #include <bmon/bmon.h>
26: #include <bmon/conf.h>
27: #include <bmon/item.h>
28: #include <bmon/itemtab.h>
29: #include <bmon/input.h>
30: #include <bmon/output.h>
31: #include <bmon/signal.h>
32: #include <bmon/utils.h>
33:
34: int start_time;
35: int do_quit = 0;
36:
37: struct reader_timing rtiming;
38: static char *usage_text =
39: "Usage: bmon [OPTION]...\n" \
40: "\n" \
41: "Options:\n" \
42: " -i <modparm> Primary input module\n" \
43: " -o <modparm> Primary ouptut module\n" \
44: " -I <modparm> Secondary input modules\n" \
45: " -O <modparm> Secondary output modules\n" \
46: " -f <path> Alternative path to configuration file\n" \
47: " -p <policy> Interface acceptance policy\n" \
48: " -a Accept interfaces even if they are down\n" \
49: " -A <attrs> Attributes history configuration\n" \
50: " -r <float> Read interval in seconds\n" \
51: " -R <float> Rate interval in seconds\n" \
52: " -H <hbeat> Heartbeat factor (0..1)\n" \
53: " -L <lifetime> Lifetime of a item in seconds\n" \
54: " -c Use SI units\n" \
55: " -t <path> Alternative path to itemtab file\n" \
56: " -N <num> Number of graphs to draw\n" \
57: " -s <float> Sleep time in seconds\n" \
58: " -w Signal driven output intervals\n" \
59: " -S <pid> Send SIGUSR1 to a running bmon instance\n" \
60: " -u <uid> Drop privileges and change UID\n" \
61: " -g <gid> Drop privileges and change GID\n" \
62: " -h show this help text\n" \
63: " -V show version\n" \
64: "\n" \
65: "Module configuration:\n" \
66: " modparm := MODULE:optlist,MODULE:optlist,...\n" \
67: " optlist := option;option;...\n" \
68: " option := TYPE[=VALUE]\n" \
69: "\n" \
70: " Examples:\n" \
71: " -O html:path=/var/www/html,distribution:port=2444;debug\n" \
72: " -O list # Shows a list of available modules\n" \
73: " -O html:help # Shows a help text for html module\n" \
74: "\n" \
75: "Interface selection:\n" \
76: " policy := [!]simple_regexp,[!]simple_regexp,...\n" \
77: "\n" \
78: " Example: -p 'eth*,lo*,!eth1'\n" \
79: "\n" \
80: "Attributes selection:\n" \
81: " attrs := [!]name,[!]name,...\n" \
82: "\n" \
83: " Example: -A !hbeat_err\n" \
84: "\n" \
85: "Please see the bmon(1) man pages for full documentation.\n";
86:
87: static char *uid, *gid;
88:
89: static void do_shutdown(void)
90: {
91: static int done;
92:
93: if (!done) {
94: done = 1;
95: input_shutdown();
96: output_shutdown();
97: }
98: }
99:
100: RETSIGTYPE sig_int(int unused)
101: {
102: if (do_quit)
103: exit(-1);
104: do_quit = 1;
105: }
106:
107: void sig_exit(void)
108: {
109: do_shutdown();
110: }
111:
112: void quit(const char *fmt, ...)
113: {
114: static int done;
115: va_list args;
116:
117: if (!done) {
118: done = 1;
119: do_shutdown();
120: }
121:
122: va_start(args, fmt);
123: vfprintf(stderr, fmt, args);
124: va_end(args);
125:
126: exit(1);
127: }
128:
129: static void print_version(void)
130: {
131: printf("bmon %s\n", PACKAGE_VERSION);
132: printf("Copyright (C) 2001-2005 by Thomas Graf <tgraf@suug.ch>\n");
133: printf("bmon comes with ABSOLUTELY NO WARRANTY. This is free software, " \
134: "and you\nare welcome to redistribute it under certain conditions. " \
135: "See the source\ncode for details.\n");
136: }
137:
138: static void parse_args(int argc, char *argv[])
139: {
140: for (;;)
141: {
142: int c = getopt(argc, argv, "hVf:i:I:o:O:p:r:s:S:waA:cN" \
143: ":u:g:H:R:L:t:");
144:
145: if (c == -1)
146: break;
147:
148: switch (c)
149: {
150: case 'i':
151: set_input(optarg);
152: break;
153:
154: case 'I':
155: set_sec_input(optarg);
156: break;
157:
158: case 'o':
159: set_output(optarg);
160: break;
161:
162: case 'O':
163: set_sec_output(optarg);
164: break;
165:
166: case 'f':
167: set_configfile(optarg);
168: break;
169:
170: case 'p':
171: item_parse_policy(optarg);
172: break;
173:
174: case 'A':
175: parse_attr_policy(optarg);
176: break;
177:
178: case 'r':
179: set_read_interval(optarg);
180: break;
181:
182: case 'R':
183: set_rate_interval(optarg);
184: break;
185:
186: case 'L':
187: set_lifetime(optarg);
188: break;
189:
190: case 's':
191: set_sleep_time(optarg);
192: break;
193:
194: case 'S':
195: send_signal(optarg);
196: exit(0);
197:
198: case 'w':
199: set_signal_output(1);
200: break;
201:
202: case 'a':
203: set_show_only_running(0);
204: break;
205:
206: case 'h':
207: print_version();
208: printf("\n%s", usage_text);
209: exit(1);
210:
211: case 'N':
212: set_ngraphs(strtol(optarg, NULL, 0));
213: break;
214:
215: case 'c':
216: set_use_si();
217: break;
218:
219: case 'u':
220: uid = strdup(optarg);
221: break;
222:
223: case 'g':
224: gid = strdup(optarg);
225: break;
226:
227: case 'H':
228: set_hb_factor(optarg);
229: break;
230:
231: case 't':
232: set_itemtab(optarg);
233: break;
234:
235: case 'V':
236: case 'v':
237: print_version();
238: exit(0);
239:
240: default:
241: quit("Aborting...\n");
242: }
243: }
244: }
245:
246: static void calc_variance(timestamp_t *c, timestamp_t *ri)
247: {
248: float v = (ts_to_float(c) / ts_to_float(ri)) * 100.0f;
249:
250: rtiming.rt_variance.v_error = v;
251: rtiming.rt_variance.v_total += v;
252:
253: if (v > rtiming.rt_variance.v_max)
254: rtiming.rt_variance.v_max = v;
255:
256: if (v < rtiming.rt_variance.v_min)
257: rtiming.rt_variance.v_min = v;
258: }
259:
260: static void drop_privs(void)
261: {
262: struct passwd *uentry = NULL;
263: struct group *gentry = NULL;
264:
265: if (gid)
266: gentry = getgrnam(gid);
267:
268: if (uid)
269: uentry = getpwnam(uid);
270:
271: if (gentry)
272: if (setgid(gentry->gr_gid) < 0)
273: quit("Unable to set group id %d: %s\n",
274: gentry->gr_gid, strerror(errno));
275:
276: if (uentry)
277: if (setuid(uentry->pw_uid) < 0)
278: quit("Unable to set user id %d: %s\n",
279: uentry->pw_uid, strerror(errno));
280: }
281:
282: int main(int argc, char *argv[])
283: {
284: unsigned long c_sleep_time;
285: float read_interval;
286:
287: start_time = time(0);
288:
289: parse_args(argc, argv);
290: read_configfile();
291: read_itemtab();
292:
293: c_sleep_time = get_sleep_time();
294: read_interval = get_read_interval();
295:
296: if (((double) c_sleep_time/1000000.0f) > read_interval)
297: c_sleep_time = (unsigned long) (read_interval * 1000000.0f);
298:
299: input_init();
300: output_init();
301:
302: drop_privs();
303:
304: {
305: /*
306: * E := Elapsed time
307: * NR := Next Read
308: * LR := Last Read
309: * RI := Read Interval
310: * ST := Sleep Time
311: * C := Correction
312: */
313: timestamp_t e, ri, tmp;
314: unsigned long st;
315:
316: get_read_interval_as_ts(&ri);
317:
318: /*
319: * E := NOW()
320: */
321: update_ts(&e);
322:
323: /*
324: * NR := E
325: */
326: COPY_TS(&rtiming.rt_next_read, &e);
327:
328: for (;;) {
329: output_pre();
330:
331: /*
332: * E := NOW()
333: */
334: update_ts(&e);
335:
336: /*
337: * IF NR <= E THEN
338: */
339: if (ts_le(&rtiming.rt_next_read, &e)) {
340: timestamp_t c;
341:
342: /*
343: * C := (NR - E)
344: */
345: ts_sub(&c, &rtiming.rt_next_read, &e);
346:
347: calc_variance(&c, &ri);
348:
349: /*
350: * LR := E
351: */
352: COPY_TS(&rtiming.rt_last_read, &e);
353:
354: /*
355: * NR := E + RI + C
356: */
357: ts_add(&rtiming.rt_next_read, &e, &ri);
358: ts_add(&rtiming.rt_next_read, &rtiming.rt_next_read, &c);
359:
360: input_read();
361: output_draw();
362:
363: output_post();
364: }
365:
366: if (do_quit)
367: exit(0);
368:
369: if (got_resized())
370: output_resize();
371:
372: /*
373: * ST := Configured ST
374: */
375: st = c_sleep_time;
376:
377: /*
378: * IF (NR - E) < ST THEN
379: */
380: ts_sub(&tmp, &rtiming.rt_next_read, &e);
381:
382: if (tmp.tv_sec < 0)
383: continue;
384:
385: if (tmp.tv_sec == 0 && tmp.tv_usec < st) {
386: if (tmp.tv_usec < 0)
387: continue;
388: /*
389: * ST := (NR - E)
390: */
391: st = tmp.tv_usec;
392: }
393:
394: /*
395: * SLEEP(ST)
396: */
397: usleep(st);
398: }
399: }
400:
401: return 0; /* buddha says i'll never be reached */
402: }
403:
404: static void __init bmon_init(void)
405: {
406: memset(&rtiming, 0, sizeof(rtiming));
407: rtiming.rt_variance.v_min = 10000000.0f;
408: atexit(&sig_exit);
409: signal(SIGINT, &sig_int);
410: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>