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