source: network-demos/ttcp/ttcp_orig/ttcp.c @ 556c269

4.11network-demos-4-10-branchnetwork-demos-4-9-branch
Last change on this file since 556c269 was 556c269, checked in by Joel Sherrill <joel.sherrill@…>, on Aug 21, 2008 at 4:40:18 PM

2008-08-21 Joel Sherrill <joel.sherrill@…>

  • ttcp_orig/ttcp.c: Fix warning.
  • 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;
596int len;
597{
598        struct timeval timedol;
599        struct rusage ru1;
600        struct timeval td;
601        struct timeval tend, tstart;
602        char line[132];
603
604        getrusage(RUSAGE_SELF, &ru1);
605        gettimeofday(&timedol, (struct timezone *)0);
606        prusage(&ru0, &ru1, &timedol, &time0, line);
607        (void)strncpy( str, line, len );
608
609        /* Get real time */
610        tvsub( &td, &timedol, &time0 );
611        realt = td.tv_sec + ((double)td.tv_usec) / 1000000;
612
613        /* Get CPU time (user+sys) */
614        tvadd( &tend, &ru1.ru_utime, &ru1.ru_stime );
615        tvadd( &tstart, &ru0.ru_utime, &ru0.ru_stime );
616        tvsub( &td, &tend, &tstart );
617        cput = td.tv_sec + ((double)td.tv_usec) / 1000000;
618        if( cput < 0.00001 )  cput = 0.00001;
619        return( cput );
620}
621
622static void
623prusage(r0, r1, e, b, outp)
624        register struct rusage *r0, *r1;
625        struct timeval *e, *b;
626        char *outp;
627{
628        struct timeval tdiff;
629        register time_t t;
630        register char *cp;
631        register int i;
632        int ms;
633
634        t = (r1->ru_utime.tv_sec-r0->ru_utime.tv_sec)*100+
635            (r1->ru_utime.tv_usec-r0->ru_utime.tv_usec)/10000+
636            (r1->ru_stime.tv_sec-r0->ru_stime.tv_sec)*100+
637            (r1->ru_stime.tv_usec-r0->ru_stime.tv_usec)/10000;
638        ms =  (e->tv_sec-b->tv_sec)*100 + (e->tv_usec-b->tv_usec)/10000;
639
640#define END(x)  {while(*x) x++;}
641#if defined(SYSV)
642        cp = "%Uuser %Ssys %Ereal %P";
643#else
644#if defined(sgi)                /* IRIX 3.3 will show 0 for %M,%F,%R,%C */
645        cp = "%Uuser %Ssys %Ereal %P %Mmaxrss %F+%Rpf %Ccsw";
646#else
647        cp = "%Uuser %Ssys %Ereal %P %Xi+%Dd %Mmaxrss %F+%Rpf %Ccsw";
648#endif
649#endif
650        for (; *cp; cp++)  {
651                if (*cp != '%')
652                        *outp++ = *cp;
653                else if (cp[1]) switch(*++cp) {
654
655                case 'U':
656                        tvsub(&tdiff, &r1->ru_utime, &r0->ru_utime);
657                        sprintf(outp,"%ld.%01ld", tdiff.tv_sec, tdiff.tv_usec/100000);
658                        END(outp);
659                        break;
660
661                case 'S':
662                        tvsub(&tdiff, &r1->ru_stime, &r0->ru_stime);
663                        sprintf(outp,"%ld.%01ld", tdiff.tv_sec, tdiff.tv_usec/100000);
664                        END(outp);
665                        break;
666
667                case 'E':
668                        psecs(ms / 100, outp);
669                        END(outp);
670                        break;
671
672                case 'P':
673                        sprintf(outp,"%d%%", (int) (t*100 / ((ms ? ms : 1))));
674                        END(outp);
675                        break;
676
677#if !defined(SYSV)
678                case 'W':
679                        i = r1->ru_nswap - r0->ru_nswap;
680                        sprintf(outp,"%d", i);
681                        END(outp);
682                        break;
683
684                case 'X':
685                        sprintf(outp,"%ld", t == 0 ? 0 : (r1->ru_ixrss-r0->ru_ixrss)/t);
686                        END(outp);
687                        break;
688
689                case 'D':
690                        sprintf(outp,"%ld", t == 0 ? 0 :
691                            (r1->ru_idrss+r1->ru_isrss-(r0->ru_idrss+r0->ru_isrss))/t);
692                        END(outp);
693                        break;
694
695                case 'K':
696                        sprintf(outp,"%ld", t == 0 ? 0 :
697                            ((r1->ru_ixrss+r1->ru_isrss+r1->ru_idrss) -
698                            (r0->ru_ixrss+r0->ru_idrss+r0->ru_isrss))/t);
699                        END(outp);
700                        break;
701
702                case 'M':
703                        sprintf(outp,"%d", r1->ru_maxrss/2);
704                        END(outp);
705                        break;
706
707                case 'F':
708                        sprintf(outp,"%d", r1->ru_majflt-r0->ru_majflt);
709                        END(outp);
710                        break;
711
712                case 'R':
713                        sprintf(outp,"%d", r1->ru_minflt-r0->ru_minflt);
714                        END(outp);
715                        break;
716
717                case 'I':
718                        sprintf(outp,"%d", r1->ru_inblock-r0->ru_inblock);
719                        END(outp);
720                        break;
721
722                case 'O':
723                        sprintf(outp,"%d", r1->ru_oublock-r0->ru_oublock);
724                        END(outp);
725                        break;
726                case 'C':
727                        sprintf(outp,"%d+%d", r1->ru_nvcsw-r0->ru_nvcsw,
728                                r1->ru_nivcsw-r0->ru_nivcsw );
729                        END(outp);
730                        break;
731#endif /* !SYSV */
732                }
733        }
734        *outp = '\0';
735}
736
737static void
738tvadd(tsum, t0, t1)
739        struct timeval *tsum, *t0, *t1;
740{
741
742        tsum->tv_sec = t0->tv_sec + t1->tv_sec;
743        tsum->tv_usec = t0->tv_usec + t1->tv_usec;
744        if (tsum->tv_usec > 1000000)
745                tsum->tv_sec++, tsum->tv_usec -= 1000000;
746}
747
748static void
749tvsub(tdiff, t1, t0)
750        struct timeval *tdiff, *t1, *t0;
751{
752
753        tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
754        tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
755        if (tdiff->tv_usec < 0)
756                tdiff->tv_sec--, tdiff->tv_usec += 1000000;
757}
758
759static void
760psecs(l,cp)
761long l;
762register char *cp;
763{
764        register int i;
765
766        i = l / 3600;
767        if (i) {
768                sprintf(cp,"%d:", i);
769                END(cp);
770                i = l % 3600;
771                sprintf(cp,"%d%d", (i/60) / 10, (i/60) % 10);
772                END(cp);
773        } else {
774                i = l;
775                sprintf(cp,"%d", i / 60);
776                END(cp);
777        }
778        i %= 60;
779        *cp++ = ':';
780        sprintf(cp,"%d%d", i / 10, i % 10);
781}
782
783/*
784 *                      N R E A D
785 */
786int Nread( fd, buf, count )
787int fd;
788void *buf;
789int count;
790{
791        struct sockaddr_in from;
792        socklen_t len = sizeof(from);
793        register int cnt;
794        if( udp )  {
795                cnt = recvfrom( fd, buf, count, 0, (struct sockaddr *)&from, &len );
796                numCalls++;
797        } else {
798                if( b_flag )
799                        cnt = mread( fd, buf, count );  /* fill buf */
800                else {
801                        cnt = read( fd, buf, count );
802                        numCalls++;
803                }
804                if (touchdata && cnt > 0) {
805                        register int c = cnt, sum;
806                        register char *b = buf;
807                        while (c--)
808                                sum += *b++;
809                }
810        }
811        return(cnt);
812}
813
814/*
815 *                      N W R I T E
816 */
817int Nwrite( fd, buf, count )
818int fd;
819void *buf;
820int count;
821{
822        register int cnt;
823        if( udp )  {
824again:
825                cnt = sendto( fd, buf, count, 0, sinhim_p, sizeof(sinhim) );
826                numCalls++;
827                if( cnt<0 && errno == ENOBUFS )  {
828                        printf("ttcp: out of buffers -- delaying\n"); /*JRS*/
829                        delay(18000);
830                        errno = 0;
831                        goto again;
832                }
833        } else {
834                cnt = write( fd, buf, count );
835                numCalls++;
836        }
837        return(cnt);
838}
839
840void
841delay(int us)
842{
843        struct timeval tv;
844
845        tv.tv_sec = 0;
846        tv.tv_usec = us;
847        (void)select( 1, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
848}
849
850/*
851 *                      M R E A D
852 *
853 * This function performs the function of a read(II) but will
854 * call read(II) multiple times in order to get the requested
855 * number of characters.  This can be necessary because
856 * network connections don't deliver data with the same
857 * grouping as it is written with.  Written by Robert S. Miles, BRL.
858 */
859int
860mread(fd, bufp, n)
861int fd;
862register char   *bufp;
863unsigned        n;
864{
865        register unsigned       count = 0;
866        register int            nread;
867
868        do {
869                nread = read(fd, bufp, n-count);
870                numCalls++;
871                if(nread < 0)  {
872                        perror("ttcp_mread");
873                        return(-1);
874                }
875                if(nread == 0)
876                        return((int)count);
877                count += (unsigned)nread;
878                bufp += nread;
879         } while(count < n);
880
881        return((int)count);
882}
Note: See TracBrowser for help on using the repository browser.