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

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 */
1.1.1.1.2.2! misho      55: #include <unistd.h>
        !            56: #include <string.h>
        !            57: #include <stdlib.h>
1.1       misho      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();
1.1.1.1.2.2! misho     136: void pattern();
1.1       misho     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: 
1.1.1.1.2.2! misho     150: int
1.1       misho     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);
1.1.1.1.2.2! misho     253:                sinme.sin_family = AF_INET;     /* Solaris needs this */
1.1       misho     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)
1.1.1.1.2.2! misho     268:                buf += (bufalign
        !           269:                        -((unsigned long)buf % bufalign)
        !           270:                        + bufoffset) % bufalign;
1.1       misho     271: 
                    272:        if (trans) {
1.1.1.1.2.2! misho     273:            fprintf(stderr,
1.1       misho     274:            "ttcp-t: buflen=%d, nbuf=%d, align=%d/%d, port=%d",
                    275:                buflen, nbuf, bufalign, bufoffset, port);
                    276:            if (sockbufsize)
1.1.1.1.2.2! misho     277:                fprintf(stderr, ", sockbufsize=%d", sockbufsize);
        !           278:            fprintf(stderr, "  %s  -> %s\n", udp?"udp":"tcp", host);
1.1       misho     279:        } else {
1.1.1.1.2.2! misho     280:            fprintf(stderr,
1.1       misho     281:            "ttcp-r: buflen=%d, nbuf=%d, align=%d/%d, port=%d",
                    282:                buflen, nbuf, bufalign, bufoffset, port);
                    283:            if (sockbufsize)
1.1.1.1.2.2! misho     284:                fprintf(stderr, ", sockbufsize=%d", sockbufsize);
        !           285:            fprintf(stderr, "  %s\n", udp?"udp":"tcp");
1.1       misho     286:        }
                    287: 
                    288:        if ((fd = socket(AF_INET, udp?SOCK_DGRAM:SOCK_STREAM, 0)) < 0)
                    289:                err("socket");
                    290:        mes("socket");
                    291: 
1.1.1.1.2.2! misho     292:        if (bind(fd, (struct sockaddr *) &sinme, sizeof(sinme)) < 0)
1.1       misho     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
1.1.1.1.2.2! misho     333:                if(connect(fd, (struct sockaddr*)&sinhim, sizeof(sinhim) ) < 0)
1.1       misho     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: 
1.1.1.1.2.2! misho     465: void
1.1       misho     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':
1.1.1.1.2.2! misho     649:                        sprintf(outp,"%ld", t == 0 ? 0 : (r1->ru_ixrss-r0->ru_ixrss)/t);
1.1       misho     650:                        END(outp);
                    651:                        break;
                    652: 
                    653:                case 'D':
1.1.1.1.2.2! misho     654:                        sprintf(outp,"%ld", t == 0 ? 0 :
1.1       misho     655:                            (r1->ru_idrss+r1->ru_isrss-(r0->ru_idrss+r0->ru_isrss))/t);
                    656:                        END(outp);
                    657:                        break;
                    658: 
                    659:                case 'K':
1.1.1.1.2.2! misho     660:                        sprintf(outp,"%ld", t == 0 ? 0 :
1.1       misho     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':
1.1.1.1.2.2! misho     667:                        sprintf(outp,"%ld", r1->ru_maxrss/2);
1.1       misho     668:                        END(outp);
                    669:                        break;
                    670: 
                    671:                case 'F':
1.1.1.1.2.2! misho     672:                        sprintf(outp,"%ld", r1->ru_majflt-r0->ru_majflt);
1.1       misho     673:                        END(outp);
                    674:                        break;
                    675: 
                    676:                case 'R':
1.1.1.1.2.2! misho     677:                        sprintf(outp,"%ld", r1->ru_minflt-r0->ru_minflt);
1.1       misho     678:                        END(outp);
                    679:                        break;
                    680: 
                    681:                case 'I':
1.1.1.1.2.2! misho     682:                        sprintf(outp,"%ld", r1->ru_inblock-r0->ru_inblock);
1.1       misho     683:                        END(outp);
                    684:                        break;
                    685: 
                    686:                case 'O':
1.1.1.1.2.2! misho     687:                        sprintf(outp,"%ld", r1->ru_oublock-r0->ru_oublock);
1.1       misho     688:                        END(outp);
                    689:                        break;
                    690:                case 'C':
1.1.1.1.2.2! misho     691:                        sprintf(outp,"%ld+%ld", r1->ru_nvcsw-r0->ru_nvcsw,
1.1       misho     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:  */
1.1.1.1.2.2! misho     750: int
1.1       misho     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:  */
1.1.1.1.2.2! misho     782: int
1.1       misho     783: Nwrite( fd, buf, count )
                    784: int fd;
                    785: void *buf;
                    786: int count;
                    787: {
                    788:        register int cnt;
                    789:        if( udp )  {
                    790: again:
1.1.1.1.2.2! misho     791:                cnt = sendto( fd, buf, count, 0, (struct sockaddr *)&sinhim, sizeof(sinhim) );
1.1       misho     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;
1.1.1.1.2.2! misho     812:        (void)select( 1, NULL, NULL, NULL, &tv );
1.1       misho     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>