Annotation of embedaddon/mtr/ui/select.c, revision 1.1

1.1     ! misho       1: /*
        !             2:     mtr  --  a network diagnostic tool
        !             3:     Copyright (C) 1997,1998  Matt Kimball
        !             4: 
        !             5:     This program is free software; you can redistribute it and/or modify
        !             6:     it under the terms of the GNU General Public License version 2 as 
        !             7:     published by the Free Software Foundation.
        !             8: 
        !             9:     This program is distributed in the hope that it will be useful,
        !            10:     but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            11:     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            12:     GNU General Public License for more details.
        !            13: 
        !            14:     You should have received a copy of the GNU General Public License
        !            15:     along with this program; if not, write to the Free Software
        !            16:     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
        !            17: */
        !            18: 
        !            19: #include "config.h"
        !            20: 
        !            21: #include <sys/types.h>
        !            22: #include <sys/time.h>
        !            23: #include <stdlib.h>
        !            24: #include <stdio.h>
        !            25: #include <unistd.h>
        !            26: #include <time.h>
        !            27: #include <sys/select.h>
        !            28: #include <string.h>
        !            29: #include <math.h>
        !            30: #include <errno.h>
        !            31: #ifdef HAVE_ERROR_H
        !            32: #include <error.h>
        !            33: #else
        !            34: #include "portability/error.h"
        !            35: #endif
        !            36: 
        !            37: #include "mtr.h"
        !            38: #include "dns.h"
        !            39: #include "net.h"
        !            40: #include "asn.h"
        !            41: #include "display.h"
        !            42: #include "select.h"
        !            43: 
        !            44: void select_loop(
        !            45:     struct mtr_ctl *ctl)
        !            46: {
        !            47:     fd_set readfd;
        !            48:     fd_set writefd;
        !            49:     int anyset = 0;
        !            50:     int maxfd = 0;
        !            51:     int dnsfd, netfd;
        !            52: #ifdef ENABLE_IPV6
        !            53:     int dnsfd6;
        !            54: #endif
        !            55:     int NumPing = 0;
        !            56:     int paused = 0;
        !            57:     struct timeval lasttime, thistime, selecttime;
        !            58:     struct timeval startgrace;
        !            59:     int dt;
        !            60:     int rv;
        !            61:     int graceperiod = 0;
        !            62:     struct timeval intervaltime;
        !            63:     static double dnsinterval = 0;
        !            64: 
        !            65:     memset(&startgrace, 0, sizeof(startgrace));
        !            66: 
        !            67:     gettimeofday(&lasttime, NULL);
        !            68: 
        !            69:     while (1) {
        !            70:         dt = calc_deltatime(ctl->WaitTime);
        !            71:         intervaltime.tv_sec = dt / 1000000;
        !            72:         intervaltime.tv_usec = dt % 1000000;
        !            73: 
        !            74:         FD_ZERO(&readfd);
        !            75:         FD_ZERO(&writefd);
        !            76: 
        !            77:         maxfd = 0;
        !            78: 
        !            79:         if (ctl->Interactive) {
        !            80:             FD_SET(0, &readfd);
        !            81:             maxfd = 1;
        !            82:         }
        !            83: #ifdef ENABLE_IPV6
        !            84:         if (ctl->dns) {
        !            85:             dnsfd6 = dns_waitfd6();
        !            86:             if (dnsfd6 >= 0) {
        !            87:                 FD_SET(dnsfd6, &readfd);
        !            88:                 if (dnsfd6 >= maxfd)
        !            89:                     maxfd = dnsfd6 + 1;
        !            90:             } else {
        !            91:                 dnsfd6 = 0;
        !            92:             }
        !            93:         } else
        !            94:             dnsfd6 = 0;
        !            95: #endif
        !            96:         if (ctl->dns) {
        !            97:             dnsfd = dns_waitfd();
        !            98:             FD_SET(dnsfd, &readfd);
        !            99:             if (dnsfd >= maxfd)
        !           100:                 maxfd = dnsfd + 1;
        !           101:         } else
        !           102:             dnsfd = 0;
        !           103: 
        !           104:         netfd = net_waitfd();
        !           105:         FD_SET(netfd, &readfd);
        !           106:         if (netfd >= maxfd)
        !           107:             maxfd = netfd + 1;
        !           108: 
        !           109:         do {
        !           110:             if (anyset || paused) {
        !           111:                 /* Set timeout to 0.1s.
        !           112:                  * While this is almost instantaneous for human operators,
        !           113:                  * it's slow enough for computers to go do something else;
        !           114:                  * this prevents mtr from hogging 100% CPU time on one core.
        !           115:                  */
        !           116:                 selecttime.tv_sec = 0;
        !           117:                 selecttime.tv_usec = paused ? 100000 : 0;
        !           118: 
        !           119:                 rv = select(maxfd, (void *) &readfd, &writefd, NULL,
        !           120:                             &selecttime);
        !           121: 
        !           122:             } else {
        !           123:                 if (ctl->Interactive)
        !           124:                     display_redraw(ctl);
        !           125: 
        !           126:                 gettimeofday(&thistime, NULL);
        !           127: 
        !           128:                 if (thistime.tv_sec > lasttime.tv_sec + intervaltime.tv_sec
        !           129:                     || (thistime.tv_sec ==
        !           130:                         lasttime.tv_sec + intervaltime.tv_sec
        !           131:                         && thistime.tv_usec >=
        !           132:                         lasttime.tv_usec + intervaltime.tv_usec)) {
        !           133:                     lasttime = thistime;
        !           134: 
        !           135:                     if (!graceperiod) {
        !           136:                         if (NumPing >= ctl->MaxPing
        !           137:                             && (!ctl->Interactive || ctl->ForceMaxPing)) {
        !           138:                             graceperiod = 1;
        !           139:                             startgrace = thistime;
        !           140:                         }
        !           141: 
        !           142:                         /* do not send out batch when we've already initiated grace period */
        !           143:                         if (!graceperiod && net_send_batch(ctl))
        !           144:                             NumPing++;
        !           145:                     }
        !           146:                 }
        !           147: 
        !           148:                 if (graceperiod) {
        !           149:                     dt = (thistime.tv_usec - startgrace.tv_usec) +
        !           150:                         1000000 * (thistime.tv_sec - startgrace.tv_sec);
        !           151:                     if ((ctl->GraceTime * 1000 * 1000) < dt)
        !           152:                         return;
        !           153:                 }
        !           154: 
        !           155:                 selecttime.tv_usec = (thistime.tv_usec - lasttime.tv_usec);
        !           156:                 selecttime.tv_sec = (thistime.tv_sec - lasttime.tv_sec);
        !           157:                 if (selecttime.tv_usec < 0) {
        !           158:                     --selecttime.tv_sec;
        !           159:                     selecttime.tv_usec += 1000000;
        !           160:                 }
        !           161:                 selecttime.tv_usec =
        !           162:                     intervaltime.tv_usec - selecttime.tv_usec;
        !           163:                 selecttime.tv_sec =
        !           164:                     intervaltime.tv_sec - selecttime.tv_sec;
        !           165:                 if (selecttime.tv_usec < 0) {
        !           166:                     --selecttime.tv_sec;
        !           167:                     selecttime.tv_usec += 1000000;
        !           168:                 }
        !           169: 
        !           170:                 if (ctl->dns) {
        !           171:                     if ((selecttime.tv_sec > (time_t) dnsinterval) ||
        !           172:                         ((selecttime.tv_sec == (time_t) dnsinterval) &&
        !           173:                          (selecttime.tv_usec >
        !           174:                           ((time_t) (dnsinterval * 1000000) % 1000000)))) {
        !           175:                         selecttime.tv_sec = (time_t) dnsinterval;
        !           176:                         selecttime.tv_usec =
        !           177:                             (time_t) (dnsinterval * 1000000) % 1000000;
        !           178:                     }
        !           179:                 }
        !           180: 
        !           181:                 rv = select(maxfd, (void *) &readfd, NULL, NULL,
        !           182:                             &selecttime);
        !           183:             }
        !           184:         } while ((rv < 0) && (errno == EINTR));
        !           185: 
        !           186:         if (rv < 0) {
        !           187:             error(EXIT_FAILURE, errno, "Select failed");
        !           188:         }
        !           189:         anyset = 0;
        !           190: 
        !           191:         /*  Have we got new packets back?  */
        !           192:         if (FD_ISSET(netfd, &readfd)) {
        !           193:             net_process_return(ctl);
        !           194:             anyset = 1;
        !           195:         }
        !           196: 
        !           197:         if (ctl->dns) {
        !           198:             /* Handle any pending resolver events */
        !           199:             dnsinterval = ctl->WaitTime;
        !           200:         }
        !           201: 
        !           202:         /*  Have we finished a nameservice lookup?  */
        !           203: #ifdef ENABLE_IPV6
        !           204:         if (ctl->dns && dnsfd6 && FD_ISSET(dnsfd6, &readfd)) {
        !           205:             dns_ack6();
        !           206:             anyset = 1;
        !           207:         }
        !           208: #endif
        !           209:         if (ctl->dns && dnsfd && FD_ISSET(dnsfd, &readfd)) {
        !           210:             dns_ack(ctl);
        !           211:             anyset = 1;
        !           212:         }
        !           213: 
        !           214:         /*  Has a key been pressed?  */
        !           215:         if (FD_ISSET(0, &readfd)) {
        !           216:             switch (display_keyaction(ctl)) {
        !           217:             case ActionQuit:
        !           218:                 return;
        !           219:                 break;
        !           220:             case ActionReset:
        !           221:                 net_reset(ctl);
        !           222:                 break;
        !           223:             case ActionDisplay:
        !           224:                 ctl->display_mode =
        !           225:                     (ctl->display_mode + 1) % DisplayModeMAX;
        !           226:                 break;
        !           227:             case ActionClear:
        !           228:                 display_clear(ctl);
        !           229:                 break;
        !           230:             case ActionPause:
        !           231:                 paused = 1;
        !           232:                 break;
        !           233:             case ActionResume:
        !           234:                 paused = 0;
        !           235:                 break;
        !           236:             case ActionMPLS:
        !           237:                 ctl->enablempls = !ctl->enablempls;
        !           238:                 display_clear(ctl);
        !           239:                 break;
        !           240:             case ActionDNS:
        !           241:                 if (ctl->dns) {
        !           242:                     ctl->use_dns = !ctl->use_dns;
        !           243:                     display_clear(ctl);
        !           244:                 }
        !           245:                 break;
        !           246: #ifdef HAVE_IPINFO
        !           247:             case ActionII:
        !           248:                 ctl->ipinfo_no++;
        !           249:                 if (ctl->ipinfo_no > ctl->ipinfo_max)
        !           250:                     ctl->ipinfo_no = 0;
        !           251:                 break;
        !           252:             case ActionAS:
        !           253:                 ctl->ipinfo_no = ctl->ipinfo_no ? 0 : ctl->ipinfo_max;
        !           254:                 break;
        !           255: #endif
        !           256: 
        !           257:             case ActionScrollDown:
        !           258:                 ctl->display_offset += 5;
        !           259:                 break;
        !           260:             case ActionScrollUp:
        !           261:                 ctl->display_offset -= 5;
        !           262:                 if (ctl->display_offset < 0) {
        !           263:                     ctl->display_offset = 0;
        !           264:                 }
        !           265:                 break;
        !           266:             }
        !           267:             anyset = 1;
        !           268:         }
        !           269:     }
        !           270:     return;
        !           271: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>