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>