mirror of https://framagit.org/bortzmeyer/echoping
Removed bogus files
parent
aab38992d2
commit
e4f0e5612e
@ -1,33 +0,0 @@
|
||||
CC = gcc
|
||||
#CC = cc
|
||||
CFLAGS = -c -O
|
||||
#CFLAGS = -g -c -O0
|
||||
LD = $(CC)
|
||||
LDFLAGS = -o echoping
|
||||
|
||||
OBJS = echoping.o error.o readline.o writen.o util.o
|
||||
SOURCES = echoping.c error.c readline.c writen.c util.c inet.h
|
||||
MISC = README Makefile
|
||||
DISTRIB= echo/README echo/Makefile echo/echoping.ptk echo/echoping.c echo/error.c echo/readline.c echo/writen.c echo/util.c echo/inet.h
|
||||
|
||||
all: echoping
|
||||
|
||||
echoping: $(OBJS)
|
||||
@ echo Linking $@ with new $?
|
||||
$(LD) $(LDFLAGS) $(OBJS)
|
||||
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) $<
|
||||
|
||||
clean:
|
||||
-rm echoping $(OBJS)
|
||||
@ echo Erased
|
||||
|
||||
distrib:
|
||||
@(cd .. ; \
|
||||
tar cvf "echo/echoping.tar" $(DISTRIB); \
|
||||
gzip -v -f "echo/echoping.tar")
|
||||
|
||||
checkout:
|
||||
co -l $(SOURCES) README
|
||||
|
@ -1,120 +0,0 @@
|
||||
"echoping" is a small program to test (approximatively) performances of a
|
||||
remote host by sending it TCP "echo" packets.
|
||||
|
||||
It assumes the remote host accepts such connections. Experience show that
|
||||
most Internet routers do and many hosts also. However, some Unices are not
|
||||
shipped with this service enabled and, anyway, the administrator is always
|
||||
free to close it (I think they shouldn't). echoping has therefore less chance
|
||||
to succeed than ping or bing. (On a typical Unix box, "echo" service is
|
||||
configured in /etc/inetd.conf.)
|
||||
|
||||
In any case, be polite: don't bother the remote host with many repeated
|
||||
requests, especially with large size.
|
||||
|
||||
The current version is very rough. It was written quickly and not debugged
|
||||
in detail.
|
||||
|
||||
It appears to compile and run at least on OSF/1 3.2, Solaris (?),
|
||||
Linux 1.1, SunOS 4.1 and Ultrix 4.3. You do not have to be root to
|
||||
install it: just type make and copy the "echoping" executable anywhere you
|
||||
want. There is no man page.
|
||||
|
||||
To use it, simply:
|
||||
|
||||
% echoping machine.somewhere.org
|
||||
|
||||
or use the options before the machine name:
|
||||
|
||||
-v : verbose
|
||||
-s nnn : size of the data to send
|
||||
-n nnn : numbers of repeated tests
|
||||
-w nnn : number of seconds to wait between two tests (default is one)
|
||||
-t nnn : number of seconds to wait a reply before giving up
|
||||
-u : use UDP instead of TCP
|
||||
-d : use the "discard" service instead of echo
|
||||
-c : use the "chargen" service instead of echo
|
||||
|
||||
echoping simply shows the elapsed time, including the time to set up the TCP
|
||||
connection and to transfer the data. Therefore, it is unsuitable to physical
|
||||
line raw throughput measures (unlike bing). On the other end, the action it
|
||||
performs are close from a HTTP request and it is meaningful to use it
|
||||
(carefully) to measure Web performances.
|
||||
|
||||
With the '-n' option, you have also the minimum, maximum, average and median
|
||||
time. The median is the value such that half of the measures are under it
|
||||
and the other half is above. When you measure highly variables values, like
|
||||
it is often the case on the whole Internet, median is better than average
|
||||
to avoid "extreme" values.
|
||||
|
||||
There are many, many traps when measuring something on the Internet. Just one
|
||||
example: 'echoping -w 0 -n 4 a-sunOS-machine' and you'll see the first test
|
||||
succeed in a very short time (if you are close from the machine) and all of
|
||||
the others take a much longer time (one second). With '-w 1' (wait one second
|
||||
between tests, the default), everything works fine: it seems the sockets on
|
||||
SunOS need time to recover :-)
|
||||
|
||||
With UDP servers you can have other surprises: the first test is quite often
|
||||
much slower since inetd has to launch the process. After that, the process
|
||||
stays a while so the next texts run faster.
|
||||
|
||||
If you have the Perl/Tk <http://pubweb.bnl.gov/~ptk/> package, you can use a
|
||||
(quite rough) windowing interface, "echoping.ptk". To use it, you should
|
||||
define FLUSH_OUTPUT at the beginning of echoping.c (this seems to work
|
||||
on only a few Unices, including DEC's OSF/1).
|
||||
|
||||
Known bugs:
|
||||
|
||||
- UDP isn't really useable with large packets because of sockets
|
||||
limitations and the lack of workaround code
|
||||
|
||||
To do:
|
||||
|
||||
- display statistics even when interrupted by Control-C
|
||||
- display other calculations such as standard deviation
|
||||
- timeouts even on TCP connections
|
||||
|
||||
To measure performances on the Internet you can also see:
|
||||
|
||||
Unix:
|
||||
|
||||
- bing, a bandwidth measurement tool <ftp://ftp.ibp.fr/pub/networking>
|
||||
- ping, probably available with your system
|
||||
- traceroute, idem (otherwise, see <ftp://ftp.ee.lbl.gov/>)
|
||||
- ttcp, the best measurement tool but it needs some control over the
|
||||
two machines <ftp://ftp.arl.mil/pub/ttcp>
|
||||
- spray is a tool which I dont't know very well. It is available on some
|
||||
machines (Sun, OSF/1).
|
||||
I've also heard of but never tried:
|
||||
- NetPerf <http://www.cup.hp.com/netperf/NetperfPage.html>
|
||||
- a suite of Bandwidth Measuring programs from gnn@netcom.com
|
||||
<ftp.netcom.com/~ftp/gnn/bwmeas-0.3.tar.Z>. These are several
|
||||
programs that measure bandwidth and jitter over several kinds of
|
||||
IPC links, including TCP and UDP.
|
||||
|
||||
Macintosh:
|
||||
|
||||
- TCP Watcher, a very nice "swiss-army knife" tool, to test ping, DNS, echo.
|
||||
It includes an echo server. Available on Info-Mac in "comm/tcp".
|
||||
|
||||
Web clients:
|
||||
|
||||
- You can ping or traceroute on the Web. See
|
||||
<http://hplyot.obspm.fr/cgi-bin/nph-traceroute>, <http://www.fr.net/>,
|
||||
and <gopher://ns.urec.fr/11/Reseaux/Annuaires>.
|
||||
|
||||
|
||||
Use all of them with care, the result is not obvious to interpret.
|
||||
|
||||
And don't forget to read RFC 1470 ("Tools for Monitoring and Debugging
|
||||
TCP/IP Internets and Interconnected Devices"), specially its "Benchmark"
|
||||
section and the Richard Stevens' books (all of them), published by
|
||||
Addison-Wesley.
|
||||
|
||||
|
||||
The reference site for echoping is:
|
||||
|
||||
ftp://ftp.pasteur.fr/pub/Network/echoping
|
||||
|
||||
Stephane Bortzmeyer <bortzmeyer@pasteur.fr>. October 1995 for the
|
||||
first version. December 1995 for this one.
|
||||
|
@ -1,475 +0,0 @@
|
||||
/*
|
||||
* echoping : uses the TCP echo service to measure (roughly) response times.
|
||||
*
|
||||
* Written by Stephane Bortzmeyer <bortzmeyer@pasteur.fr>. A lot of code stolen
|
||||
* from Richard Stevens' book "Unix network programming" and Pierre Beyssac's
|
||||
* "bing" tool
|
||||
*
|
||||
*/
|
||||
|
||||
char *progname;
|
||||
unsigned short timeout_flag;
|
||||
|
||||
#include "inet.h"
|
||||
|
||||
/*
|
||||
* An option to define only if you want to drive echoping from another
|
||||
* process. Useless but harmless otherwise. In practice, while OSF/1 is happy
|
||||
* with it, SunOS refuses to use fflush on a NULL and Linux fails.
|
||||
*/
|
||||
#undef FLUSH_OUTPUT
|
||||
|
||||
void
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
extern int opterr;
|
||||
extern int optopt;
|
||||
|
||||
extern int tvcmp();
|
||||
|
||||
char ch;
|
||||
|
||||
int sockfd;
|
||||
struct hostent *hostptr;
|
||||
struct sockaddr_in serv_addr;
|
||||
struct sockaddr_in udp_cli_addr; /* client's Internet socket
|
||||
* addr */
|
||||
struct servent *sp;
|
||||
int verbose = FALSE;
|
||||
char *server_address;
|
||||
u_int addr;
|
||||
struct in_addr *ptr;
|
||||
int n, nr;
|
||||
char *sendline, recvline[MAXLINE + 1];
|
||||
struct timeval newtv, oldtv;
|
||||
|
||||
unsigned int size = DEFLINE;
|
||||
unsigned int number = 1;
|
||||
unsigned int wait = 1;
|
||||
unsigned char fill;
|
||||
unsigned short fill_requested = 0;
|
||||
unsigned int i, j = 0;
|
||||
unsigned int successes = 0;
|
||||
struct result {
|
||||
unsigned short valid;
|
||||
struct timeval timevalue;
|
||||
};
|
||||
struct result results[MAXNUMBER];
|
||||
struct timeval good_results[MAXNUMBER];
|
||||
|
||||
struct timeval max, min, total, median, temp;
|
||||
|
||||
void to_alarm(); /* our alarm() signal handler */
|
||||
void interrupted();
|
||||
unsigned int timeout = 10;
|
||||
unsigned short timeout_requested = 0;
|
||||
|
||||
char *port_name = ECHO_TCP_PORT;
|
||||
unsigned short port_to_use = USE_ECHO;
|
||||
unsigned short udp = 0;
|
||||
unsigned short ttcp = 0;
|
||||
|
||||
unsigned short stop_at_newlines = 1;
|
||||
|
||||
null_timeval.tv_sec = 0;
|
||||
null_timeval.tv_usec = 0;
|
||||
max_timeval.tv_sec = 1000000000;
|
||||
max_timeval.tv_usec = 999999;
|
||||
total = null_timeval;
|
||||
median = null_timeval;
|
||||
max = null_timeval;
|
||||
min = max_timeval;
|
||||
|
||||
for (i = 0; i <= MAXNUMBER; i++) {
|
||||
results[i].valid = 0;
|
||||
}
|
||||
progname = argv[0];
|
||||
while ((ch = getopt(argc, argv, "vs:n:w:dcrut:f:")) != EOF) {
|
||||
switch (ch) {
|
||||
case 'v':
|
||||
verbose = TRUE;
|
||||
break;
|
||||
case 'r':
|
||||
ttcp = 1;
|
||||
break;
|
||||
case 'u':
|
||||
udp = 1;
|
||||
break;
|
||||
case 'd':
|
||||
port_name = DISCARD_TCP_PORT;
|
||||
port_to_use = USE_DISCARD;
|
||||
break;
|
||||
case 'c':
|
||||
port_name = CHARACTER_GENERATOR_TCP_PORT;
|
||||
port_to_use = USE_CHARGEN;
|
||||
stop_at_newlines = 0;
|
||||
break;
|
||||
case 'f':
|
||||
fill = optarg;
|
||||
fill_requested = 1;
|
||||
break;
|
||||
case 's':
|
||||
size = atoi(optarg);
|
||||
if (size > MAXLINE) {
|
||||
(void) fprintf(stderr,
|
||||
"%s: packet size too large, max is %d.\n",
|
||||
progname, MAXLINE);
|
||||
exit(1);
|
||||
}
|
||||
if (size <= 0) {
|
||||
(void) fprintf(stderr,
|
||||
"%s: illegal packet size.\n", progname);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 't':
|
||||
timeout = atoi(optarg);
|
||||
timeout_requested = 1;
|
||||
if (size <= 0) {
|
||||
(void) fprintf(stderr,
|
||||
"%s: illegal timeout.\n", progname);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'n':
|
||||
number = atoi(optarg);
|
||||
if (number > MAXNUMBER) {
|
||||
(void) fprintf(stderr,
|
||||
"%s: number of iterations too large, max is %d.\n",
|
||||
progname, MAXNUMBER);
|
||||
exit(1);
|
||||
}
|
||||
if (number <= 0) {
|
||||
(void) fprintf(stderr,
|
||||
"%s: illegal number of iterations.\n", progname);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'w':
|
||||
wait = atoi(optarg);
|
||||
if (wait < 0) {
|
||||
(void) fprintf(stderr,
|
||||
"%s: illegal waiting time.\n", progname);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
}
|
||||
if (udp && (port_to_use == USE_CHARGEN)) {
|
||||
(void) fprintf(stderr,
|
||||
"%s: I don't know how to use CHARGEN with UDP.\n", progname);
|
||||
exit(1);
|
||||
}
|
||||
if (!udp && (timeout_requested)) {
|
||||
(void) fprintf(stderr,
|
||||
"%s: Time out ignored for TCP connections.\n", progname);
|
||||
exit(1);
|
||||
}
|
||||
if (udp && ttcp) {
|
||||
(void) fprintf(stderr,
|
||||
"%s: UDP and T/TCP are incompatible.\n", progname);
|
||||
exit(1);
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
if (argc != 1) {
|
||||
usage();
|
||||
}
|
||||
if (verbose) {
|
||||
printf("\nThis is %s, version %s.\n\n", progname, VERSION);
|
||||
}
|
||||
server = argv[0];
|
||||
signal(SIGINT, interrupted);
|
||||
if ((addr = inet_addr(server)) == INADDR_NONE) {
|
||||
if ((hostptr = gethostbyname(server)) == NULL) {
|
||||
err_quit("gethostbyname error for host: %s %s",
|
||||
server, sys_err_str());
|
||||
}
|
||||
server_address = *(hostptr->h_addr_list); /* First item of the
|
||||
* list */
|
||||
/*
|
||||
* addr = (u_long) *server_address; /* hostptr->h_addr_list
|
||||
* points actually to u_longs, not strings
|
||||
*/
|
||||
/* ptr.s_addr = addr; */
|
||||
ptr = (struct in_addr *) server_address; /* hostptr->h_addr_list
|
||||
* points actually to
|
||||
* u_longs, not strings */
|
||||
addr = ptr->s_addr;
|
||||
} else {
|
||||
ptr = (struct in_addr *) malloc(sizeof(struct in_addr));
|
||||
ptr->s_addr = addr;
|
||||
}
|
||||
if (!udp) {
|
||||
if ((sp = getservbyname(port_name, "tcp")) == NULL) {
|
||||
err_quit("tcp_open: unknown service: %s/tcp", port_name);
|
||||
}
|
||||
} else {
|
||||
if ((sp = getservbyname(port_name, "udp")) == NULL) {
|
||||
err_quit("tcp_open: unknown service: %s/udp", port_name);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Fill in the structure "serv_addr" with the address of the server
|
||||
* that we want to connect with.
|
||||
*/
|
||||
|
||||
bzero((char *) &serv_addr, sizeof(serv_addr));
|
||||
serv_addr.sin_family = AF_INET;
|
||||
serv_addr.sin_addr.s_addr = addr;
|
||||
serv_addr.sin_port = sp->s_port;
|
||||
|
||||
if (!fill_requested) {
|
||||
sendline = random_string(size);
|
||||
} else {
|
||||
sendline = (char *) malloc(size);
|
||||
for (i = 0; i < size; i++)
|
||||
sendline[i] = fill;
|
||||
}
|
||||
n = strlen(sendline) + 1;
|
||||
|
||||
for (i = 1; i <= number; i++) {
|
||||
|
||||
if (!udp) {
|
||||
/*
|
||||
* Open a TCP socket (an Internet stream socket).
|
||||
*/
|
||||
|
||||
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
|
||||
err_sys("Can't open stream socket");
|
||||
} else {
|
||||
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
|
||||
err_sys("Can't open datagram socket");
|
||||
/* Bind socket for reply. Not necessary? */
|
||||
bzero((char *) &udp_cli_addr, sizeof(udp_cli_addr));
|
||||
udp_cli_addr.sin_family = AF_INET;
|
||||
udp_cli_addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
udp_cli_addr.sin_port = htons(0);
|
||||
if (bind(sockfd, (struct sockaddr *) & udp_cli_addr,
|
||||
sizeof(udp_cli_addr)) < 0) {
|
||||
err_sys("bind error");
|
||||
}
|
||||
}
|
||||
if (verbose) {
|
||||
printf("Trying to connect to internet address %s to transmit %u bytes...\n",
|
||||
inet_ntoa(*ptr), size);
|
||||
#ifdef FLUSH_OUTPUT
|
||||
if (fflush((FILE *) NULL) != 0) {
|
||||
err_sys("I cannot flush");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
(void) gettimeofday(&oldtv, (struct timezone *) NULL);
|
||||
|
||||
if (!ttcp) {
|
||||
/*
|
||||
* Connect to the server.
|
||||
*/
|
||||
|
||||
if (connect(sockfd, (struct sockaddr *) & serv_addr,
|
||||
sizeof(serv_addr)) < 0)
|
||||
err_sys("Can't connect to server");
|
||||
if (verbose) {
|
||||
printf("Connected...\n");
|
||||
#ifdef FLUSH_OUTPUT
|
||||
if (fflush((FILE *) NULL) != 0) {
|
||||
err_sys("I cannot flush");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
/* Not T/TCP */
|
||||
else {
|
||||
/* No initial connection */
|
||||
}
|
||||
if ((port_to_use == USE_ECHO) || (port_to_use == USE_DISCARD)) {
|
||||
if (ttcp) {
|
||||
if (sendto(sockfd, sendline, n, MSG_EOF,
|
||||
(struct sockaddr *) & serv_addr, sizeof(serv_addr)) != n)
|
||||
err_sys("sendto error on socket");
|
||||
if (verbose) {
|
||||
printf("T/TCP connection done\n");
|
||||
}
|
||||
} else if (!udp) {
|
||||
/* Write something to the server */
|
||||
if (writen(sockfd, sendline, n) != n)
|
||||
err_sys("writen error on socket");
|
||||
} else {
|
||||
/*
|
||||
* if (sendto(sockfd, sendline, n, 0,
|
||||
* &serv_addr, sizeof(serv_addr)) != n)
|
||||
* err_sys("sendto error on socket");
|
||||
*/
|
||||
if (send(sockfd, sendline, n, 0) != n)
|
||||
err_sys("send error on socket");
|
||||
}
|
||||
if (verbose) {
|
||||
printf("Sent (%d bytes)...\n", n);
|
||||
#ifdef FLUSH_OUTPUT
|
||||
if (fflush((FILE *) NULL) != 0) {
|
||||
err_sys("I cannot flush");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if ((port_to_use == USE_ECHO) || (port_to_use == USE_CHARGEN)) {
|
||||
if (!udp) {
|
||||
/* Read from the server */
|
||||
nr = readline(sockfd, recvline, n, stop_at_newlines);
|
||||
} else {
|
||||
signal(SIGALRM, to_alarm);
|
||||
timeout_flag = 0; /* for signal handler */
|
||||
alarm(timeout);
|
||||
nr = recv(sockfd, recvline, n, 0);
|
||||
/*
|
||||
* nr = recvfrom(sockfd, recvline, n, 0,
|
||||
* (struct sockaddr *) 0, (int *) 0);
|
||||
* recvfrom fails on SunOS on connected
|
||||
* sockets.
|
||||
*/
|
||||
/*
|
||||
* BUG: in UDP, we should loop to read: we
|
||||
* can have several reads necessary.
|
||||
*/
|
||||
alarm(0);
|
||||
if ((nr < 0) && (errno == EINTR) && (timeout_flag)) {
|
||||
nr = n;
|
||||
printf("Timeout\n");
|
||||
#ifdef FLUSH_OUTPUT
|
||||
if (fflush((FILE *) NULL) != 0) {
|
||||
err_sys("I cannot flush");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (nr < 0 || nr != n)
|
||||
err_sys("readline error: %d bytes read, %d bytes requested", nr, n);
|
||||
}
|
||||
/* That's all, folks */
|
||||
close(sockfd);
|
||||
|
||||
(void) gettimeofday(&newtv, (struct timezone *) NULL);
|
||||
temp = newtv;
|
||||
tvsub(&temp, &oldtv);
|
||||
if (!timeout_flag) {
|
||||
tvadd(&total, &temp);
|
||||
|
||||
/* Check */
|
||||
if (port_to_use == USE_ECHO) {
|
||||
if (strcmp(sendline, recvline) != 0) {
|
||||
printf(" I wrote:\n%s\n", sendline);
|
||||
printf(" and I got back:\n%s\n", recvline);
|
||||
err_quit("Strange server");
|
||||
}
|
||||
if (verbose) {
|
||||
printf("Checked\n");
|
||||
#ifdef FLUSH_OUTPUT
|
||||
if (fflush((FILE *) NULL) != 0) {
|
||||
err_sys("I cannot flush");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (port_to_use == USE_CHARGEN) {
|
||||
sendline = CHARGENERATED;
|
||||
recvline[strlen(sendline)] = 0;
|
||||
if (strcmp(sendline, recvline) != 0) {
|
||||
printf(" I got back:\n%s\n", recvline);
|
||||
printf(" instead of the most common:\n%s\n", sendline);
|
||||
err_ret("Strange server");
|
||||
}
|
||||
if (verbose) {
|
||||
printf("Checked\n");
|
||||
}
|
||||
}
|
||||
tvsub(&newtv, &oldtv);
|
||||
tvmin(&min, &newtv);
|
||||
tvmax(&max, &newtv);
|
||||
printf("Elapsed time: %d.%06d seconds\n", newtv.tv_sec, newtv.tv_usec);
|
||||
#ifdef FLUSH_OUTPUT
|
||||
if (fflush((FILE *) NULL) != 0) {
|
||||
err_sys("I cannot flush");
|
||||
}
|
||||
#endif
|
||||
results[i - 1].valid = 1;
|
||||
results[i - 1].timevalue = newtv;
|
||||
successes++;
|
||||
}
|
||||
if (number > 1) {
|
||||
sleep(wait);
|
||||
}
|
||||
}
|
||||
printstats:
|
||||
/* if ((number > 1) && ((!udp) || (successes > 0))) { */
|
||||
if (successes > 1) {
|
||||
printf("---\n");
|
||||
if (successes < number)
|
||||
printf("Warning: %d messages lost (%d %%)\n", number - successes,
|
||||
((number - successes) * 100) / number);
|
||||
printf("Minimum time: %d.%06d seconds (%.0f bytes per sec.)\n",
|
||||
min.tv_sec, min.tv_usec, (double) size / tv2double(min));
|
||||
printf("Maximum time: %d.%06d seconds (%.0f bytes per sec.)\n",
|
||||
max.tv_sec, max.tv_usec, (double) size / tv2double(max));
|
||||
tvavg(&total, successes);
|
||||
printf("Average time: %d.%06d seconds (%.0f bytes per sec.)\n",
|
||||
total.tv_sec, total.tv_usec, (double) size / tv2double(total));
|
||||
for (i = 0; i < number; i++) {
|
||||
if (results[i].valid)
|
||||
good_results[j++] = results[i].timevalue;
|
||||
}
|
||||
if (successes != j) /* Bug! */
|
||||
err_quit("successes (%d) is different from j (%d)", successes, j);
|
||||
qsort(good_results, successes, sizeof(struct timeval), tvcmp);
|
||||
/*
|
||||
* for (i = 1; i <= number; i++) { printf("---\nTime %d th:
|
||||
* %d.%06d seconds\n", i, results[i-1].tv_sec,
|
||||
* results[i-1].tv_usec); }
|
||||
*/
|
||||
if ((successes % 2) == 1) {
|
||||
/*
|
||||
* printf("Searching good_results[%d]\n", (successes
|
||||
* + 1) / 2 - 1);
|
||||
*/
|
||||
median = good_results[((successes + 1) / 2 - 1)];
|
||||
} else {
|
||||
/*
|
||||
* printf("Searching good_results[%d] and [%d]\n",
|
||||
* (successes / 2) - 1, successes / 2);
|
||||
*/
|
||||
tvadd(&median, &good_results[(successes / 2) - 1]);
|
||||
tvadd(&median, &good_results[successes / 2]);
|
||||
tvavg(&median, 2);
|
||||
}
|
||||
printf("Median time: %d.%06d seconds (%.0f bytes per sec.)\n",
|
||||
median.tv_sec, median.tv_usec, (double) size / tv2double(median));
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Signal handler for timeouts (SIGALRM). This function is called when the
|
||||
* alarm() value that was set counts down to zero. This indicates that we
|
||||
* haven't received a response from the server to the last datagram we sent.
|
||||
* All we do is set a flag and return from the signal handler. The occurrence
|
||||
* of the signal interrupts the recvfrom() system call (errno = EINTR) above,
|
||||
* and we then check the tout_flag flag.
|
||||
*/
|
||||
|
||||
void
|
||||
to_alarm()
|
||||
{
|
||||
timeout_flag = 1; /* set flag for function above */
|
||||
}
|
||||
|
||||
void
|
||||
interrupted()
|
||||
{
|
||||
printf("Interrupted by user\n");
|
||||
exit(1);
|
||||
}
|
@ -1,314 +0,0 @@
|
||||
#!/usr/local/bin/perl -w
|
||||
|
||||
require 5.001;
|
||||
use Tk;
|
||||
use Tk::IO;
|
||||
require 'sys/socket.ph';
|
||||
|
||||
# Let's be paranoid
|
||||
use strict;
|
||||
|
||||
require "newgetopt.pl";
|
||||
&NGetOpt (("geometry=s", "font=s", "background=s", "bg=s", "foreground=s", "fg=s", "title=s"));
|
||||
|
||||
my $default_host;
|
||||
if (@ARGV) {
|
||||
$default_host = shift (@ARGV);
|
||||
#TODO: shouldn't we try to echoping it right now?
|
||||
}
|
||||
else {
|
||||
$default_host = "localhost";
|
||||
}
|
||||
if (@ARGV) {
|
||||
print STDERR "Ignoring extra arguments \"" . join (' ', @ARGV) . "\"\n";
|
||||
}
|
||||
|
||||
my $top = MainWindow->new;
|
||||
|
||||
if ($main::opt_geometry) {
|
||||
$top->geometry ($main::opt_geometry);
|
||||
}
|
||||
if ($main::opt_title) {
|
||||
$top->title ($main::opt_title);
|
||||
}
|
||||
else {
|
||||
$top->title ("EchoPing Driver");
|
||||
}
|
||||
#TODO: how to set background, font, etc for all the widgets?
|
||||
if ($main::opt_bg) {
|
||||
$main::opt_background = $main::opt_bg;
|
||||
}
|
||||
if ($main::opt_background) {
|
||||
$top->configure (-background => $main::opt_background);
|
||||
}
|
||||
if ($main::opt_fg) {
|
||||
$main::opt_foreground = $main::opt_fg;
|
||||
}
|
||||
if ($main::opt_foreground) {
|
||||
$top->configure (-foreground => $main::opt_foreground);
|
||||
}
|
||||
if ($main::opt_font) {
|
||||
$top->configure (-font => $main::opt_font);
|
||||
}
|
||||
|
||||
#TODO : on line help with context => 'connection refused' will give an explanation
|
||||
|
||||
$main::echoping = &find_pg ("echoping");
|
||||
if (! $main::echoping) {
|
||||
print STDERR "Cannot find the echoping program in the path.\n";
|
||||
exit 1;
|
||||
#TODO: a nice pop-up window with an hypertext link to the FTP server :-)
|
||||
}
|
||||
|
||||
my $message;
|
||||
open (ECHOPING, "$main::echoping -v localhost 2>&1 |") || &panic ("Cannot echoping");
|
||||
my $result = <ECHOPING>;
|
||||
chop $result;
|
||||
if ($result) { # Something was wrong
|
||||
if ($result =~ /Connection refused/) {
|
||||
$message = "localhost refused echo: egoist!";
|
||||
#TODO: better explanations
|
||||
}
|
||||
else {
|
||||
$message = "Problem localhost: $result";
|
||||
}
|
||||
}
|
||||
else {
|
||||
$message = <ECHOPING>;
|
||||
}
|
||||
close (ECHOPING);
|
||||
|
||||
# Some useful declarations
|
||||
my $text;
|
||||
my $results;
|
||||
my $number;
|
||||
my $size;
|
||||
my $delay;
|
||||
|
||||
my $frame1 = $top->Frame(-borderwidth => '2m');
|
||||
$frame1->pack(-fill => 'x');
|
||||
|
||||
# Entry field
|
||||
my $entry = $frame1->Entry(-relief => 'sunken', -width => 45);
|
||||
my $label = $frame1->Label(-text => 'Enter host name');
|
||||
$label->pack(-side => 'left');
|
||||
$entry->pack(-side => 'left');
|
||||
$entry->insert('insert', $default_host);
|
||||
$entry->selection ('range', 0, length ($default_host));
|
||||
$entry->focus;
|
||||
# I believe the following binding is necessary only on OSF/1?
|
||||
$entry->bind('<Delete>' => 'Backspace');
|
||||
|
||||
# Doit button
|
||||
my $doit = $frame1->Button(-text => 'Do it',
|
||||
-command => sub {doit ($top, $entry, $results, $number->get, $size->get, $delay->get, $text)});
|
||||
$doit->pack(-side => 'left', -fill => 'x', -padx => '2m');
|
||||
$top->bind ('<Return>' => sub {doit ($top, $entry, $results, $number->get, $size->get, $delay->get, $text)});
|
||||
my $cancel = $frame1->Button(-text => 'Cancel',
|
||||
-command => sub {$main::cancel_requested = 1;});
|
||||
#TODO: Cancel should test if an operation is in progress, otherwise, it will
|
||||
# be "recorded" for the next time.
|
||||
$cancel->pack(-side => 'left', -fill => 'x', -padx => '2m');
|
||||
|
||||
my $frame2 = $top->Frame(-borderwidth => '2m');
|
||||
$frame2->pack(-fill => 'x');
|
||||
#TODO: every number should be in the settings section at the beginning
|
||||
$number = $frame2->Scale(-from => '1', -to => '10', -orient => 'horizontal', -label => 'Number of connections');
|
||||
$number->set ('1');
|
||||
$number->pack (-side => 'top', -fill => 'x');
|
||||
$size = $frame2->Scale(-from => '1', -to => '1000', '-length' => '500', -orient => 'horizontal', -label => 'Size of packets');
|
||||
$size->set ('256'); #TODO: finds a way to enter value directly
|
||||
$size->pack (-side => 'top', -fill => 'x');
|
||||
$delay = $frame2->Scale(-from => '0', -to => '20', '-length' => '500', -orient => 'horizontal', -label => 'Delay between connections');
|
||||
$delay->set ('1');
|
||||
$delay->pack (-side => 'top', -fill => 'x');
|
||||
|
||||
my $frame3 = $top->Frame(-borderwidth => '2m');
|
||||
$frame3->pack (-fill => 'both', -expand => 'yes');
|
||||
|
||||
# Status text
|
||||
$text = $frame3->Label(
|
||||
-justify => 'center',
|
||||
-text => "$message",
|
||||
);
|
||||
$text->pack(-side => 'top', -fill => 'none', -expand => 'no');
|
||||
|
||||
# Results text with scrollbar
|
||||
#TODO: nice tags and hypertext tags
|
||||
$results = $frame3->Text(-relief => 'sunken', -state => 'disabled');
|
||||
my $scrollbar = $frame3->Scrollbar(-command => ['yview', $results]);
|
||||
$results->configure(-yscrollcommand => ['set', $scrollbar]);
|
||||
$scrollbar->pack(-side => 'right', -fill => 'y');
|
||||
$results->pack(-side => 'left', -expand => 'yes', -fill => 'both');
|
||||
|
||||
my $frame4 = $top->Frame(-borderwidth => '2m');
|
||||
$frame4->pack(-fill => 'x');
|
||||
|
||||
# Quit button
|
||||
my $quit = $frame4->Button(-text => 'Quit', -command => sub {exit 0;});
|
||||
$quit->pack(-side => 'bottom', -fill => 'x');
|
||||
#TODO: a "clear results" button and a "shrink results"
|
||||
|
||||
@main::to_disable = ($entry, $doit, $quit, $number, $size, $delay);
|
||||
@main::to_mark = ($label, $frame1, $frame2, $frame3, $frame4);
|
||||
|
||||
#TODO: better resizing: the Quit button disappears when shrinking
|
||||
|
||||
MainLoop;
|
||||
|
||||
sub doit {
|
||||
my ($top_window, $entry, $text, $number, $size, $delay, $label) = @_;
|
||||
my ($date) = `date`;
|
||||
my $line;
|
||||
my $index;
|
||||
chop $date;
|
||||
my $host = $entry->get;
|
||||
&disable (@main::to_disable);
|
||||
&mark_used (@main::to_mark);
|
||||
&status ($label, "Looking up $host");
|
||||
$label->update;
|
||||
my ($name, $aliases, $addrtype, $length, @addrs) = gethostbyname ($host);
|
||||
if (! $name) {
|
||||
$text->configure (-state => 'normal');
|
||||
$text->insert ('end', "\n----------\nHost $host unknown at $date\n\n");
|
||||
$text->configure (-state => 'disabled');
|
||||
&status ($label, "Idle");
|
||||
&enable (@main::to_disable);
|
||||
&mark_unused (@main::to_mark);
|
||||
return;
|
||||
}
|
||||
my $address = join ('.', unpack('C4', $addrs[0]));
|
||||
&status ($label, "Echopinging $name");
|
||||
my $handle = Tk::IO->open ("$main::echoping -v -n $number -s $size -w $delay $address 2>&1 |") || &panic ("Cannot echoping");
|
||||
# Some messages to ignore. May be we should check them?
|
||||
my $garbage = $handle->readline;
|
||||
$garbage = $handle->readline;
|
||||
$garbage = $handle->readline;
|
||||
$text->configure (-state => 'normal');
|
||||
$text->insert ('end', "\n----------\n$main::echoping of $host ($name [" .
|
||||
$address . "])\n" .
|
||||
" (with $size bytes and $delay s interval)\n" .
|
||||
" at $date:\n");
|
||||
$text->configure (-state => 'disabled');
|
||||
while ($line = $handle->readline) {
|
||||
#TODO: cancel will only be taken into account when there is something to read :-(
|
||||
# may be more feedback would be good?
|
||||
if ($main::cancel_requested) {
|
||||
last; # The only problem is that we lose the last line received
|
||||
# but the test is here to have more opportunities to
|
||||
# catch a cancel.
|
||||
}
|
||||
if ($line =~ /^Trying to connect to internet address/) {
|
||||
&status ($label, "Trying to connect");
|
||||
next;
|
||||
}
|
||||
elsif ($line =~ /^Connected/) {
|
||||
&status ($label, "Connected");
|
||||
next;
|
||||
}
|
||||
elsif ($line =~ /^Sent/) {
|
||||
&status ($label, "Data sent");
|
||||
next;
|
||||
}
|
||||
elsif ($line =~ /^Checked/) {
|
||||
&status ($label, "Data received and checked");
|
||||
next;
|
||||
}
|
||||
elsif ($line =~ /^Elapsed time/) {
|
||||
&status ($label, "Sleeping");
|
||||
}
|
||||
$text->configure (-state => 'normal');
|
||||
$text->insert ('end', $line);
|
||||
#$text->update;
|
||||
#TODO: scroll to see the end since it doesn't seem automatic
|
||||
$text->configure (-state => 'disabled');
|
||||
}
|
||||
$text->configure (-state => 'normal');
|
||||
if ($main::cancel_requested) {
|
||||
undef $main::cancel_requested;
|
||||
$text->insert ('end', "\nCancelled by user\n");
|
||||
}
|
||||
$handle->close;
|
||||
$date = `date`;
|
||||
chop $date;
|
||||
&status ($label, "Idle");
|
||||
$text->insert ('end', "Over at $date\n");
|
||||
$text->configure (-state => 'disabled');
|
||||
&enable (@main::to_disable);
|
||||
&mark_unused (@main::to_mark);
|
||||
}
|
||||
|
||||
sub status {
|
||||
my ($label, $message) = @_;
|
||||
$label->configure (-text=>"Status: $message");
|
||||
}
|
||||
|
||||
# Disable a list of widgets
|
||||
sub disable {
|
||||
my (@widgets) = @_;
|
||||
my $w;
|
||||
for $w (@widgets) {
|
||||
$w->configure (-state=>'disabled', -cursor=>'watch');
|
||||
}
|
||||
}
|
||||
|
||||
# Enable a list of widgets
|
||||
sub enable {
|
||||
my (@widgets) = @_;
|
||||
my $w;
|
||||
for $w (@widgets) {
|
||||
$w->configure (-state=>'normal', -cursor=>'top_left_arrow');
|
||||
}
|
||||
}
|
||||
|
||||
# Mark a list of widgets as used
|
||||
sub mark_used {
|
||||
my (@widgets) = @_;
|
||||
my $w;
|
||||
for $w (@widgets) {
|
||||
$w->configure (-cursor=>'watch');
|
||||
}
|
||||
}
|
||||
|
||||
# Mark a list of widgets as unused
|
||||
sub mark_unused {
|
||||
my (@widgets) = @_;
|
||||
my $w;
|
||||
for $w (@widgets) {
|
||||
$w->configure (-cursor=>'top_left_arrow');
|
||||
}
|
||||
}
|
||||
|
||||
# The "find_pg" (find program) code has been stolen from "aub"
|
||||
# and lightly adapted.
|
||||
sub find_pg {
|
||||
#
|
||||
# find_pg: find the specified executable on this machine, if possible.
|
||||
#
|
||||
# We try using which first, assuming that if the desired executable is in
|
||||
# our path, it's the one we want.
|
||||
#
|
||||
# If it's not in our path, we try whereis, returning the first program
|
||||
# whereis names for us which is executable.
|
||||
#
|
||||
# If we can't find what we need, we return an empty string.
|
||||
#
|
||||
|
||||
my ($pg) = @_;
|
||||
my ($ex) = 1;
|
||||
my ($try, @found);
|
||||
|
||||
return $pg if ($pg =~ m/^\//); # Absolute paths know best
|
||||
chop($try = `which $pg`);
|
||||
return $try if ($try =~ m/^\//);
|
||||
|
||||
chop($try = `whereis $pg`);
|
||||
if ($try =~ m/^$pg:\s+\//) {
|
||||
@found = split(/\s/, $try);
|
||||
$ex++ while (! -x $found[$ex]);
|
||||
return $found[$ex] unless ($found[$ex] eq "");
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
@ -1,129 +0,0 @@
|
||||
#include "inet.h"
|
||||
|
||||
|
||||
/* Most of error-handling routines stolen from Stevens' books */
|
||||
|
||||
/*
|
||||
* Recoverable error. Print a message, and return to caller.
|
||||
*
|
||||
* err_ret(str, arg1, arg2, ...)
|
||||
*
|
||||
* The string "str" must specify the conversion specification for any args.
|
||||
*/
|
||||
|
||||
/* VARARGS1 */
|
||||
err_ret(va_alist)
|
||||
va_dcl
|
||||
{
|
||||
va_list args;
|
||||
char *fmt;
|
||||
|
||||
va_start(args);
|
||||
fmt = va_arg(args, char *);
|
||||
vfprintf(stderr, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
my_perror();
|
||||
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fatal error. Print a message and terminate. Don't dump core and don't
|
||||
* print the system's errno value.
|
||||
*
|
||||
* err_quit(str, arg1, arg2, ...)
|
||||
*
|
||||
* The string "str" must specify the conversion specification for any args.
|
||||
*/
|
||||
|
||||
/* VARARGS1 */
|
||||
err_quit(va_alist)
|
||||
va_dcl
|
||||
{
|
||||
va_list args;
|
||||
char *fmt;
|
||||
|
||||
va_start(args);
|
||||
fmt = va_arg(args, char *);
|
||||
vfprintf(stderr, fmt, args);
|
||||
fputc('\n', stderr);
|
||||
va_end(args);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fatal error related to a system call. Print a message and terminate.
|
||||
* Don't dump core, but do print the system's errno value and its associated
|
||||
* message.
|
||||
*
|
||||
* err_sys(str, arg1, arg2, ...)
|
||||
*
|
||||
* The string "str" must specify the conversion specification for any args.
|
||||
*/
|
||||
|
||||
/* VARARGS1 */
|
||||
err_sys(va_alist)
|
||||
va_dcl
|
||||
{
|
||||
va_list args;
|
||||
char *fmt;
|
||||
|
||||
va_start(args);
|
||||
fmt = va_arg(args, char *);
|
||||
vfprintf(stderr, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
my_perror();
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
my_perror()
|
||||
{
|
||||
fprintf(stderr, " %s\n", sys_err_str());
|
||||
}
|
||||
|
||||
usage()
|
||||
{
|
||||
fprintf(stderr, "Usage: %s [-v] [-t timeout] [-c] [-d] [-u] [-s size] [-n number] [-w delay] server-name\n", progname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
extern int errno; /* Unix error number */
|
||||
extern int sys_nerr; /* # of error message strings in sys table */
|
||||
#ifdef __FreeBSD__
|
||||
#else
|
||||
extern char *sys_errlist[]; /* the system error message table */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Return a string containing some additional operating-system dependent
|
||||
* information. Note that different versions of UNIX assign different
|
||||
* meanings to the same value of "errno" (compare errno's starting with 35
|
||||
* between System V and BSD, for example). This means that if an error
|
||||
* condition is being sent to another UNIX system, we must interpret the
|
||||
* errno value on the system that generated the error, and not just send the
|
||||
* decimal value of errno to the other system.
|
||||
*/
|
||||
|
||||
char *
|
||||
sys_err_str()
|
||||
{
|
||||
static char msgstr[200];
|
||||
|
||||
if (errno != 0) {
|
||||
if (errno > 0 && errno < sys_nerr)
|
||||
sprintf(msgstr, "(%s)", sys_errlist[errno]);
|
||||
else
|
||||
sprintf(msgstr, "(errno = %d)", errno);
|
||||
} else {
|
||||
msgstr[0] = '\0';
|
||||
}
|
||||
|
||||
return (msgstr);
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
/*
|
||||
* Definitions for TCP and UDP client/server programs.
|
||||
*/
|
||||
|
||||
#define VERSION "1.3.0-beta-T/TCP"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <varargs.h>
|
||||
#include <sys/time.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
#ifndef SIGALRM /* Linux Slackware... */
|
||||
#define SIGALRM 14 /* alarm clock timeout */
|
||||
#endif
|
||||
#ifndef SIGINT /* Linux Slackware... */
|
||||
#define SIGINT 2 /* interrupt, generated from terminal special char */
|
||||
#endif
|
||||
|
||||
#ifndef INADDR_NONE
|
||||
#define INADDR_NONE (-1)
|
||||
#endif
|
||||
|
||||
struct timeval null_timeval;
|
||||
struct timeval max_timeval;
|
||||
|
||||
#define ECHO_TCP_PORT "echo"
|
||||
#define DISCARD_TCP_PORT "discard"
|
||||
#define CHARACTER_GENERATOR_TCP_PORT "chargen"
|
||||
|
||||
#define USE_ECHO 1
|
||||
#define USE_DISCARD 2
|
||||
#define USE_CHARGEN 3
|
||||
|
||||
#define CHARGENERATED " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefg";
|
||||
|
||||
char *server;
|
||||
|
||||
char *sys_err_str();
|
||||
|
||||
char *random_string();
|
||||
|
||||
double tv2double();
|
||||
|
||||
#define DEFLINE 256
|
||||
#define MAXLINE 1500
|
||||
#define MAXNUMBER 20
|
||||
|
||||
extern char *progname;
|
@ -1,35 +0,0 @@
|
||||
/*
|
||||
* Read a line from a descriptor. Read the line one byte at a time, looking
|
||||
* for the newline. We store the newline in the buffer, then follow it with
|
||||
* a null (the same as fgets(3)). We return the number of characters up to,
|
||||
* but not including, the null (the same as strlen(3)). If ln == 0, we treat
|
||||
* newline as an ordinary charracter.
|
||||
*/
|
||||
|
||||
int
|
||||
readline(fd, ptr, maxlen, ln)
|
||||
int fd;
|
||||
char *ptr;
|
||||
int maxlen;
|
||||
unsigned short ln;
|
||||
{
|
||||
int n, rc;
|
||||
char c;
|
||||
|
||||
for (n = 1; n < maxlen; n++) {
|
||||
if ((rc = read(fd, &c, 1)) == 1) {
|
||||
*ptr++ = c;
|
||||
if (c == '\n' && ln == 1)
|
||||
break;
|
||||
} else if (rc == 0) {
|
||||
if (n == 1)
|
||||
return (0); /* EOF, no data read */
|
||||
else
|
||||
break; /* EOF, some data was read */
|
||||
} else
|
||||
return (-1); /* error */
|
||||
}
|
||||
|
||||
*ptr = 0;
|
||||
return (n);
|
||||
}
|
@ -1,129 +0,0 @@
|
||||
#include "inet.h"
|
||||
|
||||
#define STATES 32
|
||||
|
||||
#include <time.h>
|
||||
|
||||
char *
|
||||
random_string(unsigned length)
|
||||
{
|
||||
|
||||
char *state = (char *) malloc(sizeof(char) * STATES);
|
||||
char *result = (char *) malloc(length);
|
||||
int i, number;
|
||||
unsigned seed = (unsigned) time((time_t *) NULL);
|
||||
|
||||
/* printf ("Seed is %u\n", seed); */
|
||||
|
||||
/* Initialize random generator */
|
||||
(void) initstate(seed, state, STATES);
|
||||
|
||||
for (i = 0; i < (length - 1); i++) {
|
||||
number = (random() % 94) + 33;
|
||||
/* printf ("Number for %d is %d\n", i, number); */
|
||||
result[i] = (char) number;
|
||||
}
|
||||
result[length - 1] = '\0';
|
||||
|
||||
/* printf ("Result is %s\n", result); */
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* tvsub -- Subtract 2 timeval structs: out = out - in. Out is assumed to be
|
||||
* >= in. Comes from the bing program.
|
||||
*/
|
||||
void
|
||||
tvsub(out, in)
|
||||
struct timeval *out, *in;
|
||||
{
|
||||
if ((out->tv_usec -= in->tv_usec) < 0) {
|
||||
--out->tv_sec;
|
||||
out->tv_usec += 1000000;
|
||||
}
|
||||
out->tv_sec -= in->tv_sec;
|
||||
}
|
||||
|
||||
/* tvadd -- Adds 2 timeval structs: out = out + in. */
|
||||
void
|
||||
tvadd(out, in)
|
||||
struct timeval *out, *in;
|
||||
{
|
||||
if ((out->tv_usec += in->tv_usec) >= 1000000) {
|
||||
++out->tv_sec;
|
||||
out->tv_usec -= 1000000;
|
||||
}
|
||||
out->tv_sec += in->tv_sec;
|
||||
}
|
||||
|
||||
/* tvavg -- Averages a timeval struct */
|
||||
void
|
||||
tvavg(out, number)
|
||||
struct timeval *out;
|
||||
int number;
|
||||
{
|
||||
double result;
|
||||
/*
|
||||
* out->tv_sec = out->tv_sec/number; out->tv_usec =
|
||||
* out->tv_usec/number;
|
||||
*/
|
||||
result = (1000000 * out->tv_sec + out->tv_usec) / number;
|
||||
/* printf ("Result of average is %f\n", result) */ ;
|
||||
out->tv_sec = (long) (result / 1000000);
|
||||
out->tv_usec = (long) (result - (out->tv_sec * 1000000));
|
||||
}
|
||||
|
||||
/* tvcmp -- Compares two timeval structs */
|
||||
int
|
||||
tvcmp(left, right)
|
||||
struct timeval *left, *right;
|
||||
{
|
||||
if (left->tv_sec < right->tv_sec) {
|
||||
return -1;
|
||||
}
|
||||
if (left->tv_sec > right->tv_sec) {
|
||||
return 1;
|
||||
}
|
||||
if (left->tv_usec < right->tv_usec) {
|
||||
return -1;
|
||||
}
|
||||
if (left->tv_usec > right->tv_usec) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/* tvmin */
|
||||
int
|
||||
tvmin(champion, challenger)
|
||||
struct timeval *champion, *challenger;
|
||||
{
|
||||
if (tvcmp(champion, challenger) == 1) {
|
||||
champion->tv_sec = challenger->tv_sec;
|
||||
champion->tv_usec = challenger->tv_usec;
|
||||
}
|
||||
}
|
||||
|
||||
/* tvmax */
|
||||
int
|
||||
tvmax(champion, challenger)
|
||||
struct timeval *champion, *challenger;
|
||||
{
|
||||
if (tvcmp(champion, challenger) == -1) {
|
||||
champion->tv_sec = challenger->tv_sec;
|
||||
champion->tv_usec = challenger->tv_usec;
|
||||
}
|
||||
}
|
||||
|
||||
double
|
||||
tv2double(tv)
|
||||
struct timeval tv;
|
||||
{
|
||||
double result;
|
||||
result = (((((double) tv.tv_sec) * 1000000.0) + (double) tv.tv_usec) / 1000000.0);
|
||||
/* printf ("Double is %9.3f\n", result); */
|
||||
return result;
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
/*
|
||||
* Write "n" bytes to a descriptor. Use in place of write() when fd is a
|
||||
* stream socket.
|
||||
*/
|
||||
|
||||
int
|
||||
writen(fd, ptr, nbytes)
|
||||
register int fd;
|
||||
register char *ptr;
|
||||
register int nbytes;
|
||||
{
|
||||
int nleft, nwritten;
|
||||
|
||||
nleft = nbytes;
|
||||
while (nleft > 0) {
|
||||
nwritten = write(fd, ptr, nleft);
|
||||
if (nwritten <= 0)
|
||||
return (nwritten); /* error */
|
||||
|
||||
nleft -= nwritten;
|
||||
ptr += nwritten;
|
||||
}
|
||||
return (nbytes - nleft);
|
||||
}
|
Loading…
Reference in New Issue