]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Removed tcp-banger* and pconn-banger tools (#1236)
authorAmos Jeffries <squid3@treenet.co.nz>
Tue, 17 Jan 2023 02:19:01 +0000 (02:19 +0000)
committerSquid Anubis <squid-anubis@squid-cache.org>
Tue, 17 Jan 2023 02:19:10 +0000 (02:19 +0000)
We do not have enough resources/demand for maintaining these tools, they
do require maintenance, and there are better tools available.

* tcp-banger2 is not built by default and probably could not be built at
  all since at least 2006 commit 5679212.

* tcp-banger3 lacked build rules since inception (1998 commit 2742510)
  and probably could not be built manually (by mimicking tcp-banger2
  build commands) without warnings since 2002 commit 88d8a2a.

* pconn-banger lacked build rules since inception (1997 commit eb5f55b)
  and probably could not be built manually since at least 2007 commit
  cc192b5.

* tcp-banger.pl has portability and code quality issues; its basic
  functionality is supported by squidclient, wget, curl, and others.

Co-authored-by: Alex Rousskov <rousskov@measurement-factory.com>
scripts/Makefile.am
scripts/tcp-banger.pl [deleted file]
test-suite/Makefile.am
test-suite/pconn-banger.c [deleted file]
test-suite/tcp-banger2.c [deleted file]
test-suite/tcp-banger3.c [deleted file]

index 816830e56d6420989ae96715bb84b6785387a946..6f3adb916a9882c06903c970a6c631c918dcc16d 100644 (file)
@@ -10,7 +10,7 @@ EXTRA_DIST    = AnnounceCache.pl access-log-matrix.pl cache-compare.pl \
                fileno-to-pathname.pl flag_truncs.pl icp-test.pl \
                find-alive.pl trace-job.pl trace-master.pl \
                trace-context.pl \
-               icpserver.pl tcp-banger.pl udp-banger.pl upgrade-1.0-store.pl \
+               icpserver.pl udp-banger.pl upgrade-1.0-store.pl \
                update-contributors.pl \
                calc-must-ids.pl calc-must-ids.sh
 
diff --git a/scripts/tcp-banger.pl b/scripts/tcp-banger.pl
deleted file mode 100755 (executable)
index 24a7bc6..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/usr/local/bin/perl
-#
-## Copyright (C) 1996-2022 The Squid Software Foundation and contributors
-##
-## Squid software is distributed under GPLv2+ license and includes
-## contributions from numerous individuals and organizations.
-## Please see the COPYING and CONTRIBUTORS files for details.
-##
-
-# tcp-banger.pl
-#
-# Duane Wessels, Dec 1995
-#
-# Usage: tcp-banger.pl [host [port]] < url-list
-#
-# Sends a continuous stream of HTTP proxy requests to a cache.  Stdin is a
-# list of URLs to request.  Run N of these at the same time to simulate a
-# heavy client load.
-#
-# NOTE: does not simulate "real-world" events such as aborted requests
-# (connections) and other network problems.
-
-$|=1;
-
-$host=(shift || 'localhost') ;
-$port=(shift || '3128') ;
-
-require 'sys/socket.ph';
-
-$sockaddr = 'S n a4 x8';
-($name, $aliases, $proto) = getprotobyname("tcp");
-($fqdn, $aliases, $type, $len, $thataddr) = gethostbyname($host);
-$thissock = pack($sockaddr, &AF_INET, 0, "\0\0\0\0");
-$that = pack($sockaddr, &AF_INET, $port, $thataddr);
-
-while (<>) {
-    chop ($url = $_);
-
-    die "socket: $!\n" unless
-        socket (SOCK, &AF_INET, &SOCK_STREAM, $proto);
-    die "bind: $!\n" unless
-        bind (SOCK, $thissock);
-    die "$host:$port: $!\n" unless
-        connect (SOCK, $that);
-    select (SOCK); $| = 1;
-    select (STDOUT);
-
-    print SOCK "GET $url HTTP/1.0\r\nAccept: */*\r\n\r\n";
-    $_ = <SOCK>;
-    ($ver,$code,$junk) = split;
-    printf "%s %s\n", $code ? $code : 'FAIL', $url;
-    1 while (read(SOCK,$_,4096));
-    close SOCK;
-}
index 5fbdc5ecbf41f509d4cb11947d868281a59e1aa0..123d9305bd3322b9a227e3d44181cfef33fc9df7 100644 (file)
@@ -18,7 +18,7 @@ LDADD = \
        $(COMPAT_LIB) \
        $(XTRA_LIBS)
 
-EXTRA_PROGRAMS = mem_node_test splay tcp-banger2
+EXTRA_PROGRAMS = mem_node_test splay
 
 EXTRA_DIST = \
        $(srcdir)/squidconf/* \
@@ -54,9 +54,6 @@ check_PROGRAMS += \
                syntheticoperators \
                VirtualDeleteOperator
 
-
-tcp_banger2_LDADD = $(top_builddir)/lib/libmiscutil.la
-
 #do not include stub_libmem.cc here, as it would override libmem.la in
 # several tests whose purpose is testing libmem itself.
 STUBS = \
diff --git a/test-suite/pconn-banger.c b/test-suite/pconn-banger.c
deleted file mode 100644 (file)
index f45eca3..0000000
+++ /dev/null
@@ -1,588 +0,0 @@
-/*
- * Copyright (C) 1996-2022 The Squid Software Foundation and contributors
- *
- * Squid software is distributed under GPLv2+ license and includes
- * contributions from numerous individuals and organizations.
- * Please see the COPYING and CONTRIBUTORS files for details.
- */
-
-#include "squid.h"
-
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#if HAVE_STRING_H
-#include <string.h>
-#endif
-#if HAVE_STRINGS_H
-#include <strings.h>
-#endif
-#if HAVE_BSTRING_H
-#include <bstring.h>
-#endif
-#if HAVE_SIGNAL_H
-#include <signal.h>
-#endif
-#if HAVE_TIME_H
-#include <time.h>
-#endif
-#if HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-#if HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-#if HAVE_ARPA_INET_H
-#include <arpa/inet.h>
-#endif
-#if HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#if HAVE_CTYPE_H
-#include <ctype.h>
-#endif
-#if HAVE_ASSERT_H
-#include <assert.h>
-#endif
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-
-#define PROXY_PORT "3128"
-#define PROXY_ADDR "127.0.0.1"
-#define MAX_FDS 1024
-#define READ_BUF_SZ 4096
-#define min(x,y) ((x)<(y)? (x) : (y))
-
-static int proxy_port = PROXY_PORT;
-static char *proxy_addr = PROXY_ADDR;
-static char *progname;
-static int noutstanding = 0;
-static int done_reading_urls = 0;
-static int opt_ims = 0;
-static int opt_checksum = 0;
-static int opt_reopen = 1;
-static int max_outstanding = 10;
-static time_t lifetime = 60;
-static const char *const crlf = "\r\n";
-static int trace_fd = -1;
-static int total_bytes_read = 0;
-
-#define REPLY_HDR_SZ 8192
-
-struct _r {
-    char url[1024];
-    int content_length;
-    int hdr_length;
-    int hdr_offset;
-    int bytes_read;
-    char reply_hdrs[REPLY_HDR_SZ];
-    struct _r *next;
-    long sum;
-    long validsize;
-    long validsum;
-};
-
-static struct _r *Requests;
-
-char *
-mkrfc850(t)
-time_t *t;
-{
-    static char buf[128];
-    struct tm *gmt = gmtime(t);
-    buf[0] = '\0';
-    (void) strftime(buf, 127, "%A, %d-%b-%y %H:%M:%S GMT", gmt);
-    return buf;
-}
-
-char *
-mime_headers_end(const char *mime)
-{
-    const char *p1, *p2;
-    const char *end = NULL;
-
-    p1 = strstr(mime, "\n\r\n");
-    p2 = strstr(mime, "\n\n");
-
-    if (p1 && p2)
-        end = p1 < p2 ? p1 : p2;
-    else
-        end = p1 ? p1 : p2;
-    if (end)
-        end += (end == p1 ? 3 : 2);
-
-    return (char *) end;
-}
-
-void
-sig_intr(int sig)
-{
-    fprintf(stderr, "\rWaiting for open connections to finish...\n");
-    signal(sig, SIG_DFL);
-    done_reading_urls = 1;
-}
-
-int
-open_http_socket(void)
-{
-    int s;
-    struct addrinfo *AI = NULL;
-    struct addrinfo hints;
-
-    memset(&hints, '\0', sizeof(struct addrinfo));
-    hints.ai_flags = AI_NUMERICHOST|AI_NUMERICSERV;
-    hints.ai_family = AF_UNSPEC;
-    hints.ai_socktype = SOCK_STREAM;
-
-    getaddrinfo(proxy_addr, proxy_port, &hints, AI);
-
-    if ((s = socket(AI->ai_family, AI->ai_socktype, AI->ai_protocol)) < 0) {
-        perror("socket");
-        s = -1;
-    } else if (connect(s, AI->ai_addr, AI->ai_addrlen) < 0) {
-        close(s);
-        perror("connect");
-        s = -1;
-    }
-
-    freeaddrinfo(AI);
-    return s;
-}
-
-int
-send_request(int fd, const char *data)
-{
-    char msg[4096], buf[4096];
-    int len;
-    time_t w;
-    struct _r *r;
-    struct _r **R;
-    char *method, *url, *file, *size, *checksum;
-    char *tmp = xstrdup(data);
-    struct stat st;
-    int file_fd = -1;
-    method = strtok(tmp, " ");
-    url = strtok(NULL, " ");
-    file = strtok(NULL, " ");
-    size = strtok(NULL, " ");
-    checksum = strtok(NULL, " ");
-    if (!url) {
-        url = method;
-        method = "GET";
-    }
-    if (file && strcmp(file, "-") == 0)
-        file = NULL;
-    if (size && strcmp(size, "-") == 0)
-        size = NULL;
-    if (checksum && strcmp(checksum, "-") == 0)
-        checksum = NULL;
-    msg[0] = '\0';
-    snprintf(buf, sizeof(buf)-1, "%s %s HTTP/1.0\r\n", method, url);
-    strcat(msg, buf);
-    strcat(msg, "Accept: */*\r\n");
-    strcat(msg, "Proxy-Connection: Keep-Alive\r\n");
-    if (opt_ims && (lrand48() & 0x03) == 0) {
-        w = time(NULL) - (lrand48() & 0x3FFFF);
-        snprintf(buf, sizeof(buf)-1, "If-Modified-Since: %s\r\n", mkrfc850(&w));
-        strcat(msg, buf);
-    }
-    if (file) {
-        if ((file_fd = open(file, O_RDONLY)) < 0) {
-            perror("open");
-            return -1;
-        }
-        if (fstat(file_fd, &st)) {
-            perror("fstat");
-            close(file_fd);
-            return -1;
-        }
-        snprintf(buf, sizeof(buf)-1, "Content-length: %d\r\n", st.st_size);
-        strcat(msg, buf);
-    }
-    strcat(msg, "\r\n");
-    len = strlen(msg);
-    if (write(fd, msg, len) < 0) {
-        close(fd);
-        perror("request write");
-        close(file_fd);
-        return -1;
-    }
-    if (file) {
-        while ((len = read(file_fd, buf, sizeof buf)) > 0) {
-            if (write(fd, buf, len) < 0) {
-                close(fd);
-                perror("body write");
-                close(file_fd);
-                return -1;
-            }
-        }
-        if (len < 0) {
-            perror("file read");
-            close(file_fd);
-            return -1;
-        }
-        close(file_fd);
-    }
-    r = calloc(1, sizeof(struct _r));
-    strcpy(r->url, url);
-    if (size)
-        r->validsize = atoi(size);
-    else
-        r->validsize = -1;
-    if (checksum)
-        r->validsum = atoi(checksum);
-    for (R = &Requests; *R; R = &(*R)->next);
-    *R = r;
-    /*    fprintf(stderr, "REQUESTED %s\n", url); */
-    noutstanding++;
-    return 0;
-}
-
-static int
-get_header_int_value(const char *hdr, const char *buf, const char *end)
-{
-    const char *t;
-    for (t = buf; t < end; t += strcspn(t, crlf), t += strspn(t, crlf)) {
-        if (strncasecmp(t, hdr, strlen(hdr)) == 0) {
-            t += strlen(hdr);
-            while (xisspace(*t))
-                t++;
-            return atoi(t);
-        }
-    }
-    return -1;
-}
-
-static const char *
-get_header_string_value(const char *hdr, const char *buf, const char *end)
-{
-    const char *t;
-    static char result[8192];
-    for (t = buf; t < end; t += strcspn(t, crlf), t += strspn(t, crlf)) {
-        if (strncasecmp(t, hdr, strlen(hdr)) == 0) {
-            t += strlen(hdr);
-            while (xisspace(*t))
-                t++;
-            strcpy(result, "");
-            strncat(result, t, strcspn(t, crlf));
-            return result;
-        }
-    }
-    return NULL;
-}
-
-void
-request_done(struct _r *r)
-{
-    if (r->content_length != r->bytes_read)
-        fprintf(stderr, "ERROR! Short reply, expected %d bytes got %d\n",
-                r->content_length, r->bytes_read);
-    else if (r->validsize >= 0) {
-        if (r->validsize != r->bytes_read)
-            fprintf(stderr, "WARNING: %s Object size mismatch, expected %d got %d\n",
-                    r->url, r->validsize, r->bytes_read);
-        else if (opt_checksum && r->sum != r->validsum)
-            fprintf(stderr, "WARNING: %s Checksum error. Expected %d got %d\n",
-                    r->url, r->validsum, r->sum);
-    }
-}
-int
-handle_read(char *inbuf, int len)
-{
-    struct _r *r = Requests;
-    const char *end;
-    const char *url;
-    static char buf[READ_BUF_SZ];
-    int hlen, blen;
-    if (len < 0) {
-        perror("read");
-        Requests = r->next;
-        request_done(r);
-        free(r);
-        noutstanding--;
-        if (trace_fd >= 0)
-            write(trace_fd, "\n[CLOSED]\n", 10);
-        return -1;
-    }
-    total_bytes_read += len;
-    memcpy(buf, inbuf, len);
-    if (len == 0) {
-        fprintf(stderr, "WARNING: %s, server closed socket after %d+%d bytes\n", r->url, r->hdr_offset, r->bytes_read);
-        /* XXX, If no data was received and it isn't the first request on this
-         * connection then the request should be restarted rather than aborted
-         * but this is a simple test program an not a full blown HTTP client.
-         */
-        request_done(r);
-        Requests = r->next;
-        free(r);
-        noutstanding--;
-        return -1;
-    }
-    if (trace_fd > 0)
-        write(trace_fd, buf, len);
-    while (len > 0) {
-        /* Build headers */
-        if (r->hdr_length == 0) {
-            hlen = min(len, REPLY_HDR_SZ - r->hdr_offset - 1);
-            memcpy(r->reply_hdrs + r->hdr_offset, buf, hlen);
-            r->hdr_offset += hlen;
-            r->reply_hdrs[r->hdr_offset] = '\0';
-            len -= hlen;
-            /* Save any remaining read data */
-            memmove(buf, buf + hlen, len);
-        }
-        /* Process headers */
-        if (r->hdr_length == 0 && (end = mime_headers_end(r->reply_hdrs)) != NULL) {
-            r->hdr_length = end - r->reply_hdrs;
-            /* "unread" any body contents received */
-            blen = r->hdr_offset - r->hdr_length;
-            assert(blen >= 0);
-            if (blen > 0) {
-                memmove(buf + blen, buf, len);
-                memcpy(buf, r->reply_hdrs + r->hdr_length, blen);
-                len += blen;
-            }
-            r->reply_hdrs[r->hdr_length] = '\0';    /* Null terminate headers */
-            /* Parse headers */
-            r->content_length = get_header_int_value("content-length:", r->reply_hdrs, end);
-            /*          fprintf(stderr, "CONTENT_LENGTH = %d\n", r->content_length); */
-            url = get_header_string_value("X-Request-URI:", r->reply_hdrs, end);
-            if (url != NULL && strcmp(r->url, url) != 0)
-                fprintf(stderr, "WARNING: %s got reply %s\n", r->url, url);
-#if XREQUESTURI || 0
-            fprintf(stderr, "LOCATION = %s\n", get_header_string_value("X-Request-URI:", r->reply_hdrs, end));
-#endif
-        }
-        if (!(len == 0 || r->hdr_length > 0)) {
-            fprintf(stderr, "ERROR!!!\n");
-            assert((len == 0 || r->hdr_length > 0));
-        }
-        /* Process body */
-        if (r->hdr_length != 0) {
-            int i;
-            int bytes_left, bytes_used;
-            if (r->content_length >= 0) {
-                bytes_left = r->content_length - r->bytes_read;
-                assert(bytes_left >= 0);
-                bytes_used = len < bytes_left ? len : bytes_left;
-            } else {
-                bytes_left = len + 1;   /* Unknown end... */
-                bytes_used = len;
-            }
-            if (opt_checksum) {
-                for (i = 0; i < bytes_used; i++)
-                    r->sum += (int) buf[i] & 0xFF;
-            }
-            r->bytes_read += bytes_used;
-            len -= bytes_used;
-            if (bytes_left == bytes_used) {
-                request_done(r);
-                Requests = r->next;
-                free(r);
-                noutstanding--;
-                r = Requests;
-            } else if (r->content_length > -1) {
-                assert(r->bytes_read < r->content_length);
-            }
-            memmove(buf, buf + bytes_used, len);
-        }
-    }
-    return 0;
-}
-
-int
-read_reply(int fd)
-{
-    static char buf[READ_BUF_SZ];
-    int len;
-    int x;
-    len = read(fd, buf, READ_BUF_SZ);
-    x = handle_read(buf, len);
-    if (x < 0) {
-        perror("read reply");
-        close(fd);
-    }
-    return x;
-}
-
-void
-main_loop(void)
-{
-    static int pconn_fd = -1;
-    static char buf[8192];
-    struct timeval to;
-    struct timeval now, last, start;
-    fd_set R;
-    struct _r *r;
-    struct _r *nextr;
-    int x;
-    int timeouts;
-    int nrequests = 0, rrequests = 0, reqpersec = 0;
-
-    gettimeofday(&start, NULL);
-    last = start;
-
-    pconn_fd = open_http_socket();
-    if (pconn_fd < 0) {
-        perror("socket");
-        exit(1);
-    }
-    while (!done_reading_urls || noutstanding) {
-        if (!opt_reopen && pconn_fd < 0) {
-            fprintf(stderr, "TERMINATED: Connection closed\n");
-            break;
-        }
-        if (pconn_fd < 0) {
-            pconn_fd = open_http_socket();
-            if (pconn_fd < 0) {
-                perror("socket");
-                exit(1);
-            }
-            nextr = Requests;
-            Requests = NULL;
-            noutstanding = 0;
-            while ((r = nextr) != NULL) {
-                nextr = r->next;
-                if (send_request(pconn_fd, r->url) != 0) {
-                    close(pconn_fd);
-                    pconn_fd = -1;
-                    nextr = r;
-                    for (r = Requests; r != NULL && r->next; r = r->next);
-                    if (r != NULL)
-                        r->next = nextr;
-                    else
-                        Requests = nextr;
-                    break;
-                }
-                free(r);
-            }
-            timeouts = 0;
-            if (pconn_fd < 0)
-                continue;
-        }
-        if (timeouts == 200) {
-            close(pconn_fd);
-            pconn_fd = -1;
-            r = Requests;
-            Requests = Requests->next;
-            fprintf(stderr, "ABORT %s\n", Requests->url);
-            free(r);
-            noutstanding--;
-        }
-        if (pconn_fd >= 0 && noutstanding < max_outstanding && !done_reading_urls) {
-            char *t;
-            if (fgets(buf, 8191, stdin) == NULL) {
-                fprintf(stderr, "Done Reading URLS\n");
-                done_reading_urls = 1;
-                continue;
-            }
-            rrequests++;
-            if ((t = strchr(buf, '\n')))
-                *t = '\0';
-            if (send_request(pconn_fd, buf) != 0) {
-                close(pconn_fd);
-                pconn_fd = -1;
-                continue;
-            }
-            nrequests++;
-            reqpersec++;
-            timeouts = 0;
-        }
-        FD_ZERO(&R);
-        to.tv_sec = 1;
-        to.tv_usec = 0;
-        FD_SET(pconn_fd, &R);
-        x = select(pconn_fd + 1, &R, NULL, NULL, &to);
-        if (x < 0) {
-            if (errno != EINTR)
-                perror("select");
-            continue;
-        } else if (x == 0) {
-            assert(Requests != NULL);
-            fprintf(stderr, "TIMEOUT %s; %d, %d\n", Requests->url,
-                    ++timeouts, noutstanding);
-            continue;
-        }
-        if (FD_ISSET(pconn_fd, &R)) {
-            timeouts = 0;
-            if (read_reply(pconn_fd) != 0)
-                pconn_fd = -1;
-        }
-        gettimeofday(&now, NULL);
-        if (now.tv_sec > last.tv_sec) {
-            int dt;
-            int nreq;
-            last = now;
-            dt = (int) (now.tv_sec - start.tv_sec);
-            nreq = 0;
-            for (r = Requests; r; r = r->next)
-                nreq++;
-            printf("T+ %6d: %9d req (%+4d), %4d pend, %3d/sec avg, %dmb, %dkb/sec avg\n",
-                   dt,
-                   nrequests,
-                   reqpersec,
-                   nreq,
-                   (int) (nrequests / dt),
-                   (int) total_bytes_read / 1024 / 1024,
-                   (int) total_bytes_read / 1024 / dt);
-            reqpersec = 0;
-        }
-    }
-}
-
-void
-usage(void)
-{
-    fprintf(stderr, "usage: %s: -p port -h host -n max -t tracefile -i -c -l lifetime\n", progname);
-}
-
-int
-main(argc, argv)
-int argc;
-char *argv[];
-{
-    int c;
-    setbuf(stdout, NULL);
-    setbuf(stderr, NULL);
-    progname = xstrdup(argv[0]);
-    while ((c = getopt(argc, argv, "p:h:n:t:icl:r")) != -1) {
-        switch (c) {
-        case 'p':
-            proxy_port = atoi(optarg);
-            break;
-        case 'h':
-            proxy_addr = xstrdup(optarg);
-            break;
-        case 'n':
-            max_outstanding = atoi(optarg);
-            break;
-        case 'i':
-            opt_ims = 1;
-            break;
-        case 'c':
-            opt_checksum = 1;
-            break;
-        case 'l':
-            lifetime = (time_t) atoi(optarg);
-            break;
-        case 't':
-            trace_fd = open(optarg, O_WRONLY | O_CREAT | O_TRUNC, 0666);
-            break;
-        case 'r':
-            opt_reopen = !opt_reopen;
-            break;
-        default:
-            usage();
-            return 1;
-        }
-    }
-    signal(SIGINT, sig_intr);
-    signal(SIGPIPE, SIG_IGN);
-    main_loop();
-    return 0;
-}
-
diff --git a/test-suite/tcp-banger2.c b/test-suite/tcp-banger2.c
deleted file mode 100644 (file)
index 2cc6a2d..0000000
+++ /dev/null
@@ -1,598 +0,0 @@
-/*
- * Copyright (C) 1996-2022 The Squid Software Foundation and contributors
- *
- * Squid software is distributed under GPLv2+ license and includes
- * contributions from numerous individuals and organizations.
- * Please see the COPYING and CONTRIBUTORS files for details.
- */
-
-#include "squid.h"
-
-/*
- * On some systems, FD_SETSIZE is set to something lower than the
- * actual number of files which can be opened.  IRIX is one case,
- * NetBSD is another.  So here we increase FD_SETSIZE to our
- * configure-discovered maximum *before* any system includes.
- */
-#define CHANGE_FD_SETSIZE 1
-
-/* Cannot increase FD_SETSIZE on Linux */
-#if _SQUID_LINUX_
-#undef CHANGE_FD_SETSIZE
-#define CHANGE_FD_SETSIZE 0
-#endif
-
-/* Cannot increase FD_SETSIZE on FreeBSD before 2.2.0, causes select(2)
- * to return EINVAL. */
-/* Marian Durkovic <marian@svf.stuba.sk> */
-/* Peter Wemm <peter@spinner.DIALix.COM> */
-#if _SQUID_FREEBSD_
-#include <osreldate.h>
-#if __FreeBSD_version < 220000
-#undef CHANGE_FD_SETSIZE
-#define CHANGE_FD_SETSIZE 0
-#endif
-#endif
-
-/* Increase FD_SETSIZE if SQUID_MAXFD is bigger */
-#if CHANGE_FD_SETSIZE && SQUID_MAXFD > DEFAULT_FD_SETSIZE
-#define FD_SETSIZE SQUID_MAXFD
-#endif
-
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#if HAVE_STRING_H
-#include <string.h>
-#endif
-#if HAVE_STRINGS_H
-#include <strings.h>
-#endif
-#if HAVE_SIGNAL_H
-#include <signal.h>
-#endif
-#if HAVE_TIME_H
-#include <time.h>
-#endif
-#if HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-#if HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-#if HAVE_ARPA_INET_H
-#include <arpa/inet.h>
-#endif
-#if HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_ASSERT_H
-#include <assert.h>
-#endif
-#if HAVE_CTYPE_H
-#include <ctype.h>
-#endif
-
-#define PROXY_PORT 3128
-#define PROXY_ADDR "127.0.0.1"
-#define READ_BUF_SZ 4096
-
-static int proxy_port = PROXY_PORT;
-static char *proxy_addr = PROXY_ADDR;
-static char *progname;
-static int reqpersec;
-static int nrequests;
-static int opt_ims = 0;
-static int opt_range = 0;
-static int opt_accel = 0;
-static int max_connections = 64;
-static time_t lifetime = 60;
-static time_t process_lifetime = 86400;
-static struct timeval now;
-static long long total_bytes_written = 0;
-static long long total_bytes_read = 0;
-static int opt_checksum = 0;
-static char *custom_header = NULL;
-FILE *trace_file = NULL;
-
-typedef void (CB) (int, void *);
-
-struct _f {
-    CB *cb;
-    CB *ccb;
-    void *data;
-    time_t start;
-};
-struct _request {
-    int fd;
-    char *url;
-    char method[16];
-    char requestbodyfile[256];
-    char buf[READ_BUF_SZ * 2 + 1];
-    int headfound;
-    int validsize;
-    int bodysize;
-    int content_length;
-    int status;
-    long validsum;
-    long sum;
-    int validstatus;
-};
-
-struct _f FD[SQUID_MAXFD];
-int nfds = 0;
-int maxfd = 0;
-
-static void
-free_request(struct _request *r)
-{
-    if (r->url)
-        free(r->url);
-    free(r);
-}
-
-#define RFC1123_STRFTIME "%a, %d %b %Y %H:%M:%S GMT"
-char *
-mkrfc1123(t)
-time_t *t;
-{
-    static char buf[128];
-    struct tm *gmt = gmtime(t);
-    buf[0] = '\0';
-    (void) strftime(buf, 127, RFC1123_STRFTIME, gmt);
-    return buf;
-}
-
-void
-fd_close(int fd)
-{
-    close(fd);
-    if (FD[fd].ccb)
-        FD[fd].ccb(fd, FD[fd].data);
-    FD[fd].ccb = NULL;
-    FD[fd].cb = NULL;
-    FD[fd].data = NULL;
-    nfds--;
-    if (fd == maxfd) {
-        while (fd > 0 && FD[fd].cb == NULL)
-            fd--;
-        maxfd = fd;
-    }
-}
-
-void
-fd_open(int fd, CB * cb, void *data, CB * ccb)
-{
-    assert(fd < SQUID_MAXFD);
-    FD[fd].cb = cb;
-    FD[fd].ccb = ccb;
-    FD[fd].data = data;
-    FD[fd].start = now.tv_sec;
-    if (fd > maxfd)
-        maxfd = fd;
-    nfds++;
-}
-
-void
-sig_intr(int sig)
-{
-    fd_close(0);
-    nfds++;
-    printf("\rWaiting for open connections to finish...\n");
-    signal(sig, SIG_DFL);
-}
-
-void
-read_reply(int fd, void *data)
-{
-    struct _request *r = data;
-    static unsigned char buf[READ_BUF_SZ];
-    int len;
-    int used = 0;
-    if ((len = read(fd, buf, READ_BUF_SZ)) <= 0) {
-        fd_close(fd);
-        reqpersec++;
-        nrequests++;
-        return;
-    }
-    total_bytes_read += len;
-    if (r->headfound < 2) {
-        char *p, *header = NULL;
-        int oldlen = strlen(r->buf);
-        int newlen = oldlen + len;
-        assert(oldlen <= READ_BUF_SZ);
-        memcpy(r->buf + oldlen, buf, len);
-        r->buf[newlen + 1] = '\0';
-        for (p = r->buf; r->headfound < 2 && used < newlen; p++, used++) {
-            switch (*p) {
-            case '\n':
-                r->headfound++;
-                if (!header)
-                    break;
-                /* Decode header */
-                if (strncmp(header, "HTTP", 4) == 0)
-                    r->status = atoi(header + 8);
-                else if (strncasecmp(header, "Content-Length:", 15) == 0)
-                    r->content_length = atoi(header + 15);
-                else if (strncasecmp(header, "X-Request-URI:", 14) == 0) {
-                    /* Check URI */
-                    if (strncmp(r->url, header + 15, strcspn(header + 15, "\r\n"))) {
-                        char url[8192];
-                        strncpy(url, header + 15, strcspn(header + 15, "\r\n"));
-                        url[strcspn(header + 15, "\r\n")] = '\n';
-                        fprintf(stderr, "ERROR: Sent %s received %s\n",
-                                r->url, url);
-                    }
-                }
-                header = NULL;
-                break;
-            case '\r':
-                break;
-            default:
-                r->headfound = 0;
-                if (!header)
-                    header = p;
-                break;
-            }
-        }
-        if (header) {
-            memmove(r->buf, header, newlen - (header - r->buf) + 1);
-        }
-        assert(used >= oldlen);
-        used -= oldlen;
-    }
-    r->bodysize += len - used;
-    if (opt_checksum) {
-        for (; used < len; used++) {
-            r->sum += buf[used];
-        }
-    }
-}
-
-void
-reply_done(int fd, void *data)
-{
-    struct _request *r = data;
-    if (opt_range);     /* skip size checks for now */
-    else if (strcmp(r->method, "HEAD") == 0);
-    else if (r->bodysize != r->content_length && r->content_length >= 0)
-        fprintf(stderr, "ERROR: %s got %d of %d bytes\n",
-                r->url, r->bodysize, r->content_length);
-    else if (r->validsize >= 0) {
-        if (r->validsize != r->bodysize)
-            fprintf(stderr, "WARNING: %s size mismatch wanted %d bytes got %d\n",
-                    r->url, r->validsize, r->bodysize);
-        else if (opt_checksum && r->validsum != r->sum)
-            fprintf(stderr, "WARNING: %s invalid checksum wanted 0x%lx got 0x%lx\n",
-                    r->url, r->validsum, r->sum);
-    }
-    if (r->validstatus && r->status != r->validstatus) {
-        fprintf(stderr, "WARNING: %s status mismatch wanted %d got %d\n",
-                r->url, r->validstatus, r->status);
-    }
-    if (trace_file) {
-        if (opt_checksum)
-            fprintf(trace_file, "%s %s %d %s %d 0x%lx\n",
-                    r->method, r->url, r->status, r->requestbodyfile, r->bodysize, r->sum);
-        else
-            fprintf(trace_file, "%s %s %d %s %d\n",
-                    r->method, r->url, r->status, r->requestbodyfile, r->bodysize);
-    }
-    free_request(r);
-}
-
-struct _request *
-request(char *urlin) {
-    int s = -1, f = -1;
-    char buf[4096];
-    char msg[8192];
-    char *method, *url, *file, *size, *checksum, *status;
-    char *host;
-    char urlbuf[8192];
-    int len, len2;
-    time_t w;
-    struct stat st;
-    struct sockaddr_in S;
-    struct _request *r;
-    if (*urlin == '\0')
-        return NULL;
-    if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
-        perror("socket");
-        return NULL;
-    }
-    memset(&S, '\0', sizeof(struct sockaddr_in));
-    S.sin_family = AF_INET;
-    S.sin_port = htons(proxy_port);
-    S.sin_addr.s_addr = inet_addr(proxy_addr);
-    if (connect(s, (struct sockaddr *) &S, sizeof(S)) < 0) {
-        close(s);
-        perror("connect");
-        return NULL;
-    }
-    strcpy(urlbuf, urlin);
-    method = strtok(urlbuf, " ");
-    url = strtok(NULL, " ");
-    status = strtok(NULL, " ");
-    file = strtok(NULL, " ");
-    size = strtok(NULL, " ");
-    checksum = strtok(NULL, " ");
-    if (!url) {
-        url = method;
-        method = "GET";
-    }
-    if (!file)
-        file = "-";
-    if (!size)
-        size = "-";
-    if (!checksum)
-        checksum = "-";
-    r = calloc(1, sizeof *r);
-    assert(r != NULL);
-    r->url = xstrdup(url);
-    assert(r->url);
-    strcpy(r->method, method);
-    strcpy(r->requestbodyfile, file);
-    r->fd = s;
-    if (size && strcmp(size, "-") != 0)
-        r->validsize = atoi(size);
-    else
-        r->validsize = -1;  /* Unknown */
-    if (checksum && strcmp(checksum, "-") != 0)
-        r->validsum = strtoul(checksum, NULL, 0);
-    if (status)
-        r->validstatus = atoi(status);
-    r->content_length = -1; /* Unknown */
-    if (opt_accel) {
-        host = strchr(url, '/') + 2;
-        url = strchr(host, '/');
-    } else {
-        host = NULL;
-    }
-    snprintf(msg, sizeof(msg)-1, "%s %s HTTP/1.0\r\n", method, url);
-    if (host) {
-        url[0] = '\0';
-        snprintf(buf, sizeof(buf)-1, "Host: %s\r\n", host);
-        strcat(msg, buf);
-        url[0] = '/';
-    }
-    strcat(msg, "Accept: */*\r\n");
-    if (opt_ims && (lrand48() & 0x03) == 0) {
-        w = time(NULL) - (lrand48() & 0x3FFFF);
-        snprintf(buf, sizeof(buf)-1, "If-Modified-Since: %s\r\n", mkrfc850(&w));
-        strcat(msg, buf);
-    }
-    if (file && strcmp(file, "-") != 0) {
-        f = open(file, O_RDONLY);
-        if (f < 0) {
-            perror("open file");
-            exit(1);
-        }
-        fstat(f, &st);
-        snprintf(buf, sizeof(buf)-1, "Content-Length: %d\r\n", (int) st.st_size);
-        strcat(msg, buf);
-    }
-    if (opt_range && (lrand48() & 0x03) == 0) {
-        int len;
-        int count = 0;
-        strcat(msg, "Range: bytes=");
-        while (((len = (int) lrand48()) & 0x03) == 0 || !count) {
-            const int offset = (int) lrand48();
-            if (count)
-                strcat(msg, ",");
-            switch (lrand48() & 0x03) {
-            case 0:
-                snprintf(buf, sizeof(buf)-1, "-%d", len);
-                break;
-            case 1:
-                snprintf(buf, sizeof(buf)-1, "%d-", offset);
-                break;
-            default:
-                snprintf(buf, sizeof(buf)-1, "%d-%d", offset, offset + len);
-                break;
-            }
-            strcat(msg, buf);
-            count++;
-        }
-        strcat(msg, "\r\n");
-    }
-    strcat(msg, custom_header);
-    strcat(msg, "\r\n");
-    len = strlen(msg);
-    if ((len2 = write(s, msg, len)) != len) {
-        close(s);
-        perror("write request");
-        free_request(r);
-        return NULL;
-    } else
-        total_bytes_written += len2;
-    if (f >= 0) {
-        while ((len = read(f, buf, sizeof(buf))) > 0) {
-            len2 = write(s, buf, len);
-            if (len2 < 0) {
-                perror("write body");
-                close(s);
-                free_request(r);
-            }
-        }
-        if (len < 0) {
-            perror("read body");
-            exit(1);
-        }
-    }
-    /*
-     * if (fcntl(s, F_SETFL, O_NDELAY) < 0)
-     * perror("fcntl O_NDELAY");
-     */
-    return r;
-}
-
-void
-read_url(int fd, void *junk)
-{
-    struct _request *r;
-    static char buf[8192];
-    char *t;
-    buf[0] = '\0';
-    if (fgets(buf, 8191, stdin) == NULL) {
-        printf("Done Reading URLS\n");
-        fd_close(0);
-        nfds++;
-        return;
-    }
-    if (buf[0] == '\0')
-        return;
-    if ((t = strchr(buf, '\n')))
-        *t = '\0';
-    r = request(buf);
-    if (!r) {
-        max_connections = nfds - 1;
-        printf("NOTE: max_connections set at %d\n", max_connections);
-    } else {
-        fd_open(r->fd, read_reply, r, reply_done);
-    }
-}
-
-void
-usage(void)
-{
-    fprintf(stderr, "usage: %s: -p port -h host -n max\n", progname);
-    fprintf(stderr, " -t <tracefile>  Save request trace\n");
-    fprintf(stderr, " -c              Check checksum agains trace\n");
-    fprintf(stderr, " -i              Send random If-Modified-Since times\n");
-    fprintf(stderr, " -l <seconds>    Connection lifetime timeout (default 60)\n");
-    fprintf(stderr, " -a              Accelerator mode\n");
-    fprintf(stderr, " -H <string>     Custom header\n");
-}
-
-int
-main(argc, argv)
-int argc;
-char *argv[];
-{
-    int i;
-    int c;
-    int dt;
-    int j;
-    fd_set R, R2;
-    struct timeval start;
-    struct timeval last;
-    struct timeval to;
-    setbuf(stdout, NULL);
-    setbuf(stderr, NULL);
-    progname = xstrdup(argv[0]);
-    gettimeofday(&now, NULL);
-    start = last = now;
-    custom_header = xstrdup("");
-    while ((c = getopt(argc, argv, "ap:h:H:n:icrl:L:t:")) != -1) {
-        switch (c) {
-        case 'a':
-            opt_accel = 1;
-            break;
-        case 'p':
-            proxy_port = atoi(optarg);
-            break;
-        case 'h':
-            proxy_addr = xstrdup(optarg);
-            break;
-        case 'n':
-            max_connections = atoi(optarg);
-            break;
-        case 'i':
-            opt_ims = 1;
-            break;
-        case 'l':
-            lifetime = (time_t) atoi(optarg);
-            break;
-        case 'L':
-            process_lifetime = (time_t) atoi(optarg);
-            break;
-        case 'c':
-            opt_checksum = 1;
-            break;
-        case 't':
-            trace_file = fopen(optarg, "a");
-            assert(trace_file);
-            setbuf(trace_file, NULL);
-            break;
-        case 'r':
-            opt_range = 1;
-            break;
-        case 'H':
-            custom_header = realloc(custom_header, strlen(custom_header) + strlen(optarg) + 2 + 1);
-            strcat(custom_header, optarg);
-            strcat(custom_header, "\r\n");
-            break;
-        default:
-            usage();
-            return 1;
-        }
-    }
-    fd_open(0, read_url, NULL, NULL);
-    nfds--;
-    signal(SIGINT, sig_intr);
-    signal(SIGPIPE, SIG_IGN);
-    FD_ZERO(&R2);
-    while (nfds || FD[0].cb) {
-        FD_ZERO(&R);
-        to.tv_sec = 0;
-        to.tv_usec = 100000;
-        if (nfds < max_connections && FD[0].cb)
-            FD_SET(0, &R);
-        for (i = 1; i <= maxfd; i++) {
-            if (FD[i].cb == NULL)
-                continue;
-            if (now.tv_sec - FD[i].start > lifetime) {
-                fprintf(stderr, "WARNING: fd %d lifetime timeout\n", i);
-                fd_close(i);
-                continue;
-            }
-            FD_SET(i, &R);
-        }
-        if (select(maxfd + 1, &R, NULL, NULL, &to) < 0) {
-            fprintf(stderr, "maxfd=%d\n", maxfd);
-            if (errno != EINTR)
-                perror("select");
-            continue;
-        }
-        gettimeofday(&now, NULL);
-        for (i = 0; i <= maxfd; i++) {
-            if (!FD_ISSET(i, &R))
-                continue;
-            FD[i].cb(i, FD[i].data);
-            if (nfds < max_connections && FD[0].cb) {
-                j = 0;
-                FD_SET(0, &R2);
-                to.tv_sec = 0;
-                to.tv_usec = 0;
-                if (select(1, &R2, NULL, NULL, &to) == 1)
-                    FD[0].cb(0, FD[0].data);
-            }
-        }
-        if (now.tv_sec > last.tv_sec) {
-            last = now;
-            dt = (int) (now.tv_sec - start.tv_sec);
-            printf("T+ %6d: %9d req (%+4d), %4d conn, %3d/sec avg, %dmb, %dkb/sec avg\n",
-                   dt,
-                   nrequests,
-                   reqpersec,
-                   nfds,
-                   (int) (nrequests / dt),
-                   (int) (total_bytes_read / 1024 / 1024),
-                   (int) (total_bytes_read / 1024 / dt));
-            reqpersec = 0;
-            /*
-             * if (dt > process_lifetime)
-             *     exit(0);
-             */
-        }
-    }
-    printf("Exiting normally\n");
-    return 0;
-}
-
diff --git a/test-suite/tcp-banger3.c b/test-suite/tcp-banger3.c
deleted file mode 100644 (file)
index e8ae55d..0000000
+++ /dev/null
@@ -1,383 +0,0 @@
-/*
- * Copyright (C) 1996-2022 The Squid Software Foundation and contributors
- *
- * Squid software is distributed under GPLv2+ license and includes
- * contributions from numerous individuals and organizations.
- * Please see the COPYING and CONTRIBUTORS files for details.
- */
-
-#include "squid.h"
-
-/*
- * On some systems, FD_SETSIZE is set to something lower than the
- * actual number of files which can be opened.  IRIX is one case,
- * NetBSD is another.  So here we increase FD_SETSIZE to our
- * configure-discovered maximum *before* any system includes.
- */
-#define CHANGE_FD_SETSIZE 1
-
-/* Cannot increase FD_SETSIZE on Linux */
-#if _SQUID_LINUX_
-#undef CHANGE_FD_SETSIZE
-#define CHANGE_FD_SETSIZE 0
-#endif
-
-/* Cannot increase FD_SETSIZE on FreeBSD before 2.2.0, causes select(2)
- * to return EINVAL. */
-/* Marian Durkovic <marian@svf.stuba.sk> */
-/* Peter Wemm <peter@spinner.DIALix.COM> */
-#if _SQUID_FREEBSD_
-#include <osreldate.h>
-#if __FreeBSD_version < 220000
-#undef CHANGE_FD_SETSIZE
-#define CHANGE_FD_SETSIZE 0
-#endif
-#endif
-
-/* Increase FD_SETSIZE if SQUID_MAXFD is bigger */
-#if CHANGE_FD_SETSIZE && SQUID_MAXFD > DEFAULT_FD_SETSIZE
-#define FD_SETSIZE SQUID_MAXFD
-#endif
-
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#if HAVE_STRING_H
-#include <string.h>
-#endif
-#if HAVE_STRINGS_H
-#include <strings.h>
-#endif
-#if HAVE_SIGNAL_H
-#include <signal.h>
-#endif
-#if HAVE_TIME_H
-#include <time.h>
-#endif
-#if HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-#if HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-#if HAVE_ARPA_INET_H
-#include <arpa/inet.h>
-#endif
-#if HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#if HAVE_ASSERT_H
-#include <assert.h>
-#endif
-#if HAVE_NETDB_H
-#include <netdb.h>
-#endif
-#if HAVE_SYS_WAIT_H
-#include <sys/wait.h>
-#endif
-
-#define READ_BUF_SZ 4096
-#define URL_BUF_SZ 4096
-
-struct _thing {
-    int rfd;
-    int wfd;
-    int state;
-    pid_t pid;
-    char url[URL_BUF_SZ];
-    struct _thing *next;
-};
-typedef struct _thing thing;
-
-static thing *things = NULL;
-static fd_set R1;
-static int maxfd = 0;
-static struct timeval now;
-#if DEBUG
-static int debug = 1;
-#else
-static int debug = 0;
-#endif
-
-int
-tvSubMsec(struct timeval t1, struct timeval t2)
-{
-    return (t2.tv_sec - t1.tv_sec) * 1000 + (t2.tv_usec - t1.tv_usec) / 1000;
-}
-
-static int
-get_url(const char *url)
-{
-    char host[URL_BUF_SZ];
-    char path[URL_BUF_SZ];
-    char request[URL_BUF_SZ];
-    char reply[READ_BUF_SZ];
-    char *t;
-    int x;
-    int s;
-    int nr = 0;
-    struct hostent *h;
-    struct sockaddr_in S;
-    unsigned short port = 80;
-    assert(!strncmp(url, "http://", 7));
-    strncpy(host, url + 7, URL_BUF_SZ);
-    if ((t = strchr(host, '/')))
-        *t = '\0';
-    if ((t = strchr(host, ':'))) {
-        *t = '\0';
-        port = (unsigned short) atoi(t + 1);
-    }
-    t = strchr(url + 7, '/');
-    strncpy(path, (t ? t : "/"), URL_BUF_SZ);
-    memset(&S, '\0', sizeof(S));
-    h = gethostbyname(host);
-    if (!h)
-        return 0;
-    memcpy(&S.sin_addr.s_addr, h->h_addr_list[0], sizeof(S.sin_addr.s_addr));
-    S.sin_port = htons(port);
-    S.sin_family = AF_INET;
-    if (debug) {
-        char tmp[16];
-        fprintf(stderr, "%s (%s) %d %s\n", host, inet_ntop(AF_INET, &S.sin_addr,tmp,sizeof(tmp)), (int) port, path);
-    }
-    s = socket(PF_INET, SOCK_STREAM, 0);
-    if (s < 0) {
-        perror("socket");
-        return -errno;
-    }
-    x = connect(s, (struct sockaddr *) &S, sizeof(S));
-    if (x < 0) {
-        perror(host);
-        return -errno;
-    }
-    snprintf(request, URL_BUF_SZ,
-             "GET %s HTTP/1.1\r\n"
-             "Accept: */*\r\n"
-             "Host: %s\r\n"
-             "Connection: close\r\n"
-             "\r\n",
-             path,
-             host);
-    x = write(s, request, strlen(request));
-    if (x < 0) {
-        perror("write");
-        return -errno;
-    }
-    do {
-        x = read(s, reply, READ_BUF_SZ);
-        if (x > 0)
-            nr += x;
-    } while (x > 0);
-    close(s);
-    return nr;
-}
-
-static void
-child_main_loop(void)
-{
-    char buf[URL_BUF_SZ];
-    char *t;
-    int n;
-    struct timeval t1;
-    struct timeval t2;
-    if (debug)
-        fprintf(stderr, "Child PID %d entering child_main_loop\n", (int) getpid());
-    setbuf(stdin, NULL);
-    setbuf(stdout, NULL);
-    setbuf(stderr, NULL);
-    while (fgets(buf, URL_BUF_SZ, stdin)) {
-        t = strchr(buf, '\n');
-        if (t == NULL)
-            continue;
-        *t = '\0';
-        if (strncmp(buf, "http://", 7))
-            continue;
-        gettimeofday(&t1, NULL);
-        n = get_url(buf);
-        gettimeofday(&t2, NULL);
-        printf("%d %d\n", n, tvSubMsec(t1, t2));
-    }
-}
-
-static thing *
-create_a_thing(char *argv[])
-{
-    int p2c[2];
-    int c2p[2];
-    int prfd, pwfd, crfd, cwfd;
-    pid_t pid;
-    thing *t;
-    if (pipe(p2c) < 0)
-        abort();
-    if (pipe(c2p) < 0)
-        abort();
-    prfd = p2c[0];
-    cwfd = p2c[1];
-    crfd = c2p[0];
-    pwfd = c2p[1];
-    if ((pid = fork()) < 0)
-        abort();
-    if (pid > 0) {      /* parent */
-        /* close shared socket with child */
-        close(crfd);
-        close(cwfd);
-        t = calloc(1, sizeof(*t));
-        t->wfd = pwfd;
-        t->rfd = prfd;
-        if (pwfd > maxfd)
-            maxfd = pwfd;
-        if (prfd > maxfd)
-            maxfd = prfd;
-        t->pid = pid;
-        return t;
-    }
-    /* child */
-    close(prfd);
-    close(pwfd);
-    dup2(crfd, 0);
-    dup2(cwfd, 1);
-    close(crfd);
-    close(cwfd);
-    child_main_loop();
-    exit(0);
-}
-
-static void
-create_children(char *argv[])
-{
-    thing *t;
-    thing **T = &things;
-    int i;
-    for (i = 0; i < 20; i++) {
-        t = create_a_thing(argv);
-        assert(t);
-        if (debug)
-            fprintf(stderr, "Thing #%d on FD %d/%d\n",
-                    i, t->rfd, t->wfd);
-        *T = t;
-        T = &t->next;
-    }
-}
-
-char *
-parent_read_url(void)
-{
-    static char buf[URL_BUF_SZ];
-    while (fgets(buf, URL_BUF_SZ, stdin)) {
-        if (strncmp(buf, "http://", 7))
-            continue;
-        return buf;
-    }
-    return NULL;
-}
-
-static thing *
-get_idle_thing(void)
-{
-    thing *t;
-    thing *n = things;
-    while ((t = n)) {
-        n = t->next;
-        if (t->state == 0)
-            break;
-    }
-    return t;
-}
-
-static void
-dispatch(thing * t, char *url)
-{
-    int x;
-    char *s;
-    assert(t->state == 0);
-    x = write(t->wfd, url, strlen(url));
-    if (x < 0)
-        perror("write");
-    if (debug)
-        fprintf(stderr, "dispatched URL to thing PID %d, %d bytes\n", (int) t->pid, x);
-    strncpy(t->url, url, URL_BUF_SZ);
-    if ((s = strchr(t->url, '\n')))
-        *s = '\0';
-    t->state = 1;
-    FD_SET(t->rfd, &R1);
-}
-
-static void
-read_reply(thing * t)
-{
-    char buf[128];
-    int i;
-    int x;
-    int j;
-    x = read(t->rfd, buf, 128);
-    if (x < 0) {
-        perror("read");
-    } else if (2 == sscanf(buf, "%d %d", &i, &j)) {
-        gettimeofday(&now, NULL);
-        printf("%d.%06d %9d %9d %s\n", (int) now.tv_sec, (int) now.tv_usec, i, j, t->url);
-    }
-    t->state = 0;
-    FD_CLR(t->rfd, &R1);
-}
-
-static void
-parent_main_loop(void)
-{
-    thing *t;
-    char *url;
-    fd_set R2;
-    int x;
-    struct timeval to;
-    FD_ZERO(&R1);
-    for (;;) {
-        while ((t = get_idle_thing()) && (url = parent_read_url()))
-            dispatch(t, url);
-        R2 = R1;
-        to.tv_sec = 60;
-        to.tv_usec = 0;
-        x = select(maxfd + 1, &R2, NULL, NULL, &to);
-        if (x < 0) {
-            perror("select");
-            continue;
-        } else if (x == 0) {
-            return;
-        }
-        for (t = things; t; t = t->next) {
-            if (t->state != 1)
-                continue;
-            if (!FD_ISSET(t->rfd, &R2))
-                continue;
-            read_reply(t);
-        }
-    }
-}
-
-static void
-sig_child(int sig)
-{
-    int status;
-    pid_t pid;
-    do {
-        pid = waitpid(-1, &status, WNOHANG);
-    } while (pid > 0 || (pid < 0 && errno == EINTR));
-    signal(sig, sig_child);
-}
-
-int
-main(int argc, char *argv[])
-{
-    int i;
-    signal(SIGCHLD, sig_child);
-    create_children(argv);
-    parent_main_loop();
-    for (i = 3; i <= maxfd; i++)
-        close(i);
-    sleep(1);
-}
-