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

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