source: network-demos/ttcp/ttcp_orig/ttcp.c @ 6a19a29

4.11network-demos-4-10-branchnetwork-demos-4-8-branchnetwork-demos-4-9-branch
Last change on this file since 6a19a29 was 6a19a29, checked in by Joel Sherrill <joel.sherrill@…>, on 06/21/07 at 18:00:35

2007-06-21 Joel Sherrill <joel.sherrill@…>

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