]>
Commit | Line | Data |
---|---|---|
f7f3304a | 1 | #include "squid.h" |
27bc2077 | 2 | #include "compat/getaddrinfo.h" |
eb5f55b3 | 3 | |
4 | #if HAVE_UNISTD_H | |
5 | #include <unistd.h> | |
6 | #endif | |
eb5f55b3 | 7 | #if HAVE_STDIO_H |
8 | #include <stdio.h> | |
9 | #endif | |
10 | #if HAVE_FCNTL_H | |
11 | #include <fcntl.h> | |
12 | #endif | |
32d002cb | 13 | #if HAVE_STRING_H |
eb5f55b3 | 14 | #include <string.h> |
15 | #endif | |
32d002cb | 16 | #if HAVE_STRINGS_H |
eb5f55b3 | 17 | #include <strings.h> |
18 | #endif | |
32d002cb | 19 | #if HAVE_BSTRING_H |
eb5f55b3 | 20 | #include <bstring.h> |
21 | #endif | |
eb5f55b3 | 22 | #if HAVE_SIGNAL_H |
23 | #include <signal.h> | |
24 | #endif | |
25 | #if HAVE_TIME_H | |
26 | #include <time.h> | |
27 | #endif | |
eb5f55b3 | 28 | #if HAVE_SYS_SOCKET_H |
29 | #include <sys/socket.h> | |
30 | #endif | |
31 | #if HAVE_NETINET_IN_H | |
32 | #include <netinet/in.h> | |
33 | #endif | |
34 | #if HAVE_ARPA_INET_H | |
35 | #include <arpa/inet.h> | |
36 | #endif | |
37 | #if HAVE_ERRNO_H | |
38 | #include <errno.h> | |
39 | #endif | |
40 | #if HAVE_CTYPE_H | |
41 | #include <ctype.h> | |
42 | #endif | |
43 | #if HAVE_ASSERT_H | |
44 | #include <assert.h> | |
45 | #endif | |
14ff08f1 | 46 | #if HAVE_SYS_STAT_H |
47 | #include <sys/stat.h> | |
48 | #endif | |
eb5f55b3 | 49 | |
cc192b50 | 50 | #define PROXY_PORT "3128" |
eb5f55b3 | 51 | #define PROXY_ADDR "127.0.0.1" |
52 | #define MAX_FDS 1024 | |
53 | #define READ_BUF_SZ 4096 | |
54 | #define min(x,y) ((x)<(y)? (x) : (y)) | |
55 | ||
56 | static int proxy_port = PROXY_PORT; | |
57 | static char *proxy_addr = PROXY_ADDR; | |
58 | static char *progname; | |
59 | static int noutstanding = 0; | |
60 | static int done_reading_urls = 0; | |
61 | static int opt_ims = 0; | |
14ff08f1 | 62 | static int opt_checksum = 0; |
63 | static int opt_reopen = 1; | |
64 | static int max_outstanding = 10; | |
eb5f55b3 | 65 | static time_t lifetime = 60; |
66 | static const char *const crlf = "\r\n"; | |
14ff08f1 | 67 | static int trace_fd = -1; |
68 | static int total_bytes_read = 0; | |
eb5f55b3 | 69 | |
70 | #define REPLY_HDR_SZ 8192 | |
71 | ||
72 | struct _r { | |
14ff08f1 | 73 | char url[1024]; |
eb5f55b3 | 74 | int content_length; |
75 | int hdr_length; | |
76 | int hdr_offset; | |
77 | int bytes_read; | |
78 | char reply_hdrs[REPLY_HDR_SZ]; | |
79 | struct _r *next; | |
14ff08f1 | 80 | long sum; |
81 | long validsize; | |
82 | long validsum; | |
eb5f55b3 | 83 | }; |
84 | ||
85 | static struct _r *Requests; | |
86 | ||
87 | char * | |
88 | mkrfc850(t) | |
26ac0430 | 89 | time_t *t; |
eb5f55b3 | 90 | { |
91 | static char buf[128]; | |
92 | struct tm *gmt = gmtime(t); | |
93 | buf[0] = '\0'; | |
94 | (void) strftime(buf, 127, "%A, %d-%b-%y %H:%M:%S GMT", gmt); | |
95 | return buf; | |
96 | } | |
97 | ||
eb5f55b3 | 98 | char * |
99 | mime_headers_end(const char *mime) | |
100 | { | |
101 | const char *p1, *p2; | |
102 | const char *end = NULL; | |
103 | ||
104 | p1 = strstr(mime, "\n\r\n"); | |
105 | p2 = strstr(mime, "\n\n"); | |
106 | ||
107 | if (p1 && p2) | |
26ac0430 | 108 | end = p1 < p2 ? p1 : p2; |
eb5f55b3 | 109 | else |
26ac0430 | 110 | end = p1 ? p1 : p2; |
eb5f55b3 | 111 | if (end) |
26ac0430 | 112 | end += (end == p1 ? 3 : 2); |
eb5f55b3 | 113 | |
114 | return (char *) end; | |
115 | } | |
116 | ||
117 | void | |
118 | sig_intr(int sig) | |
119 | { | |
14ff08f1 | 120 | fprintf(stderr, "\rWaiting for open connections to finish...\n"); |
eb5f55b3 | 121 | signal(sig, SIG_DFL); |
14ff08f1 | 122 | done_reading_urls = 1; |
eb5f55b3 | 123 | } |
124 | ||
125 | int | |
126 | open_http_socket(void) | |
127 | { | |
128 | int s; | |
cc192b50 | 129 | struct addrinfo *AI = NULL; |
130 | struct addrinfo hints; | |
131 | ||
132 | memset(&hints, '\0', sizeof(struct addrinfo)); | |
133 | hints.ai_flags = AI_NUMERICHOST|AI_NUMERICSERV; | |
134 | hints.ai_family = AF_UNSPEC; | |
135 | hints.ai_socktype = SOCK_STREAM; | |
136 | ||
27bc2077 | 137 | getaddrinfo(proxy_addr, proxy_port, &hints, AI); |
cc192b50 | 138 | |
139 | if ((s = socket(AI->ai_family, AI->ai_socktype, AI->ai_protocol)) < 0) { | |
26ac0430 | 140 | perror("socket"); |
b1c8a478 A |
141 | s = -1; |
142 | } else if (connect(s, AI->ai_addr, AI->ai_addrlen) < 0) { | |
26ac0430 AJ |
143 | close(s); |
144 | perror("connect"); | |
27bc2077 | 145 | s = -1; |
eb5f55b3 | 146 | } |
cc192b50 | 147 | |
27bc2077 | 148 | freeaddrinfo(AI); |
eb5f55b3 | 149 | return s; |
150 | } | |
151 | ||
152 | int | |
14ff08f1 | 153 | send_request(int fd, const char *data) |
eb5f55b3 | 154 | { |
468ae12b | 155 | char msg[4096], buf[4096]; |
eb5f55b3 | 156 | int len; |
157 | time_t w; | |
158 | struct _r *r; | |
159 | struct _r **R; | |
14ff08f1 | 160 | char *method, *url, *file, *size, *checksum; |
161 | char *tmp = strdup(data); | |
162 | struct stat st; | |
163 | int file_fd = -1; | |
468ae12b | 164 | method = strtok(tmp, " "); |
165 | url = strtok(NULL, " "); | |
166 | file = strtok(NULL, " "); | |
167 | size = strtok(NULL, " "); | |
168 | checksum = strtok(NULL, " "); | |
14ff08f1 | 169 | if (!url) { |
26ac0430 AJ |
170 | url = method; |
171 | method = "GET"; | |
14ff08f1 | 172 | } |
468ae12b | 173 | if (file && strcmp(file, "-") == 0) |
26ac0430 | 174 | file = NULL; |
468ae12b | 175 | if (size && strcmp(size, "-") == 0) |
26ac0430 | 176 | size = NULL; |
468ae12b | 177 | if (checksum && strcmp(checksum, "-") == 0) |
26ac0430 | 178 | checksum = NULL; |
14ff08f1 | 179 | msg[0] = '\0'; |
180 | sprintf(buf, "%s %s HTTP/1.0\r\n", method, url); | |
468ae12b | 181 | strcat(msg, buf); |
14ff08f1 | 182 | strcat(msg, "Accept: */*\r\n"); |
183 | strcat(msg, "Proxy-Connection: Keep-Alive\r\n"); | |
eb5f55b3 | 184 | if (opt_ims && (lrand48() & 0x03) == 0) { |
26ac0430 AJ |
185 | w = time(NULL) - (lrand48() & 0x3FFFF); |
186 | sprintf(buf, "If-Modified-Since: %s\r\n", mkrfc850(&w)); | |
187 | strcat(msg, buf); | |
eb5f55b3 | 188 | } |
14ff08f1 | 189 | if (file) { |
26ac0430 AJ |
190 | if ((file_fd = open(file, O_RDONLY)) < 0) { |
191 | perror("open"); | |
192 | return -1; | |
193 | } | |
194 | if (fstat(file_fd, &st)) { | |
195 | perror("fstat"); | |
196 | close(file_fd); | |
197 | return -1; | |
198 | } | |
199 | sprintf(buf, "Content-length: %d\r\n", st.st_size); | |
200 | strcat(msg, buf); | |
14ff08f1 | 201 | } |
202 | strcat(msg, "\r\n"); | |
203 | len = strlen(msg); | |
204 | if (write(fd, msg, len) < 0) { | |
26ac0430 AJ |
205 | close(fd); |
206 | perror("request write"); | |
207 | close(file_fd); | |
208 | return -1; | |
eb5f55b3 | 209 | } |
14ff08f1 | 210 | if (file) { |
26ac0430 AJ |
211 | while ((len = read(file_fd, buf, sizeof buf)) > 0) { |
212 | if (write(fd, buf, len) < 0) { | |
213 | close(fd); | |
214 | perror("body write"); | |
215 | close(file_fd); | |
216 | return -1; | |
217 | } | |
218 | } | |
219 | if (len < 0) { | |
220 | perror("file read"); | |
221 | close(file_fd); | |
222 | return -1; | |
223 | } | |
224 | close(file_fd); | |
14ff08f1 | 225 | } |
eb5f55b3 | 226 | r = calloc(1, sizeof(struct _r)); |
14ff08f1 | 227 | strcpy(r->url, url); |
228 | if (size) | |
26ac0430 | 229 | r->validsize = atoi(size); |
14ff08f1 | 230 | else |
26ac0430 | 231 | r->validsize = -1; |
14ff08f1 | 232 | if (checksum) |
26ac0430 | 233 | r->validsum = atoi(checksum); |
eb5f55b3 | 234 | for (R = &Requests; *R; R = &(*R)->next); |
235 | *R = r; | |
26ac0430 | 236 | /* fprintf(stderr, "REQUESTED %s\n", url); */ |
eb5f55b3 | 237 | noutstanding++; |
238 | return 0; | |
239 | } | |
240 | ||
241 | static int | |
242 | get_header_int_value(const char *hdr, const char *buf, const char *end) | |
243 | { | |
244 | const char *t; | |
245 | for (t = buf; t < end; t += strcspn(t, crlf), t += strspn(t, crlf)) { | |
26ac0430 AJ |
246 | if (strncasecmp(t, hdr, strlen(hdr)) == 0) { |
247 | t += strlen(hdr); | |
248 | while (xisspace(*t)) | |
249 | t++; | |
250 | return atoi(t); | |
251 | } | |
eb5f55b3 | 252 | } |
14ff08f1 | 253 | return -1; |
eb5f55b3 | 254 | } |
255 | ||
14ff08f1 | 256 | static const char * |
257 | get_header_string_value(const char *hdr, const char *buf, const char *end) | |
258 | { | |
259 | const char *t; | |
260 | static char result[8192]; | |
261 | for (t = buf; t < end; t += strcspn(t, crlf), t += strspn(t, crlf)) { | |
26ac0430 AJ |
262 | if (strncasecmp(t, hdr, strlen(hdr)) == 0) { |
263 | t += strlen(hdr); | |
264 | while (xisspace(*t)) | |
265 | t++; | |
266 | strcpy(result, ""); | |
267 | strncat(result, t, strcspn(t, crlf)); | |
268 | return result; | |
269 | } | |
14ff08f1 | 270 | } |
271 | return NULL; | |
272 | } | |
273 | ||
274 | void | |
275 | request_done(struct _r *r) | |
276 | { | |
277 | #if 0 | |
278 | fprintf(stderr, "DONE: %s, (%d+%d)\n", | |
26ac0430 AJ |
279 | r->url, |
280 | r->hdr_length, | |
281 | r->content_length); | |
14ff08f1 | 282 | #endif |
283 | if (r->content_length != r->bytes_read) | |
26ac0430 AJ |
284 | fprintf(stderr, "ERROR! Short reply, expected %d bytes got %d\n", |
285 | r->content_length, r->bytes_read); | |
14ff08f1 | 286 | else if (r->validsize >= 0) { |
26ac0430 AJ |
287 | if (r->validsize != r->bytes_read) |
288 | fprintf(stderr, "WARNING: %s Object size mismatch, expected %d got %d\n", | |
289 | r->url, r->validsize, r->bytes_read); | |
290 | else if (opt_checksum && r->sum != r->validsum) | |
291 | fprintf(stderr, "WARNING: %s Checksum error. Expected %d got %d\n", | |
292 | r->url, r->validsum, r->sum); | |
14ff08f1 | 293 | } |
294 | } | |
eb5f55b3 | 295 | int |
14ff08f1 | 296 | handle_read(char *inbuf, int len) |
eb5f55b3 | 297 | { |
298 | struct _r *r = Requests; | |
299 | const char *end; | |
14ff08f1 | 300 | const char *url; |
301 | static char buf[READ_BUF_SZ]; | |
468ae12b | 302 | int hlen, blen; |
303 | if (len < 0) { | |
26ac0430 AJ |
304 | perror("read"); |
305 | Requests = r->next; | |
306 | request_done(r); | |
307 | free(r); | |
308 | noutstanding--; | |
309 | if (trace_fd >= 0) | |
310 | write(trace_fd, "\n[CLOSED]\n", 10); | |
311 | return -1; | |
eb5f55b3 | 312 | } |
14ff08f1 | 313 | total_bytes_read += len; |
41d00cd3 | 314 | memcpy(buf, inbuf, len); |
eb5f55b3 | 315 | if (len == 0) { |
26ac0430 AJ |
316 | fprintf(stderr, "WARNING: %s, server closed socket after %d+%d bytes\n", r->url, r->hdr_offset, r->bytes_read); |
317 | /* XXX, If no data was received and it isn't the first request on this | |
318 | * connection then the request should be restarted rather than aborted | |
319 | * but this is a simple test program an not a full blown HTTP client. | |
320 | */ | |
321 | request_done(r); | |
322 | Requests = r->next; | |
323 | free(r); | |
324 | noutstanding--; | |
325 | return -1; | |
eb5f55b3 | 326 | } |
14ff08f1 | 327 | if (trace_fd > 0) |
26ac0430 | 328 | write(trace_fd, buf, len); |
14ff08f1 | 329 | while (len > 0) { |
26ac0430 AJ |
330 | /* Build headers */ |
331 | if (r->hdr_length == 0) { | |
332 | hlen = min(len, REPLY_HDR_SZ - r->hdr_offset - 1); | |
41d00cd3 | 333 | memcpy(r->reply_hdrs + r->hdr_offset, buf, hlen); |
26ac0430 AJ |
334 | r->hdr_offset += hlen; |
335 | r->reply_hdrs[r->hdr_offset] = '\0'; | |
336 | len -= hlen; | |
337 | /* Save any remaining read data */ | |
41d00cd3 | 338 | memmove(buf, buf + hlen, len); |
26ac0430 AJ |
339 | } |
340 | /* Process headers */ | |
341 | if (r->hdr_length == 0 && (end = mime_headers_end(r->reply_hdrs)) != NULL) { | |
14ff08f1 | 342 | #if 0 |
26ac0430 AJ |
343 | fprintf(stderr, "FOUND EOH FOR %s\n", r->url); |
344 | */ | |
14ff08f1 | 345 | #endif |
26ac0430 | 346 | r->hdr_length = end - r->reply_hdrs; |
14ff08f1 | 347 | #if 0 |
26ac0430 | 348 | fprintf(stderr, "HDR_LENGTH = %d\n", r->hdr_length); |
14ff08f1 | 349 | #endif |
26ac0430 AJ |
350 | /* "unread" any body contents received */ |
351 | blen = r->hdr_offset - r->hdr_length; | |
352 | assert(blen >= 0); | |
353 | if (blen > 0) { | |
41d00cd3 AJ |
354 | memmove(buf + blen, buf, len); |
355 | memcpy(buf, r->reply_hdrs + r->hdr_length, blen); | |
26ac0430 AJ |
356 | len += blen; |
357 | } | |
358 | r->reply_hdrs[r->hdr_length] = '\0'; /* Null terminate headers */ | |
359 | /* Parse headers */ | |
360 | r->content_length = get_header_int_value("content-length:", r->reply_hdrs, end); | |
361 | /* fprintf(stderr, "CONTENT_LENGTH = %d\n", r->content_length); */ | |
362 | url = get_header_string_value("X-Request-URI:", r->reply_hdrs, end); | |
363 | if (url != NULL && strcmp(r->url, url) != 0) | |
364 | fprintf(stderr, "WARNING: %s got reply %s\n", r->url, url); | |
14ff08f1 | 365 | #if XREQUESTURI || 0 |
26ac0430 | 366 | fprintf(stderr, "LOCATION = %s\n", get_header_string_value("X-Request-URI:", r->reply_hdrs, end)); |
14ff08f1 | 367 | #endif |
26ac0430 AJ |
368 | } |
369 | if (!(len == 0 || r->hdr_length > 0)) { | |
370 | fprintf(stderr, "ERROR!!!\n"); | |
371 | assert((len == 0 || r->hdr_length > 0)); | |
372 | } | |
373 | /* Process body */ | |
374 | if (r->hdr_length != 0) { | |
375 | int i; | |
376 | int bytes_left, bytes_used; | |
377 | if (r->content_length >= 0) { | |
378 | bytes_left = r->content_length - r->bytes_read; | |
379 | assert(bytes_left >= 0); | |
380 | bytes_used = len < bytes_left ? len : bytes_left; | |
381 | } else { | |
382 | bytes_left = len + 1; /* Unknown end... */ | |
383 | bytes_used = len; | |
384 | } | |
385 | if (opt_checksum) { | |
386 | for (i = 0; i < bytes_used; i++) | |
387 | r->sum += (int) buf[i] & 0xFF; | |
388 | } | |
389 | r->bytes_read += bytes_used; | |
390 | len -= bytes_used; | |
391 | if (bytes_left == bytes_used) { | |
392 | request_done(r); | |
393 | Requests = r->next; | |
394 | free(r); | |
395 | noutstanding--; | |
396 | r = Requests; | |
397 | } else if (r->content_length > -1) { | |
398 | assert(r->bytes_read < r->content_length); | |
399 | } | |
41d00cd3 | 400 | memmove(buf, buf + bytes_used, len); |
26ac0430 | 401 | } |
eb5f55b3 | 402 | } |
403 | return 0; | |
404 | } | |
405 | ||
406 | int | |
407 | read_reply(int fd) | |
408 | { | |
409 | static char buf[READ_BUF_SZ]; | |
410 | int len; | |
411 | int x; | |
412 | len = read(fd, buf, READ_BUF_SZ); | |
413 | x = handle_read(buf, len); | |
14ff08f1 | 414 | if (x < 0) { |
26ac0430 AJ |
415 | perror("read reply"); |
416 | close(fd); | |
14ff08f1 | 417 | } |
eb5f55b3 | 418 | return x; |
419 | } | |
420 | ||
421 | void | |
422 | main_loop(void) | |
423 | { | |
424 | static int pconn_fd = -1; | |
425 | static char buf[8192]; | |
426 | struct timeval to; | |
468ae12b | 427 | struct timeval now, last, start; |
eb5f55b3 | 428 | fd_set R; |
429 | struct _r *r; | |
430 | struct _r *nextr; | |
431 | int x; | |
e3fc4f10 | 432 | int timeouts; |
14ff08f1 | 433 | int nrequests = 0, rrequests = 0, reqpersec = 0; |
434 | ||
435 | gettimeofday(&start, NULL); | |
436 | last = start; | |
437 | ||
438 | pconn_fd = open_http_socket(); | |
439 | if (pconn_fd < 0) { | |
26ac0430 AJ |
440 | perror("socket"); |
441 | exit(1); | |
14ff08f1 | 442 | } |
eb5f55b3 | 443 | while (!done_reading_urls || noutstanding) { |
26ac0430 AJ |
444 | if (!opt_reopen && pconn_fd < 0) { |
445 | fprintf(stderr, "TERMINATED: Connection closed\n"); | |
446 | break; | |
447 | } | |
448 | if (pconn_fd < 0) { | |
449 | pconn_fd = open_http_socket(); | |
450 | if (pconn_fd < 0) { | |
451 | perror("socket"); | |
452 | exit(1); | |
453 | } | |
454 | nextr = Requests; | |
455 | Requests = NULL; | |
456 | noutstanding = 0; | |
457 | while ((r = nextr) != NULL) { | |
458 | nextr = r->next; | |
459 | if (send_request(pconn_fd, r->url) != 0) { | |
460 | close(pconn_fd); | |
461 | pconn_fd = -1; | |
462 | nextr = r; | |
463 | for (r = Requests; r != NULL && r->next; r = r->next); | |
464 | if (r != NULL) | |
465 | r->next = nextr; | |
466 | else | |
467 | Requests = nextr; | |
468 | break; | |
469 | } | |
470 | free(r); | |
471 | } | |
472 | timeouts = 0; | |
473 | if (pconn_fd < 0) | |
474 | continue; | |
475 | } | |
476 | if (timeouts == 200) { | |
477 | close(pconn_fd); | |
478 | pconn_fd = -1; | |
479 | r = Requests; | |
480 | Requests = Requests->next; | |
481 | fprintf(stderr, "ABORT %s\n", Requests->url); | |
482 | free(r); | |
483 | noutstanding--; | |
484 | } | |
485 | if (pconn_fd >= 0 && noutstanding < max_outstanding && !done_reading_urls) { | |
486 | char *t; | |
487 | if (fgets(buf, 8191, stdin) == NULL) { | |
488 | fprintf(stderr, "Done Reading URLS\n"); | |
489 | done_reading_urls = 1; | |
490 | continue; | |
491 | } | |
492 | rrequests++; | |
493 | if ((t = strchr(buf, '\n'))) | |
494 | *t = '\0'; | |
495 | if (send_request(pconn_fd, buf) != 0) { | |
496 | close(pconn_fd); | |
497 | pconn_fd = -1; | |
498 | continue; | |
499 | } | |
500 | nrequests++; | |
501 | reqpersec++; | |
502 | timeouts = 0; | |
503 | } | |
504 | FD_ZERO(&R); | |
505 | to.tv_sec = 1; | |
506 | to.tv_usec = 0; | |
507 | FD_SET(pconn_fd, &R); | |
508 | x = select(pconn_fd + 1, &R, NULL, NULL, &to); | |
509 | if (x < 0) { | |
510 | if (errno != EINTR) | |
511 | perror("select"); | |
512 | continue; | |
513 | } else if (x == 0) { | |
514 | assert(Requests != NULL); | |
515 | fprintf(stderr, "TIMEOUT %s; %d, %d\n", Requests->url, | |
516 | ++timeouts, noutstanding); | |
517 | continue; | |
518 | } | |
519 | if (FD_ISSET(pconn_fd, &R)) { | |
520 | timeouts = 0; | |
521 | if (read_reply(pconn_fd) != 0) | |
522 | pconn_fd = -1; | |
523 | } | |
524 | gettimeofday(&now, NULL); | |
525 | if (now.tv_sec > last.tv_sec) { | |
526 | int dt; | |
527 | int nreq; | |
528 | last = now; | |
529 | dt = (int) (now.tv_sec - start.tv_sec); | |
530 | nreq = 0; | |
531 | for (r = Requests; r; r = r->next) | |
532 | nreq++; | |
533 | printf("T+ %6d: %9d req (%+4d), %4d pend, %3d/sec avg, %dmb, %dkb/sec avg\n", | |
534 | dt, | |
535 | nrequests, | |
536 | reqpersec, | |
537 | nreq, | |
538 | (int) (nrequests / dt), | |
539 | (int) total_bytes_read / 1024 / 1024, | |
540 | (int) total_bytes_read / 1024 / dt); | |
541 | reqpersec = 0; | |
542 | } | |
eb5f55b3 | 543 | } |
544 | } | |
545 | ||
546 | void | |
547 | usage(void) | |
548 | { | |
14ff08f1 | 549 | fprintf(stderr, "usage: %s: -p port -h host -n max -t tracefile -i -c -l lifetime\n", progname); |
eb5f55b3 | 550 | } |
551 | ||
552 | int | |
553 | main(argc, argv) | |
26ac0430 AJ |
554 | int argc; |
555 | char *argv[]; | |
eb5f55b3 | 556 | { |
557 | int c; | |
558 | setbuf(stdout, NULL); | |
559 | setbuf(stderr, NULL); | |
560 | progname = strdup(argv[0]); | |
14ff08f1 | 561 | while ((c = getopt(argc, argv, "p:h:n:t:icl:r")) != -1) { |
26ac0430 AJ |
562 | switch (c) { |
563 | case 'p': | |
564 | proxy_port = atoi(optarg); | |
565 | break; | |
566 | case 'h': | |
567 | proxy_addr = strdup(optarg); | |
568 | break; | |
569 | case 'n': | |
570 | max_outstanding = atoi(optarg); | |
571 | break; | |
572 | case 'i': | |
573 | opt_ims = 1; | |
574 | break; | |
575 | case 'c': | |
576 | opt_checksum = 1; | |
577 | break; | |
578 | case 'l': | |
579 | lifetime = (time_t) atoi(optarg); | |
580 | break; | |
581 | case 't': | |
582 | trace_fd = open(optarg, O_WRONLY | O_CREAT | O_TRUNC, 0666); | |
583 | break; | |
584 | case 'r': | |
585 | opt_reopen = !opt_reopen; | |
586 | break; | |
587 | default: | |
588 | usage(); | |
589 | return 1; | |
590 | } | |
eb5f55b3 | 591 | } |
592 | signal(SIGINT, sig_intr); | |
5616e319 | 593 | signal(SIGPIPE, SIG_IGN); |
eb5f55b3 | 594 | main_loop(); |
595 | return 0; | |
596 | } |