Annotation of embedaddon/ttcp/ttcp.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  *     T T C P . C
        !             3:  *
        !             4:  * Test TCP connection.  Makes a connection on port 5001
        !             5:  * and transfers fabricated buffers or data copied from stdin.
        !             6:  *
        !             7:  * Usable on 4.2, 4.3, and 4.1a systems by defining one of
        !             8:  * BSD42 BSD43 (BSD41a)
        !             9:  * Machines using System V with BSD sockets should define SYSV.
        !            10:  *
        !            11:  * Modified for operation under 4.2BSD, 18 Dec 84
        !            12:  *      T.C. Slattery, USNA
        !            13:  * Minor improvements, Mike Muuss and Terry Slattery, 16-Oct-85.
        !            14:  * Modified in 1989 at Silicon Graphics, Inc.
        !            15:  *     catch SIGPIPE to be able to print stats when receiver has died 
        !            16:  *     for tcp, don't look for sentinel during reads to allow small transfers
        !            17:  *     increased default buffer size to 8K, nbuf to 2K to transfer 16MB
        !            18:  *     moved default port to 5001, beyond IPPORT_USERRESERVED
        !            19:  *     make sinkmode default because it is more popular, 
        !            20:  *             -s now means don't sink/source 
        !            21:  *     count number of read/write system calls to see effects of 
        !            22:  *             blocking from full socket buffers
        !            23:  *     for tcp, -D option turns off buffered writes (sets TCP_NODELAY sockopt)
        !            24:  *     buffer alignment options, -A and -O
        !            25:  *     print stats in a format that's a bit easier to use with grep & awk
        !            26:  *     for SYSV, mimic BSD routines to use most of the existing timing code
        !            27:  * Modified by Steve Miller of the University of Maryland, College Park
        !            28:  *     -b sets the socket buffer size (SO_SNDBUF/SO_RCVBUF)
        !            29:  * Modified Sept. 1989 at Silicon Graphics, Inc.
        !            30:  *     restored -s sense at request of tcs@brl
        !            31:  * Modified Oct. 1991 at Silicon Graphics, Inc.
        !            32:  *     use getopt(3) for option processing, add -f and -T options.
        !            33:  *     SGI IRIX 3.3 and 4.0 releases don't need #define SYSV.
        !            34:  *
        !            35:  * Distribution Status -
        !            36:  *      Public Domain.  Distribution Unlimited.
        !            37:  */
        !            38: 
        !            39: #define BSD43
        !            40: /* #define BSD42 */
        !            41: /* #define BSD41a */
        !            42: /* #define SYSV */     /* required on SGI IRIX releases before 3.3 */
        !            43: 
        !            44: #include <stdio.h>
        !            45: #include <signal.h>
        !            46: #include <ctype.h>
        !            47: #include <errno.h>
        !            48: #include <sys/types.h>
        !            49: #include <sys/socket.h>
        !            50: #include <netinet/in.h>
        !            51: #include <netinet/tcp.h>
        !            52: #include <arpa/inet.h>
        !            53: #include <netdb.h>
        !            54: #include <sys/time.h>          /* struct timeval */
        !            55: #include <unistd.h>
        !            56: #include <string.h>
        !            57: #include <stdlib.h>
        !            58: 
        !            59: #if defined(SYSV)
        !            60: #include <sys/times.h>
        !            61: #include <sys/param.h>
        !            62: struct rusage {
        !            63:     struct timeval ru_utime, ru_stime;
        !            64: };
        !            65: #define RUSAGE_SELF 0
        !            66: #else
        !            67: #include <sys/resource.h>
        !            68: #endif
        !            69: 
        !            70: struct sockaddr_in sinme;
        !            71: struct sockaddr_in sinhim;
        !            72: struct sockaddr_in frominet;
        !            73: 
        !            74: int domain, fromlen;
        !            75: int fd;                                /* fd of network socket */
        !            76: 
        !            77: int buflen = 8 * 1024;         /* length of buffer */
        !            78: char *buf;                     /* ptr to dynamic buffer */
        !            79: int nbuf = 2 * 1024;           /* number of buffers to send in sinkmode */
        !            80: 
        !            81: int bufoffset = 0;             /* align buffer to this */
        !            82: int bufalign = 16*1024;                /* modulo this */
        !            83: 
        !            84: int udp = 0;                   /* 0 = tcp, !0 = udp */
        !            85: int options = 0;               /* socket options */
        !            86: int one = 1;                    /* for 4.3 BSD style setsockopt() */
        !            87: short port = 5001;             /* TCP port number */
        !            88: char *host;                    /* ptr to name of host */
        !            89: int trans;                     /* 0=receive, !0=transmit mode */
        !            90: int sinkmode = 0;              /* 0=normal I/O, !0=sink/source mode */
        !            91: int verbose = 0;               /* 0=print basic info, 1=print cpu rate, proc
        !            92:                                 * resource usage. */
        !            93: int nodelay = 0;               /* set TCP_NODELAY socket option */
        !            94: int b_flag = 0;                        /* use mread() */
        !            95: int sockbufsize = 0;           /* socket buffer size to use */
        !            96: char fmt = 'K';                        /* output format: k = kilobits, K = kilobytes,
        !            97:                                 *  m = megabits, M = megabytes, 
        !            98:                                 *  g = gigabits, G = gigabytes */
        !            99: int touchdata = 0;             /* access data after reading */
        !           100: 
        !           101: struct hostent *addr;
        !           102: extern int errno;
        !           103: extern int optind;
        !           104: extern char *optarg;
        !           105: 
        !           106: char Usage[] = "\
        !           107: Usage: ttcp -t [-options] host [ < in ]\n\
        !           108:        ttcp -r [-options > out]\n\
        !           109: Common options:\n\
        !           110:        -l ##   length of bufs read from or written to network (default 8192)\n\
        !           111:        -u      use UDP instead of TCP\n\
        !           112:        -p ##   port number to send to or listen at (default 5001)\n\
        !           113:        -s      -t: source a pattern to network\n\
        !           114:                -r: sink (discard) all data from network\n\
        !           115:        -A      align the start of buffers to this modulus (default 16384)\n\
        !           116:        -O      start buffers at this offset from the modulus (default 0)\n\
        !           117:        -v      verbose: print more statistics\n\
        !           118:        -d      set SO_DEBUG socket option\n\
        !           119:        -b ##   set socket buffer size (if supported)\n\
        !           120:        -f X    format for rate: k,K = kilo{bit,byte}; m,M = mega; g,G = giga\n\
        !           121: Options specific to -t:\n\
        !           122:        -n##    number of source bufs written to network (default 2048)\n\
        !           123:        -D      don't buffer TCP writes (sets TCP_NODELAY socket option)\n\
        !           124: Options specific to -r:\n\
        !           125:        -B      for -s, only output full blocks as specified by -l (for TAR)\n\
        !           126:        -T      \"touch\": access each byte as it's read\n\
        !           127: ";     
        !           128: 
        !           129: char stats[128];
        !           130: double nbytes;                 /* bytes on net */
        !           131: unsigned long numCalls;                /* # of I/O system calls */
        !           132: double cput, realt;            /* user, real time (seconds) */
        !           133: 
        !           134: void err();
        !           135: void mes();
        !           136: void pattern();
        !           137: void prep_timer();
        !           138: double read_timer();
        !           139: int Nread();
        !           140: int Nwrite();
        !           141: void delay();
        !           142: int mread();
        !           143: char *outfmt();
        !           144: 
        !           145: void
        !           146: sigpipe()
        !           147: {
        !           148: }
        !           149: 
        !           150: int
        !           151: main(argc,argv)
        !           152: int argc;
        !           153: char **argv;
        !           154: {
        !           155:        unsigned long addr_tmp;
        !           156:        int c;
        !           157: 
        !           158:        if (argc < 2) goto usage;
        !           159: 
        !           160:        while ((c = getopt(argc, argv, "drstuvBDTb:f:l:n:p:A:O:")) != -1) {
        !           161:                switch (c) {
        !           162: 
        !           163:                case 'B':
        !           164:                        b_flag = 1;
        !           165:                        break;
        !           166:                case 't':
        !           167:                        trans = 1;
        !           168:                        break;
        !           169:                case 'r':
        !           170:                        trans = 0;
        !           171:                        break;
        !           172:                case 'd':
        !           173:                        options |= SO_DEBUG;
        !           174:                        break;
        !           175:                case 'D':
        !           176: #ifdef TCP_NODELAY
        !           177:                        nodelay = 1;
        !           178: #else
        !           179:                        fprintf(stderr, 
        !           180:        "ttcp: -D option ignored: TCP_NODELAY socket option not supported\n");
        !           181: #endif
        !           182:                        break;
        !           183:                case 'n':
        !           184:                        nbuf = atoi(optarg);
        !           185:                        break;
        !           186:                case 'l':
        !           187:                        buflen = atoi(optarg);
        !           188:                        break;
        !           189:                case 's':
        !           190:                        sinkmode = !sinkmode;
        !           191:                        break;
        !           192:                case 'p':
        !           193:                        port = atoi(optarg);
        !           194:                        break;
        !           195:                case 'u':
        !           196:                        udp = 1;
        !           197:                        break;
        !           198:                case 'v':
        !           199:                        verbose = 1;
        !           200:                        break;
        !           201:                case 'A':
        !           202:                        bufalign = atoi(optarg);
        !           203:                        break;
        !           204:                case 'O':
        !           205:                        bufoffset = atoi(optarg);
        !           206:                        break;
        !           207:                case 'b':
        !           208: #if defined(SO_SNDBUF) || defined(SO_RCVBUF)
        !           209:                        sockbufsize = atoi(optarg);
        !           210: #else
        !           211:                        fprintf(stderr, 
        !           212: "ttcp: -b option ignored: SO_SNDBUF/SO_RCVBUF socket options not supported\n");
        !           213: #endif
        !           214:                        break;
        !           215:                case 'f':
        !           216:                        fmt = *optarg;
        !           217:                        break;
        !           218:                case 'T':
        !           219:                        touchdata = 1;
        !           220:                        break;
        !           221: 
        !           222:                default:
        !           223:                        goto usage;
        !           224:                }
        !           225:        }
        !           226:        if(trans)  {
        !           227:                /* xmitr */
        !           228:                if (optind == argc)
        !           229:                        goto usage;
        !           230:                bzero((char *)&sinhim, sizeof(sinhim));
        !           231:                host = argv[optind];
        !           232:                if (atoi(host) > 0 )  {
        !           233:                        /* Numeric */
        !           234:                        sinhim.sin_family = AF_INET;
        !           235: #if defined(cray)
        !           236:                        addr_tmp = inet_addr(host);
        !           237:                        sinhim.sin_addr = addr_tmp;
        !           238: #else
        !           239:                        sinhim.sin_addr.s_addr = inet_addr(host);
        !           240: #endif
        !           241:                } else {
        !           242:                        if ((addr=gethostbyname(host)) == NULL)
        !           243:                                err("bad hostname");
        !           244:                        sinhim.sin_family = addr->h_addrtype;
        !           245:                        bcopy(addr->h_addr,(char*)&addr_tmp, addr->h_length);
        !           246: #if defined(cray)
        !           247:                        sinhim.sin_addr = addr_tmp;
        !           248: #else
        !           249:                        sinhim.sin_addr.s_addr = addr_tmp;
        !           250: #endif /* cray */
        !           251:                }
        !           252:                sinhim.sin_port = htons(port);
        !           253:                sinme.sin_family = AF_INET;     /* Solaris needs this */
        !           254:                sinme.sin_port = 0;             /* free choice */
        !           255:        } else {
        !           256:                /* rcvr */
        !           257:                sinme.sin_port =  htons(port);
        !           258:        }
        !           259: 
        !           260: 
        !           261:        if (udp && buflen < 5) {
        !           262:            buflen = 5;         /* send more than the sentinel size */
        !           263:        }
        !           264: 
        !           265:        if ( (buf = (char *)malloc(buflen+bufalign)) == (char *)NULL)
        !           266:                err("malloc");
        !           267:        if (bufalign != 0)
        !           268:                buf += (bufalign
        !           269:                        -((unsigned long)buf % bufalign)
        !           270:                        + bufoffset) % bufalign;
        !           271: 
        !           272:        if (trans) {
        !           273:            fprintf(stderr,
        !           274:            "ttcp-t: buflen=%d, nbuf=%d, align=%d/%d, port=%d",
        !           275:                buflen, nbuf, bufalign, bufoffset, port);
        !           276:            if (sockbufsize)
        !           277:                fprintf(stderr, ", sockbufsize=%d", sockbufsize);
        !           278:            fprintf(stderr, "  %s  -> %s\n", udp?"udp":"tcp", host);
        !           279:        } else {
        !           280:            fprintf(stderr,
        !           281:            "ttcp-r: buflen=%d, nbuf=%d, align=%d/%d, port=%d",
        !           282:                buflen, nbuf, bufalign, bufoffset, port);
        !           283:            if (sockbufsize)
        !           284:                fprintf(stderr, ", sockbufsize=%d", sockbufsize);
        !           285:            fprintf(stderr, "  %s\n", udp?"udp":"tcp");
        !           286:        }
        !           287: 
        !           288:        if ((fd = socket(AF_INET, udp?SOCK_DGRAM:SOCK_STREAM, 0)) < 0)
        !           289:                err("socket");
        !           290:        mes("socket");
        !           291: 
        !           292:        if (bind(fd, (struct sockaddr *) &sinme, sizeof(sinme)) < 0)
        !           293:                err("bind");
        !           294: 
        !           295: #if defined(SO_SNDBUF) || defined(SO_RCVBUF)
        !           296:        if (sockbufsize) {
        !           297:            if (trans) {
        !           298:                if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sockbufsize,
        !           299:                    sizeof sockbufsize) < 0)
        !           300:                        err("setsockopt: sndbuf");
        !           301:                mes("sndbuf");
        !           302:            } else {
        !           303:                if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &sockbufsize,
        !           304:                    sizeof sockbufsize) < 0)
        !           305:                        err("setsockopt: rcvbuf");
        !           306:                mes("rcvbuf");
        !           307:            }
        !           308:        }
        !           309: #endif
        !           310: 
        !           311:        if (!udp)  {
        !           312:            signal(SIGPIPE, sigpipe);
        !           313:            if (trans) {
        !           314:                /* We are the client if transmitting */
        !           315:                if (options)  {
        !           316: #if defined(BSD42)
        !           317:                        if( setsockopt(fd, SOL_SOCKET, options, 0, 0) < 0)
        !           318: #else /* BSD43 */
        !           319:                        if( setsockopt(fd, SOL_SOCKET, options, &one, sizeof(one)) < 0)
        !           320: #endif
        !           321:                                err("setsockopt");
        !           322:                }
        !           323: #ifdef TCP_NODELAY
        !           324:                if (nodelay) {
        !           325:                        struct protoent *p;
        !           326:                        p = getprotobyname("tcp");
        !           327:                        if( p && setsockopt(fd, p->p_proto, TCP_NODELAY, 
        !           328:                            &one, sizeof(one)) < 0)
        !           329:                                err("setsockopt: nodelay");
        !           330:                        mes("nodelay");
        !           331:                }
        !           332: #endif
        !           333:                if(connect(fd, (struct sockaddr*)&sinhim, sizeof(sinhim) ) < 0)
        !           334:                        err("connect");
        !           335:                mes("connect");
        !           336:            } else {
        !           337:                /* otherwise, we are the server and 
        !           338:                 * should listen for the connections
        !           339:                 */
        !           340: #if defined(ultrix) || defined(sgi)
        !           341:                listen(fd,1);   /* workaround for alleged u4.2 bug */
        !           342: #else
        !           343:                listen(fd,0);   /* allow a queue of 0 */
        !           344: #endif
        !           345:                if(options)  {
        !           346: #if defined(BSD42)
        !           347:                        if( setsockopt(fd, SOL_SOCKET, options, 0, 0) < 0)
        !           348: #else /* BSD43 */
        !           349:                        if( setsockopt(fd, SOL_SOCKET, options, &one, sizeof(one)) < 0)
        !           350: #endif
        !           351:                                err("setsockopt");
        !           352:                }
        !           353:                fromlen = sizeof(frominet);
        !           354:                domain = AF_INET;
        !           355:                if((fd=accept(fd, (struct sockaddr*)&frominet, (socklen_t*)&fromlen) ) < 0)
        !           356:                        err("accept");
        !           357:                { struct sockaddr_in peer;
        !           358:                  int peerlen = sizeof(peer);
        !           359:                  if (getpeername(fd, (struct sockaddr*) &peer, (socklen_t*)&peerlen) < 0) {
        !           360:                        err("getpeername");
        !           361:                  }
        !           362:                  fprintf(stderr,"ttcp-r: accept from %s\n", 
        !           363:                        inet_ntoa(peer.sin_addr));
        !           364:                }
        !           365:            }
        !           366:        }
        !           367:        prep_timer();
        !           368:        errno = 0;
        !           369:        if (sinkmode) {      
        !           370:                register int cnt;
        !           371:                if (trans)  {
        !           372:                        pattern( buf, buflen );
        !           373:                        if(udp)  (void)Nwrite( fd, buf, 4 ); /* rcvr start */
        !           374:                        while (nbuf-- && Nwrite(fd,buf,buflen) == buflen)
        !           375:                                nbytes += buflen;
        !           376:                        if(udp)  (void)Nwrite( fd, buf, 4 ); /* rcvr end */
        !           377:                } else {
        !           378:                        if (udp) {
        !           379:                            while ((cnt=Nread(fd,buf,buflen)) > 0)  {
        !           380:                                    static int going = 0;
        !           381:                                    if( cnt <= 4 )  {
        !           382:                                            if( going )
        !           383:                                                    break;      /* "EOF" */
        !           384:                                            going = 1;
        !           385:                                            prep_timer();
        !           386:                                    } else {
        !           387:                                            nbytes += cnt;
        !           388:                                    }
        !           389:                            }
        !           390:                        } else {
        !           391:                            while ((cnt=Nread(fd,buf,buflen)) > 0)  {
        !           392:                                    nbytes += cnt;
        !           393:                            }
        !           394:                        }
        !           395:                }
        !           396:        } else {
        !           397:                register int cnt;
        !           398:                if (trans)  {
        !           399:                        while((cnt=read(0,buf,buflen)) > 0 &&
        !           400:                            Nwrite(fd,buf,cnt) == cnt)
        !           401:                                nbytes += cnt;
        !           402:                }  else  {
        !           403:                        while((cnt=Nread(fd,buf,buflen)) > 0 &&
        !           404:                            write(1,buf,cnt) == cnt)
        !           405:                                nbytes += cnt;
        !           406:                }
        !           407:        }
        !           408:        if(errno) err("IO");
        !           409:        (void)read_timer(stats,sizeof(stats));
        !           410:        if(udp&&trans)  {
        !           411:                (void)Nwrite( fd, buf, 4 ); /* rcvr end */
        !           412:                (void)Nwrite( fd, buf, 4 ); /* rcvr end */
        !           413:                (void)Nwrite( fd, buf, 4 ); /* rcvr end */
        !           414:                (void)Nwrite( fd, buf, 4 ); /* rcvr end */
        !           415:        }
        !           416:        if( cput <= 0.0 )  cput = 0.001;
        !           417:        if( realt <= 0.0 )  realt = 0.001;
        !           418:        fprintf(stderr,
        !           419:                "ttcp%s: %.0f bytes in %.2f real seconds = %s/sec +++\n",
        !           420:                trans?"-t":"-r",
        !           421:                nbytes, realt, outfmt(nbytes/realt));
        !           422:        if (verbose) {
        !           423:            fprintf(stderr,
        !           424:                "ttcp%s: %.0f bytes in %.2f CPU seconds = %s/cpu sec\n",
        !           425:                trans?"-t":"-r",
        !           426:                nbytes, cput, outfmt(nbytes/cput));
        !           427:        }
        !           428:        fprintf(stderr,
        !           429:                "ttcp%s: %lu I/O calls, msec/call = %.2f, calls/sec = %.2f\n",
        !           430:                trans?"-t":"-r",
        !           431:                numCalls,
        !           432:                1024.0 * realt/((double)numCalls),
        !           433:                ((double)numCalls)/realt);
        !           434:        fprintf(stderr,"ttcp%s: %s\n", trans?"-t":"-r", stats);
        !           435:        if (verbose) {
        !           436:            fprintf(stderr,
        !           437:                "ttcp%s: buffer address %#x\n",
        !           438:                trans?"-t":"-r",
        !           439:                (unsigned int)buf);
        !           440:        }
        !           441:        exit(0);
        !           442: 
        !           443: usage:
        !           444:        fprintf(stderr,"%s", Usage);
        !           445:        exit(1);
        !           446: }
        !           447: 
        !           448: void
        !           449: err(s)
        !           450: char *s;
        !           451: {
        !           452:        fprintf(stderr,"ttcp%s: ", trans?"-t":"-r");
        !           453:        perror(s);
        !           454:        fprintf(stderr,"errno=%d\n",errno);
        !           455:        exit(1);
        !           456: }
        !           457: 
        !           458: void
        !           459: mes(s)
        !           460: char *s;
        !           461: {
        !           462:        fprintf(stderr,"ttcp%s: %s\n", trans?"-t":"-r", s);
        !           463: }
        !           464: 
        !           465: void
        !           466: pattern( cp, cnt )
        !           467: register char *cp;
        !           468: register int cnt;
        !           469: {
        !           470:        register char c;
        !           471:        c = 0;
        !           472:        while( cnt-- > 0 )  {
        !           473:                while( !isprint((c&0x7F)) )  c++;
        !           474:                *cp++ = (c++&0x7F);
        !           475:        }
        !           476: }
        !           477: 
        !           478: char *
        !           479: outfmt(b)
        !           480: double b;
        !           481: {
        !           482:     static char obuf[50];
        !           483:     switch (fmt) {
        !           484:        case 'G':
        !           485:            sprintf(obuf, "%.2f GB", b / 1024.0 / 1024.0 / 1024.0);
        !           486:            break;
        !           487:        default:
        !           488:        case 'K':
        !           489:            sprintf(obuf, "%.2f KB", b / 1024.0);
        !           490:            break;
        !           491:        case 'M':
        !           492:            sprintf(obuf, "%.2f MB", b / 1024.0 / 1024.0);
        !           493:            break;
        !           494:        case 'g':
        !           495:            sprintf(obuf, "%.2f Gbit", b * 8.0 / 1024.0 / 1024.0 / 1024.0);
        !           496:            break;
        !           497:        case 'k':
        !           498:            sprintf(obuf, "%.2f Kbit", b * 8.0 / 1024.0);
        !           499:            break;
        !           500:        case 'm':
        !           501:            sprintf(obuf, "%.2f Mbit", b * 8.0 / 1024.0 / 1024.0);
        !           502:            break;
        !           503:     }
        !           504:     return obuf;
        !           505: }
        !           506: 
        !           507: static struct  timeval time0;  /* Time at which timing started */
        !           508: static struct  rusage ru0;     /* Resource utilization at the start */
        !           509: 
        !           510: static void prusage();
        !           511: static void tvadd();
        !           512: static void tvsub();
        !           513: static void psecs();
        !           514: 
        !           515: #if defined(SYSV)
        !           516: /*ARGSUSED*/
        !           517: static
        !           518: getrusage(ignored, ru)
        !           519:     int ignored;
        !           520:     register struct rusage *ru;
        !           521: {
        !           522:     struct tms buf;
        !           523: 
        !           524:     times(&buf);
        !           525: 
        !           526:     /* Assumption: HZ <= 2147 (LONG_MAX/1000000) */
        !           527:     ru->ru_stime.tv_sec  = buf.tms_stime / HZ;
        !           528:     ru->ru_stime.tv_usec = ((buf.tms_stime % HZ) * 1000000) / HZ;
        !           529:     ru->ru_utime.tv_sec  = buf.tms_utime / HZ;
        !           530:     ru->ru_utime.tv_usec = ((buf.tms_utime % HZ) * 1000000) / HZ;
        !           531: }
        !           532: 
        !           533: /*ARGSUSED*/
        !           534: static 
        !           535: gettimeofday(tp, zp)
        !           536:     struct timeval *tp;
        !           537:     struct timezone *zp;
        !           538: {
        !           539:     tp->tv_sec = time(0);
        !           540:     tp->tv_usec = 0;
        !           541: }
        !           542: #endif /* SYSV */
        !           543: 
        !           544: /*
        !           545:  *                     P R E P _ T I M E R
        !           546:  */
        !           547: void
        !           548: prep_timer()
        !           549: {
        !           550:        gettimeofday(&time0, (struct timezone *)0);
        !           551:        getrusage(RUSAGE_SELF, &ru0);
        !           552: }
        !           553: 
        !           554: /*
        !           555:  *                     R E A D _ T I M E R
        !           556:  * 
        !           557:  */
        !           558: double
        !           559: read_timer(str,len)
        !           560: char *str;
        !           561: {
        !           562:        struct timeval timedol;
        !           563:        struct rusage ru1;
        !           564:        struct timeval td;
        !           565:        struct timeval tend, tstart;
        !           566:        char line[132];
        !           567: 
        !           568:        getrusage(RUSAGE_SELF, &ru1);
        !           569:        gettimeofday(&timedol, (struct timezone *)0);
        !           570:        prusage(&ru0, &ru1, &timedol, &time0, line);
        !           571:        (void)strncpy( str, line, len );
        !           572: 
        !           573:        /* Get real time */
        !           574:        tvsub( &td, &timedol, &time0 );
        !           575:        realt = td.tv_sec + ((double)td.tv_usec) / 1000000;
        !           576: 
        !           577:        /* Get CPU time (user+sys) */
        !           578:        tvadd( &tend, &ru1.ru_utime, &ru1.ru_stime );
        !           579:        tvadd( &tstart, &ru0.ru_utime, &ru0.ru_stime );
        !           580:        tvsub( &td, &tend, &tstart );
        !           581:        cput = td.tv_sec + ((double)td.tv_usec) / 1000000;
        !           582:        if( cput < 0.00001 )  cput = 0.00001;
        !           583:        return( cput );
        !           584: }
        !           585: 
        !           586: static void
        !           587: prusage(r0, r1, e, b, outp)
        !           588:        register struct rusage *r0, *r1;
        !           589:        struct timeval *e, *b;
        !           590:        char *outp;
        !           591: {
        !           592:        struct timeval tdiff;
        !           593:        register time_t t;
        !           594:        register char *cp;
        !           595:        register int i;
        !           596:        int ms;
        !           597: 
        !           598:        t = (r1->ru_utime.tv_sec-r0->ru_utime.tv_sec)*100+
        !           599:            (r1->ru_utime.tv_usec-r0->ru_utime.tv_usec)/10000+
        !           600:            (r1->ru_stime.tv_sec-r0->ru_stime.tv_sec)*100+
        !           601:            (r1->ru_stime.tv_usec-r0->ru_stime.tv_usec)/10000;
        !           602:        ms =  (e->tv_sec-b->tv_sec)*100 + (e->tv_usec-b->tv_usec)/10000;
        !           603: 
        !           604: #define END(x) {while(*x) x++;}
        !           605: #if defined(SYSV)
        !           606:        cp = "%Uuser %Ssys %Ereal %P";
        !           607: #else
        !           608: #if defined(sgi)               /* IRIX 3.3 will show 0 for %M,%F,%R,%C */
        !           609:        cp = "%Uuser %Ssys %Ereal %P %Mmaxrss %F+%Rpf %Ccsw";
        !           610: #else
        !           611:        cp = "%Uuser %Ssys %Ereal %P %Xi+%Dd %Mmaxrss %F+%Rpf %Ccsw";
        !           612: #endif
        !           613: #endif
        !           614:        for (; *cp; cp++)  {
        !           615:                if (*cp != '%')
        !           616:                        *outp++ = *cp;
        !           617:                else if (cp[1]) switch(*++cp) {
        !           618: 
        !           619:                case 'U':
        !           620:                        tvsub(&tdiff, &r1->ru_utime, &r0->ru_utime);
        !           621:                        sprintf(outp,"%d.%01ld", tdiff.tv_sec, tdiff.tv_usec/100000);
        !           622:                        END(outp);
        !           623:                        break;
        !           624: 
        !           625:                case 'S':
        !           626:                        tvsub(&tdiff, &r1->ru_stime, &r0->ru_stime);
        !           627:                        sprintf(outp,"%d.%01ld", tdiff.tv_sec, tdiff.tv_usec/100000);
        !           628:                        END(outp);
        !           629:                        break;
        !           630: 
        !           631:                case 'E':
        !           632:                        psecs(ms / 100, outp);
        !           633:                        END(outp);
        !           634:                        break;
        !           635: 
        !           636:                case 'P':
        !           637:                        sprintf(outp,"%d%%", (int) (t*100 / ((ms ? ms : 1))));
        !           638:                        END(outp);
        !           639:                        break;
        !           640: 
        !           641: #if !defined(SYSV)
        !           642:                case 'W':
        !           643:                        i = r1->ru_nswap - r0->ru_nswap;
        !           644:                        sprintf(outp,"%d", i);
        !           645:                        END(outp);
        !           646:                        break;
        !           647: 
        !           648:                case 'X':
        !           649:                        sprintf(outp,"%ld", t == 0 ? 0 : (r1->ru_ixrss-r0->ru_ixrss)/t);
        !           650:                        END(outp);
        !           651:                        break;
        !           652: 
        !           653:                case 'D':
        !           654:                        sprintf(outp,"%ld", t == 0 ? 0 :
        !           655:                            (r1->ru_idrss+r1->ru_isrss-(r0->ru_idrss+r0->ru_isrss))/t);
        !           656:                        END(outp);
        !           657:                        break;
        !           658: 
        !           659:                case 'K':
        !           660:                        sprintf(outp,"%ld", t == 0 ? 0 :
        !           661:                            ((r1->ru_ixrss+r1->ru_isrss+r1->ru_idrss) -
        !           662:                            (r0->ru_ixrss+r0->ru_idrss+r0->ru_isrss))/t);
        !           663:                        END(outp);
        !           664:                        break;
        !           665: 
        !           666:                case 'M':
        !           667:                        sprintf(outp,"%ld", r1->ru_maxrss/2);
        !           668:                        END(outp);
        !           669:                        break;
        !           670: 
        !           671:                case 'F':
        !           672:                        sprintf(outp,"%ld", r1->ru_majflt-r0->ru_majflt);
        !           673:                        END(outp);
        !           674:                        break;
        !           675: 
        !           676:                case 'R':
        !           677:                        sprintf(outp,"%ld", r1->ru_minflt-r0->ru_minflt);
        !           678:                        END(outp);
        !           679:                        break;
        !           680: 
        !           681:                case 'I':
        !           682:                        sprintf(outp,"%ld", r1->ru_inblock-r0->ru_inblock);
        !           683:                        END(outp);
        !           684:                        break;
        !           685: 
        !           686:                case 'O':
        !           687:                        sprintf(outp,"%ld", r1->ru_oublock-r0->ru_oublock);
        !           688:                        END(outp);
        !           689:                        break;
        !           690:                case 'C':
        !           691:                        sprintf(outp,"%ld+%ld", r1->ru_nvcsw-r0->ru_nvcsw,
        !           692:                                r1->ru_nivcsw-r0->ru_nivcsw );
        !           693:                        END(outp);
        !           694:                        break;
        !           695: #endif /* !SYSV */
        !           696:                }
        !           697:        }
        !           698:        *outp = '\0';
        !           699: }
        !           700: 
        !           701: static void
        !           702: tvadd(tsum, t0, t1)
        !           703:        struct timeval *tsum, *t0, *t1;
        !           704: {
        !           705: 
        !           706:        tsum->tv_sec = t0->tv_sec + t1->tv_sec;
        !           707:        tsum->tv_usec = t0->tv_usec + t1->tv_usec;
        !           708:        if (tsum->tv_usec > 1000000)
        !           709:                tsum->tv_sec++, tsum->tv_usec -= 1000000;
        !           710: }
        !           711: 
        !           712: static void
        !           713: tvsub(tdiff, t1, t0)
        !           714:        struct timeval *tdiff, *t1, *t0;
        !           715: {
        !           716: 
        !           717:        tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
        !           718:        tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
        !           719:        if (tdiff->tv_usec < 0)
        !           720:                tdiff->tv_sec--, tdiff->tv_usec += 1000000;
        !           721: }
        !           722: 
        !           723: static void
        !           724: psecs(l,cp)
        !           725: long l;
        !           726: register char *cp;
        !           727: {
        !           728:        register int i;
        !           729: 
        !           730:        i = l / 3600;
        !           731:        if (i) {
        !           732:                sprintf(cp,"%d:", i);
        !           733:                END(cp);
        !           734:                i = l % 3600;
        !           735:                sprintf(cp,"%d%d", (i/60) / 10, (i/60) % 10);
        !           736:                END(cp);
        !           737:        } else {
        !           738:                i = l;
        !           739:                sprintf(cp,"%d", i / 60);
        !           740:                END(cp);
        !           741:        }
        !           742:        i %= 60;
        !           743:        *cp++ = ':';
        !           744:        sprintf(cp,"%d%d", i / 10, i % 10);
        !           745: }
        !           746: 
        !           747: /*
        !           748:  *                     N R E A D
        !           749:  */
        !           750: int
        !           751: Nread( fd, buf, count )
        !           752: int fd;
        !           753: void *buf;
        !           754: int count;
        !           755: {
        !           756:        struct sockaddr_in from;
        !           757:        int len = sizeof(from);
        !           758:        register int cnt;
        !           759:        if( udp )  {
        !           760:                cnt = recvfrom( fd, buf, count, 0, (struct sockaddr *)&from, (socklen_t*)&len );
        !           761:                numCalls++;
        !           762:        } else {
        !           763:                if( b_flag )
        !           764:                        cnt = mread( fd, buf, count );  /* fill buf */
        !           765:                else {
        !           766:                        cnt = read( fd, buf, count );
        !           767:                        numCalls++;
        !           768:                }
        !           769:                if (touchdata && cnt > 0) {
        !           770:                        register int c = cnt, sum;
        !           771:                        register char *b = buf;
        !           772:                        while (c--)
        !           773:                                sum += *b++;
        !           774:                }
        !           775:        }
        !           776:        return(cnt);
        !           777: }
        !           778: 
        !           779: /*
        !           780:  *                     N W R I T E
        !           781:  */
        !           782: int
        !           783: Nwrite( fd, buf, count )
        !           784: int fd;
        !           785: void *buf;
        !           786: int count;
        !           787: {
        !           788:        register int cnt;
        !           789:        if( udp )  {
        !           790: again:
        !           791:                cnt = sendto( fd, buf, count, 0, (struct sockaddr *)&sinhim, sizeof(sinhim) );
        !           792:                numCalls++;
        !           793:                if( cnt<0 && errno == ENOBUFS )  {
        !           794:                        delay(18000);
        !           795:                        errno = 0;
        !           796:                        goto again;
        !           797:                }
        !           798:        } else {
        !           799:                cnt = write( fd, buf, count );
        !           800:                numCalls++;
        !           801:        }
        !           802:        return(cnt);
        !           803: }
        !           804: 
        !           805: void
        !           806: delay(us)
        !           807: {
        !           808:        struct timeval tv;
        !           809: 
        !           810:        tv.tv_sec = 0;
        !           811:        tv.tv_usec = us;
        !           812:        (void)select( 1, NULL, NULL, NULL, &tv );
        !           813: }
        !           814: 
        !           815: /*
        !           816:  *                     M R E A D
        !           817:  *
        !           818:  * This function performs the function of a read(II) but will
        !           819:  * call read(II) multiple times in order to get the requested
        !           820:  * number of characters.  This can be necessary because
        !           821:  * network connections don't deliver data with the same
        !           822:  * grouping as it is written with.  Written by Robert S. Miles, BRL.
        !           823:  */
        !           824: int
        !           825: mread(fd, bufp, n)
        !           826: int fd;
        !           827: register char  *bufp;
        !           828: unsigned       n;
        !           829: {
        !           830:        register unsigned       count = 0;
        !           831:        register int            nread;
        !           832: 
        !           833:        do {
        !           834:                nread = read(fd, bufp, n-count);
        !           835:                numCalls++;
        !           836:                if(nread < 0)  {
        !           837:                        perror("ttcp_mread");
        !           838:                        return(-1);
        !           839:                }
        !           840:                if(nread == 0)
        !           841:                        return((int)count);
        !           842:                count += (unsigned)nread;
        !           843:                bufp += nread;
        !           844:         } while(count < n);
        !           845: 
        !           846:        return((int)count);
        !           847: }

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