Annotation of embedaddon/bmon/src/bmon.c, revision 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>