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