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