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>