source: network-demos/ttcp/ttcp_orig/ttcp.c @ 5ee0701

4.11network-demos-4-10-branchnetwork-demos-4-8-branchnetwork-demos-4-9-branch
Last change on this file since 5ee0701 was 5ee0701, checked in by Joel Sherrill <joel.sherrill@…>, on Aug 16, 2007 at 5:27:52 PM

2007-08-16 Joel Sherrill <joel.sherrill@…>

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