$NetBSD: patch-ab,v 1.4 2019/06/15 15:01:03 christos Exp $ 1. handle SIGCLD portably 2. define a large enough value for SO_LINGER that does not fail 3. add a runtime option -U --- nttcp.c.orig 2000-12-18 05:16:54.000000000 -0500 +++ nttcp.c 2019-06-15 10:56:28.798775017 -0400 @@ -136,9 +136,9 @@ #endif /* aix */ /*====================================================================*/ -#if defined(FreeBSD) +#ifndef SIGCLD #define SIGCLD SIGCHLD -#endif /*FreeBSD*/ +#endif /*SIGCLD*/ /*====================================================================*/ #if defined(BSD42) @@ -268,6 +268,7 @@ \t-n# number of source bufs written to network (default 2048)\n\ \t-u use UDP instead of TCP\n\ \t-g#us gap in micro seconds between UDP packets (default 0s)\n\ +\t-U# run until a number of seconds have elapsed\n\ \t-d set SO_DEBUG in sockopt\n\ \t-D don't buffer TCP writes (sets TCP_NODELAY socket option)\n\ \t-w# set the send buffer space to #kilobytes, which is\n\ @@ -310,9 +311,15 @@ setitimer(ITIMER_REAL, &itval, Nil(struct itimerval)) #define Suspend(msec) SetItVal(msec); pause() +/* + * we use 32767 (9 hours) because this is the largest implementation-specific + * value that we can since on the BSD's the kernel linger value is + * unsigned short, on opensolaris is int, and on linux is unsigned long + * scaled by HZ. + */ struct linger Ling = { 1, /* option on */ - 1000000 /* linger time, for our control connection */ + 32767 /* linger time, for our control connection */ }; /* global variables needed by StartTimer, StopTimer */ @@ -346,6 +353,7 @@ int FixedDataSize; /* if>0: calc BufCnt/BufLen from this */ int Window, SndWin, RcvWin; /* TCP window sizes */ int Verbose; /* ==1: more diagnostics */ + int RunTime; /* approximate runtime in seconds */ char *MulticastChannel; /* we send multicast traffic */ short MulticastPort; int GapLength; /* Gap length between packets */ @@ -496,6 +504,13 @@ SysCalls=0; } +int CheckTimer() { + TimeVal now; + + gettimeofday(&now, (struct timezone *)0); + return opt.RunTime < (now.tv_sec - time0.tv_sec); +} + void StopTimer(double *cput, double *realt) { /* delivers in cput: the amount of cpu time in seconds * in realt: the real time in seconds @@ -878,6 +893,7 @@ opt->Verbose=0; /* ==1: more diagnostics */ opt->GapLength=0; /* no delay, send as fast as possible */ opt->inetd= 0; /* ==1: run in inetd mode */ + opt->RunTime = 0; /* run effectively forever (ie BufCnt is limiting factor) */ opt->Service= GetService(); /* the service-port to listen to */ opt->MulticastChannel= NULL; opt->MulticastPort= 0; @@ -1013,6 +1029,10 @@ #endif /*MULTICAST*/ break; } + case 'U': + GetSizeValue(&argc, &argv, &opt->RunTime, 1000000000, + "runtime"); + break; default: { strcpy(MsgBuf, "unknown option: "); strncat(MsgBuf, argv[0], sizeof(MsgBuf)-strlen(MsgBuf)-1); @@ -1427,6 +1447,10 @@ sprintf(OptBuf, "-g%d", opt.GapLength); StrVecAppend(RemOpt, OptBuf); } + if (opt.RunTime > 0) { + sprintf(OptBuf, "-U%d", opt.RunTime); + StrVecAppend(RemOpt, OptBuf); + } if (opt.MulticastChannel) { sprintf(OptBuf, "-m%s:%d", opt.MulticastChannel, opt.MulticastPort); @@ -1781,9 +1805,17 @@ else Pattern(buf, opt.BufLen); StartTimer(); - while (n-- && Nwrite(fd, buf, opt.BufLen) == opt.BufLen) { + while (Nwrite(fd, buf, opt.BufLen) == opt.BufLen) { nBytes+= opt.BufLen; nBuffer++; + if (opt.RunTime == 0) { + if (--n == 0) + break; + } else { + /* XXX: tune how often to check if timer has expired? */ + if ((nBuffer % 100 == 0) && CheckTimer()) + break; + } } StopTimer(&cput, &realt); opt.GapLength= 0; @@ -1797,9 +1829,17 @@ nBytes= 0; nBuffer= 0; StartTimer(); - while (n-- && Nwrite(fd, buf, opt.BufLen) == opt.BufLen) { + while (Nwrite(fd, buf, opt.BufLen) == opt.BufLen) { nBytes+= opt.BufLen; nBuffer++; + if (opt.RunTime == 0) { + if (--n == 0) + break; + } else { + /* XXX: tune how often to check if timer has expired? */ + if ((nBuffer % 100 == 0) && CheckTimer()) + break; + } } StopTimer(&cput, &realt); }