]> git.ipfire.org Git - thirdparty/squid.git/blame - tools/squidclient.cc
SourceFormat Enforcement
[thirdparty/squid.git] / tools / squidclient.cc
CommitLineData
30a4f2a8 1/*
5ac5029d
AJ
2 * $Id$
3 *
30a4f2a8 4 * DEBUG: section 0 WWW Client
5 * AUTHOR: Harvest Derived
6 *
2b6662ba 7 * SQUID Web Proxy Cache http://www.squid-cache.org/
e25c139f 8 * ----------------------------------------------------------
30a4f2a8 9 *
2b6662ba 10 * Squid is the result of efforts by numerous individuals from
11 * the Internet community; see the CONTRIBUTORS file for full
12 * details. Many organizations have provided support for Squid's
13 * development; see the SPONSORS file for full details. Squid is
14 * Copyrighted (C) 2001 by the Regents of the University of
15 * California; see the COPYRIGHT file for full details. Squid
16 * incorporates software developed and/or copyrighted by other
17 * sources; see the CREDITS file for full details.
30a4f2a8 18 *
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation; either version 2 of the License, or
22 * (at your option) any later version.
3afd7aae 23 *
30a4f2a8 24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
3afd7aae 28 *
30a4f2a8 29 * You should have received a copy of the GNU General Public License
30 * along with this program; if not, write to the Free Software
cbdec147 31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
e25c139f 32 *
30a4f2a8 33 */
090089c4 34
94ab55b0 35#include "config.h"
36
15443eec 37#ifdef _SQUID_MSWIN_
63be0a78 38/** \cond AUTODOCS-IGNORE */
15443eec 39using namespace Squid;
63be0a78 40/** \endcond */
15443eec 41#endif
42
b55fa77d 43#ifdef _SQUID_WIN32_
44#include <io.h>
45#endif
815f9118 46#if HAVE_STDIO_H
94ab55b0 47#include <stdio.h>
815f9118 48#endif
815f9118 49#if HAVE_SYS_SOCKET_H
94ab55b0 50#include <sys/socket.h>
815f9118 51#endif
52#if HAVE_STRING_H
94ab55b0 53#include <string.h>
815f9118 54#endif
55#if HAVE_UNISTD_H
94ab55b0 56#include <unistd.h>
815f9118 57#endif
489520a9 58#if HAVE_NETDB_H
94ab55b0 59#include <netdb.h>
815f9118 60#endif
61#if HAVE_SIGNAL_H
94ab55b0 62#include <signal.h>
815f9118 63#endif
64#if HAVE_ERRNO_H
94ab55b0 65#include <errno.h>
815f9118 66#endif
67#if HAVE_SYS_STAT_H
94ab55b0 68#include <sys/stat.h>
815f9118 69#endif
70#if HAVE_FCNTL_H
94ab55b0 71#include <fcntl.h>
815f9118 72#endif
73#if HAVE_NETINET_IN_H
c7f83c7a 74#include <netinet/in.h>
815f9118 75#endif
d3e3ff4f 76#if HAVE_GETOPT_H
77#include <getopt.h>
78#endif
94ab55b0 79
80#include "util.h"
9837e5f0 81#include "ip/IpAddress.h"
090089c4 82
83#ifndef BUFSIZ
7ed62376
AJ
84#define BUFSIZ 8192
85#endif
86#ifndef MESSAGELEN
87#define MESSAGELEN 65536
88#endif
89#ifndef HEADERLEN
90#define HEADERLEN 65536
090089c4 91#endif
92
94ab55b0 93typedef void SIGHDLR(int sig);
94
090089c4 95/* Local functions */
ad61a2b4 96static int client_comm_bind(int, const IpAddress &);
62e76326 97
ad61a2b4 98static int client_comm_connect(int, const IpAddress &, struct timeval *);
f5b8bbc4 99static void usage(const char *progname);
62e76326 100
899bab3f 101static int Now(struct timeval *);
e6ccf245 102static SIGHDLR catchSignal;
54220df8 103static SIGHDLR pipe_handler;
d6d09e02 104static void set_our_signal(void);
20cbfe5a 105static ssize_t myread(int fd, void *buf, size_t len);
106static ssize_t mywrite(int fd, void *buf, size_t len);
cca89eeb 107static int put_fd;
108static char *put_file = NULL;
62e76326 109
b6c6bcef 110static struct stat sb;
111int total_bytes = 0;
20cbfe5a 112int io_timeout = 120;
090089c4 113
ec556193
GS
114#ifdef _SQUID_MSWIN_
115void
116Win32SockCleanup(void)
117{
118 WSACleanup();
119 return;
120}
121#endif /* ifdef _SQUID_MSWIN_ */
122
b8d8561b 123static void
0ee4272b 124usage(const char *progname)
090089c4 125{
0ee4272b 126 fprintf(stderr,
3afd7aae 127 "Version: %s\n"
4f16e7af 128 "Usage: %s [-arsv] [-g count] [-h remote host] [-H 'string'] [-i IMS] [-I ping-interval] [-j 'Host-header']"
51d94d10 129 "[-k] [-l local-host] [-m method] [-p port] [-P file] [-t count] [-T timeout] [-u proxy-user] [-U www-user] "
4f16e7af
AJ
130 "[-V version] [-w proxy-password] [-W www-password] url\n"
131 "\n"
3afd7aae 132 "Options:\n"
3afd7aae 133 " -a Do NOT include Accept: header.\n"
4f16e7af 134 " -g count Ping mode, perform \"count\" iterations (0 to loop until interrupted).\n"
3afd7aae 135 " -h host Retrieve URL from cache on hostname. Default is localhost.\n"
4f16e7af
AJ
136 " -H 'string' Extra headers to send. Use '\\n' for new lines.\n"
137 " -i IMS If-Modified-Since time (in Epoch seconds).\n"
138 " -I interval Ping interval in seconds (default 1 second).\n"
5ac5029d 139 " -j hosthdr Host header content\n"
51d94d10 140 " -k Keep the connection active. Default is to do only one request then close.\n"
4f16e7af 141 " -l host Specify a local IP address to bind to. Default is none.\n"
3afd7aae 142 " -m method Request method, default is GET.\n"
4f16e7af
AJ
143 " -p port Port number of cache. Default is %d.\n"
144 " -P file PUT request. Using the named file\n"
145 " -r Force cache to reload URL.\n"
146 " -s Silent. Do not print data to stdout.\n"
3afd7aae 147 " -t count Trace count cache-hops\n"
3afd7aae
AJ
148 " -T timeout Timeout value (seconds) for read/write operations.\n"
149 " -u user Proxy authentication username\n"
3afd7aae 150 " -U user WWW authentication username\n"
4f16e7af 151 " -v Verbose. Print outgoing message to stderr.\n"
5ac5029d 152 " -V version HTTP Version. Use '-' for HTTP/0.9 omitted case\n",
4f16e7af
AJ
153 " -w password Proxy authentication password\n"
154 " -W password WWW authentication password\n"
3afd7aae 155 VERSION, progname, CACHE_HTTP_PORT);
090089c4 156 exit(1);
157}
158
899bab3f 159static int interrupted = 0;
b8d8561b 160int
161main(int argc, char *argv[])
090089c4 162{
163 int conn, c, len, bytesWritten;
164 int port, to_stdout, reload;
899bab3f 165 int ping, pcount;
599eadbe 166 int keep_alive = 0;
88738790 167 int opt_noaccept = 0;
63259c34 168 int opt_verbose = 0;
a2c963ae 169 const char *hostname, *localhost;
ad61a2b4 170 IpAddress iaddr;
7ed62376
AJ
171 char url[BUFSIZ], msg[MESSAGELEN], buf[BUFSIZ];
172 char extra_hdrs[HEADERLEN];
0ee4272b 173 const char *method = "GET";
090089c4 174 extern char *optarg;
234967c9 175 time_t ims = 0;
b3b64e58 176 int max_forwards = -1;
62e76326 177
899bab3f 178 struct timeval tv1, tv2;
179 int i = 0, loops;
180 long ping_int;
181 long ping_min = 0, ping_max = 0, ping_sum = 0, ping_mean = 0;
5ac5029d
AJ
182 const char *proxy_user = NULL;
183 const char *proxy_password = NULL;
184 const char *www_user = NULL;
185 const char *www_password = NULL;
186 const char *host = NULL;
187 const char *version = "1.0";
090089c4 188
189 /* set the defaults */
2c08acd9 190 hostname = "localhost";
191 localhost = NULL;
63259c34 192 extra_hdrs[0] = '\0';
090089c4 193 port = CACHE_HTTP_PORT;
194 to_stdout = 1;
195 reload = 0;
899bab3f 196 ping = 0;
197 pcount = 0;
198 ping_int = 1 * 1000;
090089c4 199
200 if (argc < 2) {
3afd7aae 201 usage(argv[0]); /* need URL */
090089c4 202 } else if (argc >= 2) {
3afd7aae
AJ
203 strncpy(url, argv[argc - 1], BUFSIZ);
204 url[BUFSIZ - 1] = '\0';
62e76326 205
3afd7aae
AJ
206 if (url[0] == '-')
207 usage(argv[0]);
62e76326 208
5ac5029d 209 while ((c = getopt(argc, argv, "ah:j:V:l:P:i:km:p:rsvt:g:p:I:H:T:u:U:w:W:?")) != -1)
3afd7aae 210 switch (c) {
62e76326 211
3afd7aae
AJ
212 case 'a':
213 opt_noaccept = 1;
214 break;
62e76326 215
3afd7aae 216 case 'h': /* remote host */
3afd7aae
AJ
217 if (optarg != NULL)
218 hostname = optarg;
5ac5029d 219 break;
62e76326 220
5ac5029d 221 case 'j':
af6a12ee
AJ
222 host = optarg;
223 break;
5ac5029d
AJ
224
225 case 'V':
226 if (optarg != NULL)
227 version = optarg;
3afd7aae 228 break;
62e76326 229
3afd7aae
AJ
230 case 'l': /* local host */
231 if (optarg != NULL)
232 localhost = optarg;
3afd7aae 233 break;
62e76326 234
3afd7aae
AJ
235 case 's': /* silent */
236 to_stdout = 0;
3afd7aae 237 break;
62e76326 238
3afd7aae
AJ
239 case 'k': /* backward compat */
240 keep_alive = 1;
3afd7aae 241 break;
62e76326 242
3afd7aae
AJ
243 case 'r': /* reload */
244 reload = 1;
3afd7aae 245 break;
62e76326 246
3afd7aae
AJ
247 case 'p': /* port number */
248 sscanf(optarg, "%d", &port);
3afd7aae
AJ
249 if (port < 1)
250 port = CACHE_HTTP_PORT; /* default */
3afd7aae 251 break;
62e76326 252
3afd7aae
AJ
253 case 'P':
254 put_file = xstrdup(optarg);
3afd7aae 255 break;
62e76326 256
3afd7aae
AJ
257 case 'i': /* IMS */
258 ims = (time_t) atoi(optarg);
3afd7aae 259 break;
62e76326 260
3afd7aae
AJ
261 case 'm':
262 method = xstrdup(optarg);
3afd7aae 263 break;
62e76326 264
3afd7aae
AJ
265 case 't':
266 method = xstrdup("TRACE");
3afd7aae 267 max_forwards = atoi(optarg);
3afd7aae 268 break;
62e76326 269
3afd7aae
AJ
270 case 'g':
271 ping = 1;
3afd7aae 272 pcount = atoi(optarg);
3afd7aae 273 to_stdout = 0;
3afd7aae 274 break;
62e76326 275
3afd7aae
AJ
276 case 'I':
277 if ((ping_int = atoi(optarg) * 1000) <= 0)
278 usage(argv[0]);
3afd7aae 279 break;
62e76326 280
3afd7aae
AJ
281 case 'H':
282 if (strlen(optarg)) {
283 char *t;
284 strncpy(extra_hdrs, optarg, sizeof(extra_hdrs));
3afd7aae
AJ
285 while ((t = strstr(extra_hdrs, "\\n")))
286 *t = '\r', *(t + 1) = '\n';
287 }
288 break;
62e76326 289
3afd7aae
AJ
290 case 'T':
291 io_timeout = atoi(optarg);
292 break;
62e76326 293
3afd7aae
AJ
294 case 'u':
295 proxy_user = optarg;
296 break;
62e76326 297
3afd7aae
AJ
298 case 'w':
299 proxy_password = optarg;
300 break;
62e76326 301
3afd7aae
AJ
302 case 'U':
303 www_user = optarg;
304 break;
62e76326 305
3afd7aae
AJ
306 case 'W':
307 www_password = optarg;
308 break;
62e76326 309
3afd7aae
AJ
310 case 'v':
311 /* undocumented: may increase verb-level by giving more -v's */
312 opt_verbose++;
313 break;
62e76326 314
3afd7aae 315 case '?': /* usage */
62e76326 316
3afd7aae
AJ
317 default:
318 usage(argv[0]);
319 break;
320 }
090089c4 321 }
0ef0f1de 322#ifdef _SQUID_MSWIN_
323 {
3afd7aae
AJ
324 WSADATA wsaData;
325 WSAStartup(2, &wsaData);
326 atexit(Win32SockCleanup);
0ef0f1de 327 }
328#endif
090089c4 329 /* Build the HTTP request */
8a9b6b94 330 if (strncmp(url, "mgr:", 4) == 0) {
3afd7aae
AJ
331 char *t = xstrdup(url + 4);
332 snprintf(url, BUFSIZ, "cache_object://%s/%s", hostname, t);
333 xfree(t);
8a9b6b94 334 }
cca89eeb 335 if (put_file) {
3afd7aae
AJ
336 put_fd = open(put_file, O_RDONLY);
337 set_our_signal();
338
339 if (put_fd < 0) {
340 fprintf(stderr, "%s: can't open file (%s)\n", argv[0],
341 xstrerror());
342 exit(-1);
343 }
ec4daaa5 344#ifdef _SQUID_WIN32_
3afd7aae 345 setmode(put_fd, O_BINARY);
62e76326 346
c4aefe96 347#endif
62e76326 348
3afd7aae 349 fstat(put_fd, &sb);
cca89eeb 350 }
5ac5029d
AJ
351
352 if (!host) {
af6a12ee
AJ
353 char *newhost = strstr(url, "://");
354 if (newhost) {
355 char *t;
356 newhost += 3;
dc47f531 357 newhost = xstrdup(newhost);
af6a12ee
AJ
358 t = newhost + strcspn(newhost, "@/?");
359 if (*t == '@') {
360 newhost = t + 1;
361 t = newhost + strcspn(newhost, "@/?");
362 }
363 *t = '\0';
364 host = newhost;
365 }
5ac5029d
AJ
366 }
367
af6a12ee
AJ
368 if (version[0] == '-' || !version[0] || version[0] == '0') {
369 /* HTTP/0.9, no headers, no version */
5ac5029d
AJ
370 snprintf(msg, BUFSIZ, "%s %s\r\n", method, url);
371 } else {
372 snprintf(msg, BUFSIZ, "%s %s HTTP/%s\r\n", method, url, version);
62e76326 373
af6a12ee
AJ
374 if (host) {
375 snprintf(buf, BUFSIZ, "Host: %s\r\n", host);
376 strcat(msg,buf);
377 }
378
379 if (reload) {
380 snprintf(buf, BUFSIZ, "Pragma: no-cache\r\n");
381 strcat(msg, buf);
382 }
383 if (put_fd > 0) {
173bc2bf 384 snprintf(buf, BUFSIZ, "Content-length: %" PRId64 "\r\n", (int64_t) sb.st_size);
af6a12ee
AJ
385 strcat(msg, buf);
386 }
387 if (opt_noaccept == 0) {
388 snprintf(buf, BUFSIZ, "Accept: */*\r\n");
389 strcat(msg, buf);
390 }
391 if (ims) {
392 snprintf(buf, BUFSIZ, "If-Modified-Since: %s\r\n", mkrfc1123(ims));
393 strcat(msg, buf);
394 }
395 if (max_forwards > -1) {
396 snprintf(buf, BUFSIZ, "Max-Forwards: %d\r\n", max_forwards);
397 strcat(msg, buf);
398 }
399 if (proxy_user) {
400 const char *user = proxy_user;
401 const char *password = proxy_password;
230c091c 402#if HAVE_GETPASS
af6a12ee
AJ
403 if (!password)
404 password = getpass("Proxy password: ");
230c091c 405#endif
af6a12ee
AJ
406 if (!password) {
407 fprintf(stderr, "ERROR: Proxy password missing\n");
408 exit(1);
409 }
410 snprintf(buf, BUFSIZ, "%s:%s", user, password);
411 snprintf(buf, BUFSIZ, "Proxy-Authorization: Basic %s\r\n", base64_encode(buf));
412 strcat(msg, buf);
413 }
414 if (www_user) {
415 const char *user = www_user;
416 const char *password = www_password;
230c091c 417#if HAVE_GETPASS
af6a12ee
AJ
418 if (!password)
419 password = getpass("WWW password: ");
230c091c 420#endif
af6a12ee
AJ
421 if (!password) {
422 fprintf(stderr, "ERROR: WWW password missing\n");
423 exit(1);
424 }
425 snprintf(buf, BUFSIZ, "%s:%s", user, password);
426 snprintf(buf, BUFSIZ, "Authorization: Basic %s\r\n", base64_encode(buf));
427 strcat(msg, buf);
428 }
429
430 /* HTTP/1.0 may need keep-alive */
431 if (strcmp(version, "1.0") == 0) {
432 if (keep_alive) {
4f5ec547 433 if (strchr(url, ':')) {
af6a12ee 434 snprintf(buf, BUFSIZ, "Proxy-Connection: keep-alive\r\n");
4f5ec547
AJ
435 strcat(msg, buf);
436 } else
af6a12ee
AJ
437 strcat(msg, "Connection: keep-alive\r\n");
438 }
af6a12ee 439 }
51d94d10
AJ
440 /* HTTP/1.1 may need close */
441 if (!keep_alive)
442 strcat(msg, "Connection: close\r\n");
af6a12ee
AJ
443
444 strcat(msg, extra_hdrs);
445 strcat(msg, "\r\n");
a78886fc 446 }
5ac5029d 447
63259c34 448 if (opt_verbose)
d698d2a5 449 fprintf(stderr, "Request: '%s'\n", msg);
63259c34 450
899bab3f 451 if (ping) {
452#if HAVE_SIGACTION
62e76326 453
3afd7aae 454 struct sigaction sa, osa;
62e76326 455
3afd7aae
AJ
456 if (sigaction(SIGINT, NULL, &osa) == 0 && osa.sa_handler == SIG_DFL) {
457 sa.sa_handler = catchSignal;
458 sa.sa_flags = 0;
459 sigemptyset(&sa.sa_mask);
460 (void) sigaction(SIGINT, &sa, NULL);
461 }
899bab3f 462#else
3afd7aae 463 void (*osig) (int);
62e76326 464
3afd7aae
AJ
465 if ((osig = signal(SIGINT, catchSignal)) != SIG_DFL)
466 (void) signal(SIGINT, osig);
62e76326 467
899bab3f 468#endif
62e76326 469
899bab3f 470 }
471 loops = ping ? pcount : 1;
62e76326 472
899bab3f 473 for (i = 0; loops == 0 || i < loops; i++) {
3afd7aae 474 int fsize = 0;
cc192b50 475 struct addrinfo *AI = NULL;
476
3afd7aae 477 /* Connect to the server */
988e90e1 478
3afd7aae
AJ
479 if (localhost) {
480 if ( !iaddr.GetHostByName(localhost) ) {
cc192b50 481 fprintf(stderr, "client: ERROR: Cannot resolve %s: Host unknown.\n", localhost);
482 exit(1);
483 }
3afd7aae 484 } else {
cc192b50 485 /* Process the remote host name to locate the Protocol required
486 in case we are being asked to link to another version of squid */
3afd7aae 487 if ( !iaddr.GetHostByName(hostname) ) {
cc192b50 488 fprintf(stderr, "client: ERROR: Cannot resolve %s: Host unknown.\n", hostname);
489 exit(1);
490 }
491 }
492
493 iaddr.GetAddrInfo(AI);
494 if ((conn = socket(AI->ai_family, AI->ai_socktype, 0)) < 0) {
495 perror("client: socket");
496 iaddr.FreeAddrInfo(AI);
497 exit(1);
498 }
499 iaddr.FreeAddrInfo(AI);
500
501 if (localhost && client_comm_bind(conn, iaddr) < 0) {
502 perror("client: bind");
503 exit(1);
504 }
505
506 iaddr.SetEmpty();
3afd7aae 507 if ( !iaddr.GetHostByName(hostname) ) {
cc192b50 508 fprintf(stderr, "client: ERROR: Cannot resolve %s: Host unknown.\n", hostname);
509 exit(1);
510 }
511
512 iaddr.SetPort(port);
513
514 if (client_comm_connect(conn, iaddr, ping ? &tv1 : NULL) < 0) {
e053c141
FC
515 char hostnameBuf[MAX_IPSTRLEN];
516 iaddr.ToURL(hostnameBuf, MAX_IPSTRLEN);
cc192b50 517 if (errno == 0) {
e053c141 518 fprintf(stderr, "client: ERROR: Cannot connect to %s: Host unknown.\n", hostnameBuf);
cc192b50 519 } else {
520 char tbuf[BUFSIZ];
e053c141 521 snprintf(tbuf, BUFSIZ, "client: ERROR: Cannot connect to %s", hostnameBuf);
cc192b50 522 perror(tbuf);
523 }
524 exit(1);
525 }
988e90e1 526
3afd7aae
AJ
527 /* Send the HTTP request */
528 bytesWritten = mywrite(conn, msg, strlen(msg));
988e90e1 529
3afd7aae
AJ
530 if (bytesWritten < 0) {
531 perror("client: ERROR: write");
532 exit(1);
533 } else if ((unsigned) bytesWritten != strlen(msg)) {
534 fprintf(stderr, "client: ERROR: Cannot send request?: %s\n", msg);
535 exit(1);
536 }
cc192b50 537
3afd7aae
AJ
538 if (put_file) {
539 int x;
540 lseek(put_fd, 0, SEEK_SET);
0ef0f1de 541#ifdef _SQUID_MSWIN_
62e76326 542
3afd7aae 543 while ((x = read(put_fd, buf, sizeof(buf))) > 0) {
0ef0f1de 544#else
62e76326 545
3afd7aae 546 while ((x = myread(put_fd, buf, sizeof(buf))) > 0) {
0ef0f1de 547#endif
3afd7aae 548 x = mywrite(conn, buf, x);
62e76326 549
3afd7aae 550 total_bytes += x;
62e76326 551
3afd7aae
AJ
552 if (x <= 0)
553 break;
554 }
62e76326 555
3afd7aae
AJ
556 if (x != 0)
557 fprintf(stderr, "client: ERROR: Cannot send file.\n");
558 }
559 /* Read the data */
54220df8 560
0ef0f1de 561#ifdef _SQUID_MSWIN_
3afd7aae 562 setmode(1, O_BINARY);
62e76326 563
00f768c1 564#endif
62e76326 565
3afd7aae
AJ
566 while ((len = myread(conn, buf, sizeof(buf))) > 0) {
567 fsize += len;
62e76326 568
8fee788b
AR
569 if (to_stdout && fwrite(buf, len, 1, stdout) != 1)
570 perror("client: ERROR writing to stdout");
3afd7aae 571 }
62e76326 572
0ef0f1de 573#ifdef _SQUID_MSWIN_
3afd7aae 574 setmode(1, O_TEXT);
62e76326 575
0ef0f1de 576#endif
62e76326 577
3afd7aae 578 (void) close(conn); /* done with socket */
62e76326 579
3afd7aae
AJ
580 if (interrupted)
581 break;
62e76326 582
3afd7aae 583 if (ping) {
62e76326 584
3afd7aae
AJ
585 struct tm *tmp;
586 time_t t2s;
587 long elapsed_msec;
62e76326 588
3afd7aae
AJ
589 (void) Now(&tv2);
590 elapsed_msec = tvSubMsec(tv1, tv2);
591 t2s = tv2.tv_sec;
592 tmp = localtime(&t2s);
593 fprintf(stderr, "%d-%02d-%02d %02d:%02d:%02d [%d]: %ld.%03ld secs, %f KB/s\n",
594 tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday,
595 tmp->tm_hour, tmp->tm_min, tmp->tm_sec, i + 1,
596 elapsed_msec / 1000, elapsed_msec % 1000,
597 elapsed_msec ? (double) fsize / elapsed_msec : -1.0);
62e76326 598
3afd7aae
AJ
599 if (i == 0 || elapsed_msec < ping_min)
600 ping_min = elapsed_msec;
62e76326 601
3afd7aae
AJ
602 if (i == 0 || elapsed_msec > ping_max)
603 ping_max = elapsed_msec;
62e76326 604
3afd7aae 605 ping_sum += elapsed_msec;
62e76326 606
3afd7aae
AJ
607 /* Delay until next "ping_int" boundary */
608 if ((loops == 0 || i + 1 < loops) && elapsed_msec < ping_int) {
62e76326 609
3afd7aae
AJ
610 struct timeval tvs;
611 long msec_left = ping_int - elapsed_msec;
62e76326 612
3afd7aae
AJ
613 tvs.tv_sec = msec_left / 1000;
614 tvs.tv_usec = (msec_left % 1000) * 1000;
615 select(0, NULL, NULL, NULL, &tvs);
616 }
617 }
090089c4 618 }
899bab3f 619
620 if (ping && i) {
3afd7aae
AJ
621 ping_mean = ping_sum / i;
622 fprintf(stderr, "%d requests, round-trip (secs) min/avg/max = "
623 "%ld.%03ld/%ld.%03ld/%ld.%03ld\n", i,
624 ping_min / 1000, ping_min % 1000, ping_mean / 1000, ping_mean % 1000,
625 ping_max / 1000, ping_max % 1000);
090089c4 626 }
090089c4 627 exit(0);
628 /*NOTREACHED */
983061ed 629 return 0;
090089c4 630}
631
2c08acd9 632static int
e1381638
AJ
633client_comm_bind(int sock, const IpAddress &addr)
634{
62e76326 635
cc192b50 636 int res;
62e76326 637
cc192b50 638 static struct addrinfo *AI = NULL;
2c08acd9 639
640 /* Set up the source socket address from which to send. */
62e76326 641
cc192b50 642 addr.GetAddrInfo(AI);
2c08acd9 643
cc192b50 644 res = bind(sock, AI->ai_addr, AI->ai_addrlen);
645
646 addr.FreeAddrInfo(AI);
647
648 return res;
2c08acd9 649}
650
b8d8561b 651static int
e1381638
AJ
652client_comm_connect(int sock, const IpAddress &addr, struct timeval *tvp)
653{
cc192b50 654 int res;
655 static struct addrinfo *AI = NULL;
62e76326 656
cc192b50 657 /* Set up the destination socket address for message to send to. */
62e76326 658
cc192b50 659 addr.GetAddrInfo(AI);
090089c4 660
cc192b50 661 res = connect(sock, AI->ai_addr, AI->ai_addrlen);
090089c4 662
cc192b50 663 addr.FreeAddrInfo(AI);
62e76326 664
899bab3f 665 if (tvp)
cc192b50 666 (void) Now(tvp);
62e76326 667
cc192b50 668 return res;
090089c4 669}
899bab3f 670
671static int
e1381638
AJ
672Now(struct timeval *tp)
673{
899bab3f 674#if GETTIMEOFDAY_NO_TZP
675 return gettimeofday(tp);
676#else
62e76326 677
899bab3f 678 return gettimeofday(tp, NULL);
679#endif
680} /* ARGSUSED */
681
682static void
e1381638
AJ
683catchSignal(int sig)
684{
899bab3f 685 interrupted = 1;
686 fprintf(stderr, "Interrupted.\n");
687}
b6c6bcef 688
5446b331 689static void
e1381638
AJ
690pipe_handler(int sig)
691{
b6c6bcef 692 fprintf(stderr, "SIGPIPE received.\n");
54220df8 693}
694
695static void
e1381638
AJ
696set_our_signal(void)
697{
54220df8 698#if HAVE_SIGACTION
62e76326 699
54220df8 700 struct sigaction sa;
701 sa.sa_handler = pipe_handler;
702 sa.sa_flags = SA_RESTART;
703 sigemptyset(&sa.sa_mask);
62e76326 704
54220df8 705 if (sigaction(SIGPIPE, &sa, NULL) < 0) {
3afd7aae
AJ
706 fprintf(stderr, "Cannot set PIPE signal.\n");
707 exit(-1);
54220df8 708 }
709#else
710 signal(SIGPIPE, pipe_handler);
62e76326 711
54220df8 712#endif
713
714}
20cbfe5a 715
716static ssize_t
e1381638
AJ
717myread(int fd, void *buf, size_t len)
718{
00f768c1 719#ifndef _SQUID_MSWIN_
20cbfe5a 720 alarm(io_timeout);
721 return read(fd, buf, len);
00f768c1 722#else
723
724 return recv(fd, buf, len, 0);
725#endif
20cbfe5a 726}
727
728static ssize_t
e1381638
AJ
729mywrite(int fd, void *buf, size_t len)
730{
00f768c1 731#ifndef _SQUID_MSWIN_
20cbfe5a 732 alarm(io_timeout);
733 return write(fd, buf, len);
00f768c1 734#else
62e76326 735
00f768c1 736 return send(fd, buf, len, 0);
0ef0f1de 737#endif
00f768c1 738}