jcc.c
上传用户:qunlip
上传日期:2007-01-04
资源大小:203k
文件大小:21k
源码类别:

代理服务器

开发平台:

Visual C++

  1. char *jcc_rcs = "$Id: jcc.c,v 3.42 1998/10/29 03:11:21 ACJC Exp $";
  2. /* Written and copyright 1997 Anonymous Coders and Junkbusters Corporation.
  3.  * Distributed under the GNU General Public License; see the README file.
  4.  * This code comes with NO WARRANTY. http://www.junkbusters.com/ht/en/gpl.html
  5.  */
  6. #include <stdio.h>
  7. #include <sys/types.h>
  8. #include <stdlib.h>
  9. #include <ctype.h>
  10. #include <string.h>
  11. #include <signal.h>
  12. #include <fcntl.h>
  13. #include <errno.h>
  14. #ifdef _WIN32
  15. #include <sys/timeb.h>
  16. #include <windows.h>
  17. #include <io.h>
  18. #include <process.h>
  19. #else
  20. #include <unistd.h>
  21. #include <sys/time.h>
  22. #include <sys/wait.h>
  23. #include <sys/stat.h>
  24. #ifdef __BEOS__
  25. #include <socket.h> /* BeOS has select() for sockets only. */
  26. #include <OS.h> /* declarations for threads and stuff. */
  27. #endif
  28. #ifndef FD_ZERO
  29. #include <select.h>
  30. #endif
  31. #endif
  32. #ifdef REGEX
  33. #include <gnu_regex.h>
  34. #endif
  35. #include "jcc.h"
  36. char *prog;
  37. #define BODY "<body bgcolor="#f8f8f0" link="#000078" alink="#ff0022" vlink="#787878">n"
  38. char CFAIL[]   = "HTTP/1.0 503 Connect failedn"
  39.  "Content-Type: text/htmlnn"
  40.  "<html>n"
  41.  "<head>n"
  42.  "<title>Internet Junkbuster: Connect failed</title>n"
  43.  "</head>n"
  44.  BODY
  45.  "<h1><center>"
  46.  BANNER
  47.  "</center></h1>"
  48.  "TCP connection to '%s' failed: %s.n<br>"
  49.  "</body>n"
  50.  "</html>n"
  51.  ;
  52. char CNXDOM[]  = "HTTP/1.0 404 Non-existent domainn"
  53.  "Content-Type: text/htmlnn"
  54.  "<html>n"
  55.  "<head>n"
  56.  "<title>Internet Junkbuster: Non-existent domain</title>n"
  57.  "</head>n"
  58.  BODY
  59.  "<h1><center>"
  60.  BANNER
  61.  "</center></h1>"
  62.  "No such domain: %sn"
  63.  "</body>n"
  64.  "</html>n"
  65.  ;
  66. char CSUCCEED[] = "HTTP/1.0 200 Connection establishedn"
  67.   "Proxy-Agent: IJ/" VERSION "nn"
  68.   ;
  69. char CHEADER[] = "HTTP/1.0 400 Invalid header received from browsernn";
  70. char SHEADER[] = "HTTP/1.0 502 Invalid header received from servernn";
  71. char VANILLA_WAFER[] =
  72. "NOTICE=TO_WHOM_IT_MAY_CONCERN_"
  73. "Do_not_send_me_any_copyrighted_information_other_than_the_"
  74. "document_that_I_am_requesting_or_any_of_its_necessary_components._"
  75. "In_particular_do_not_send_me_any_cookies_that_"
  76. "are_subject_to_a_claim_of_copyright_by_anybody._"
  77. "Take_notice_that_I_refuse_to_be_bound_by_any_license_condition_"
  78. "(copyright_or_otherwise)_applying_to_any_cookie._";
  79. char DEFAULT_USER_AGENT[] ="User-Agent: Mozilla/3.01Gold (Macintosh; I; 68K)";
  80. int debug           = 0;
  81. int multi_threaded  = 1;
  82. int hideConsole     = 0;
  83. #ifdef _WIN32
  84. #define sleep(N) Sleep(((N) * 1000))
  85. #endif
  86. char *logfile = NULL;
  87. FILE *logfp;
  88. char *blockfile    = NULL;
  89. char *cookiefile   = NULL;
  90. char *trustfile    = NULL;
  91. char *forwardfile  = NULL;
  92. char *aclfile      = NULL;
  93. char *jarfile = NULL;
  94. FILE *jar;
  95. char *referrer   = NULL;
  96. char *uagent     = NULL;
  97. char *from       = NULL;
  98. int suppress_vanilla_wafer = 0;
  99. int add_forwarded      = 0;
  100. struct client_state clients[1];
  101. struct file_list    files[1];
  102. struct list wafer_list[1];
  103. struct list xtra_list[1];
  104. struct list trust_info[1];
  105. struct url_spec * trust_list[64];
  106. int (*loaders[NLOADERS])();
  107. struct gateway gateways[] = {
  108. /* type         function        gw type/host/port,    fw host/port*/
  109. { "direct", direct_connect, 0,        NULL, 0,     NULL, 0    },
  110. { ".", direct_connect, 0,        NULL, 0,     NULL, 0    },
  111. { "socks", socks4_connect, SOCKS_4,  NULL, 1080,  NULL, 0    },
  112. { "socks4", socks4_connect, SOCKS_4,  NULL, 1080,  NULL, 0    },
  113. { "socks4a", socks4_connect, SOCKS_4A, NULL, 1080,  NULL, 0    },
  114. { NULL, NULL,           0,        NULL, 0,     NULL, 0    }
  115. };
  116. struct gateway *gw_default = gateways;
  117. char *haddr = "127.0.0.1"; /* default binding to localhost */
  118. int   hport = 8000;
  119. struct proxy_args proxy_args[1];
  120. int
  121. write_socket(int fd, char *buf, int n)
  122. {
  123. if(n <= 0) return(0);
  124. if(DEBUG(LOG)) fwrite(buf, n, 1, logfp);
  125. #if defined(_WIN32) || defined(__BEOS__)
  126. return send(fd, buf, n, 0);
  127. #else
  128. return write(fd, buf, n);
  129. #endif
  130. }
  131. int
  132. read_socket(int fd, char *buf, int n)
  133. {
  134. if(n <= 0) return(0);
  135. #if defined(_WIN32) || defined(__BEOS__)
  136. return recv(fd, buf, n, 0);
  137. #else
  138. return read(fd, buf, n);
  139. #endif
  140. }
  141. void
  142. close_socket(int fd)
  143. {
  144. #if defined(_WIN32) || defined(__BEOS__)
  145. closesocket(fd);
  146. #else
  147. close(fd);
  148. #endif
  149. }
  150. void
  151. chat(struct client_state *csp)
  152. {
  153. char buf[BUFSIZ], *hdr, *p, *req;
  154. char *err = NULL;
  155. char *eno;
  156. fd_set rfds;
  157. int n, maxfd, server_body;
  158. struct cookie_spec *cs;
  159. struct gateway *gw;
  160. struct http_request *http;
  161. http = csp->http;
  162. /* read the client's request.
  163.  * note that since we're not using select()
  164.  * we could get blocked here if a client 
  165.  * connected, then didn't say anything!
  166.  */
  167. for(;;) {
  168. n = read_socket(csp->cfd, buf, sizeof(buf));
  169. if(n <= 0) break; /* error! */
  170. add_to_iob(csp, buf, n);
  171. req = get_header(csp);
  172. if(req == NULL) break; /* no HTTP request! */
  173. if(*req == '') continue; /* more to come! */
  174. parse_http_request(req, http, csp);
  175. freez(req);
  176. break;
  177. }
  178. if(http->cmd == NULL) {
  179. strcpy(buf, CHEADER);
  180. write_socket(csp->cfd, buf, strlen(buf));
  181. return;
  182. }
  183. /* decide how to route the HTTP request */
  184. if((gw = forward_url(http, csp)) == NULL) {
  185. fprintf(logfp,
  186. "%s: gateway spec is NULL!?!?  This can't happen!n", prog);
  187. abort();
  188. }
  189. /* build the http request to send to the server
  190.  * we have to do one of the following:
  191.  *
  192.  * create = use the original HTTP request to create a new
  193.  *          HTTP request that has only the path component
  194.  *          without the http://domainspec
  195.  * pass   = pass the original HTTP request unchanged
  196.  *
  197.  * drop   = drop the HTTP request
  198.  *     
  199.  * here's the matrix:
  200.  *                        SSL
  201.  *                    0        1
  202.          *                +--------+--------+
  203.          *                |        |        |
  204.          *             0  | create | drop   |
  205.          *                |        |        |
  206.          *  Forwarding    +--------+--------+
  207.          *                |        |        |
  208.          *             1  | pass   | pass   |
  209.          *                |        |        |
  210.          *                +--------+--------+
  211.          *
  212.          */
  213. if(gw->forward_host) {
  214. /* if forwarding, just pass the request as is */
  215. enlist(csp->headers, http->cmd);
  216. } else {
  217. if(http->ssl == 0) {
  218. /* otherwise elide the host information from the url */
  219. p = NULL;
  220. p = strsav(p, http->gpc);
  221. p = strsav(p, " ");
  222. p = strsav(p, http->path);
  223. p = strsav(p, " ");
  224. p = strsav(p, http->ver);
  225. enlist(csp->headers, p);
  226. freez(p);
  227. }
  228. }
  229. /* decide what we're to do with cookies */
  230. if((cs = cookie_url(http, csp))) {
  231. csp->accept_server_cookie  = cs->accept_server_cookie;
  232. csp->send_user_cookie      = cs->send_user_cookie;
  233. } else {
  234. csp->accept_server_cookie  = 0;
  235. csp->send_user_cookie      = 0;
  236. }
  237. /* grab the rest of the client's headers */
  238. for(;;) {
  239. if(( p = get_header(csp))
  240. && (*p == '')) {
  241. n = read_socket(csp->cfd, buf, sizeof(buf));
  242. if(n <= 0) {
  243. fprintf(logfp,
  244. "%s: read from client failed: ", prog);
  245. fperror(logfp, "");
  246. return;
  247. }
  248. add_to_iob(csp, buf, n);
  249. continue;
  250. }
  251. if(p == NULL) break;
  252. enlist(csp->headers, p);
  253. freez(p);
  254. }
  255. /* filter it as required */
  256. hdr = sed(client_patterns, add_client_headers, csp);
  257. destroy_list(csp->headers);
  258. if((p = intercept_url(http, csp))
  259. || (p =     block_url(http, csp))
  260. || (p =     trust_url(http, csp))) {
  261. if(DEBUG(GPC)) {
  262. fprintf(logfp, "%s: GPCt%s%s crunch!n",
  263. prog, http->hostport, http->path);
  264. }
  265. write_socket(csp->cfd, p, strlen(p));
  266. if(DEBUG(LOG)) fwrite(p, strlen(p), 1, logfp);
  267. freez(p);
  268. freez(hdr);
  269. return;
  270. }
  271. if(DEBUG(GPC)) {
  272. fprintf(logfp, "%s: GPCt%s%sn",
  273. prog, http->hostport, http->path);
  274. }
  275. if(DEBUG(CON)) {
  276. if(gw->forward_host) {
  277. fprintf(logfp,
  278. "%s: connect via %s:%d to: %s ... ",
  279. prog,
  280. gw->forward_host,
  281. gw->forward_port,
  282. http->hostport);
  283. } else {
  284. fprintf(logfp,
  285. "%s: connect to: %s ... ",
  286. prog, http->hostport);
  287. }
  288. }
  289. /* here we connect to the server, gateway, or the forwarder */
  290. csp->sfd = (gw->conn)(gw, http, csp);
  291. if(csp->sfd < 0) {
  292. if(DEBUG(CON)) {
  293. fprintf(logfp, "%s: connect to: %s failed: ",
  294. prog, http->hostport);
  295. fperror(logfp, "");
  296. }
  297. if(errno == EINVAL) {
  298. err = zalloc(strlen(CNXDOM) + strlen(http->host));
  299. sprintf(err, CNXDOM, http->host);
  300. } else {
  301. eno = safe_strerror(errno);
  302. err = zalloc(strlen(CFAIL) + strlen(http->hostport) + strlen(eno));
  303. sprintf(err, CFAIL, http->hostport, eno);
  304. }
  305. write_socket(csp->cfd, err, strlen(err));
  306. if(DEBUG(LOG)) fwrite(err, strlen(err), 1, logfp);
  307. freez(err);
  308. freez(hdr);
  309. return;
  310. }
  311. if(DEBUG(CON)) {
  312. fprintf(logfp, "OKn");
  313. }
  314. if(gw->forward_host || (http->ssl == 0)) {
  315. /* write the client's (modified) header to the server
  316.  * (along with anything else that may be in the buffer)
  317.  */
  318. n = strlen(hdr);
  319. if((write_socket(csp->sfd, hdr, n) != n)
  320. || (flush_socket(csp->sfd, csp   ) <  0)) {
  321. if(DEBUG(CON)) {
  322. fprintf(logfp, "%s: write header to: %s failed: ",
  323. prog, http->hostport);
  324. fperror(logfp, "");
  325. }
  326. eno = safe_strerror(errno);
  327. err = zalloc(strlen(CFAIL) + strlen(http->hostport) + strlen(eno));
  328. sprintf(err, CFAIL, http->hostport, eno);
  329. write_socket(csp->cfd, err, strlen(err));
  330. freez(err);
  331. freez(hdr);
  332. return;
  333. }
  334. } else {
  335. /* we're running an SSL tunnel and we're not
  336.  * forwarding, so just send the "connect succeeded"
  337.  * message to the client, flush the rest, and
  338.  * get out of the way.
  339.  */
  340. if(write_socket(csp->cfd, CSUCCEED, sizeof(CSUCCEED)-1) < 0) {
  341. freez(hdr);
  342. return;
  343. }
  344. IOB_RESET(csp);
  345. }
  346. /* we're finished with the client's header */
  347. freez(hdr);
  348. maxfd = ( csp->cfd > csp->sfd ) ? csp->cfd : csp->sfd;
  349. /* pass data between the client and server
  350.  * until one or the other shuts down the connection.
  351.  */
  352. server_body = 0;
  353. for(;;) {
  354. FD_ZERO(&rfds);
  355. FD_SET(csp->cfd, &rfds);
  356. FD_SET(csp->sfd, &rfds);
  357. n = select(maxfd+1, &rfds, NULL, NULL, NULL);
  358. if(n < 0) {
  359. fprintf(logfp, "%s: select() failed!: ", prog);
  360. fperror(logfp, "");
  361. return;
  362. }
  363. /* this is the body of the browser's request
  364.  * just read it and write it.
  365.  */
  366. if(FD_ISSET(csp->cfd, &rfds)) {
  367. n = read_socket(csp->cfd, buf, sizeof(buf));
  368. if(n <= 0) break; /* "game over, man" */
  369. if(write_socket(csp->sfd, buf, n) != n) {
  370. fprintf(logfp, "%s: write to: %s failed: ",
  371. prog, http->host);
  372. fperror(logfp, "");
  373. return;
  374. }
  375. continue;
  376. }
  377. /* the server wants to talk.
  378.  * it could be the header or the body.
  379.  * if `hdr' is null, then it's the header
  380.  * otherwise it's the body
  381.  */
  382. if(FD_ISSET(csp->sfd, &rfds)) {
  383. n = read_socket(csp->sfd, buf, sizeof(buf));
  384. if(n < 0) {
  385. fprintf(logfp, "%s: read from: %s failed: ",
  386. prog, http->host);
  387. fperror(logfp, "");
  388. eno = safe_strerror(errno);
  389. sprintf(buf, CFAIL, http->hostport, eno);
  390. freez(eno);
  391. write_socket(csp->cfd, buf, strlen(buf));
  392. return;
  393. }
  394. if(n == 0) break; /* "game over, man" */
  395. /* if this is an SSL connection or we're in the body
  396.  * of the server document, just write it to the client.
  397.  */
  398. if(server_body || http->ssl) {
  399. /* just write */
  400. if(write_socket(csp->cfd, buf, n) != n) {
  401. fprintf(logfp, "%s: write to client failed: ",
  402. prog);
  403. fperror(logfp, "");
  404. return;
  405. }
  406. continue;
  407. } else {
  408. /* we're still looking for the end of the
  409.  * server's header ... (does that make header
  410.  * parsing an "out of body experience" ?
  411.  */
  412. /* buffer up the data we just read */
  413. add_to_iob(csp, buf, n);
  414. /* get header lines from the iob */
  415. while((p = get_header(csp))) {
  416. if(*p == '') {
  417. /* see following note */
  418. break;
  419. }
  420. enlist(csp->headers, p);
  421. freez(p);
  422. }
  423. /* NOTE: there are no "empty" headers so
  424.  * if the pointer `p' is not NULL we must
  425.  * assume that we reached the end of the
  426.  * buffer before we hit the end of the header.
  427.  *
  428.  * Since we have to wait for more from the
  429.  * server before we can parse the headers
  430.  * we just continue here.
  431.  */
  432. if(p) continue;
  433. /* we have now received the entire header.
  434.  * filter it and send the result to the client
  435.  */
  436. hdr = sed(
  437. server_patterns,
  438. add_server_headers,
  439. csp);
  440. n   = strlen(hdr);
  441. /* write the server's (modified) header to
  442.  * the client (along with anything else that
  443.  * may be in the buffer)
  444.  */
  445. if((write_socket(csp->cfd, hdr, n) != n)
  446. || (flush_socket(csp->cfd, csp   ) <  0)) {
  447. if(DEBUG(CON)) {
  448. fprintf(logfp,
  449. "%s: write header to client failed: ",
  450. prog);
  451. fperror(logfp, "");
  452. }
  453. /* the write failed, so don't bother
  454.  * mentioning it to the client...
  455.  * it probably can't hear us anyway.
  456.  */
  457. freez(hdr);
  458. return;
  459. }
  460. /* we're finished with the server's header */
  461. freez(hdr);
  462. server_body = 1;
  463. }
  464. continue;
  465. }
  466. return; /* huh? we should never get here */
  467. }
  468. }
  469. void
  470. serve(struct client_state *csp)
  471. {
  472. chat(csp);
  473. close_socket(csp->cfd);
  474. if(csp->sfd >= 0) {
  475. close_socket(csp->sfd);
  476. }
  477. csp->active = 0;
  478. }
  479. #ifdef __BEOS__
  480. int32
  481. server_thread(void *data)
  482. {
  483. serve((struct client_state *) data);
  484. return 0;
  485. }
  486. #endif
  487. int
  488. main(int argc, char *argv[])
  489. {
  490. char buf[BUFSIZ];
  491. int cfd, bfd;
  492. char *p, *q;
  493. extern char *optarg;
  494. extern int optind;
  495. struct client_state *csp;
  496. char *default_configfile = NULL;
  497. char *configfile = NULL;
  498. FILE *configfp = NULL;
  499. int err = 0;
  500. prog = argv[0];
  501. logfp = stdout;
  502. init_proxy_args(argc, argv);
  503. cfd  = -1;
  504. #ifdef _WIN32
  505. default_configfile = "junkbstr.ini";
  506. #endif
  507. configfile = default_configfile;
  508. if(argc > 1) {
  509. configfile = argv[1];
  510. }
  511. if(configfile) {
  512. if((configfp = fopen(configfile, "r")) == NULL) {
  513. if(configfile != default_configfile) {
  514. fprintf(logfp,
  515. "%s: can't open configuration file '%s': ",
  516. prog, configfile);
  517. fperror(logfp, "");
  518. exit(1);
  519. }
  520. }
  521. }
  522. if(configfp) {
  523. int line_num = 0;
  524. while(fgets(buf, sizeof(buf), configfp)) {
  525. char cmd[BUFSIZ];
  526. char arg[BUFSIZ];
  527. char tmp[BUFSIZ];
  528. line_num++;
  529. strcpy(tmp, buf);
  530. if((p = strpbrk(tmp, "#rn"))) *p = '';
  531. p = tmp;
  532. /* leading skip whitespace */
  533. while(*p && ((*p == ' ') || (*p == 't'))) p++;
  534. q = cmd;
  535. while(*p && (*p != ' ') && (*p != 't')) *q++ = *p++;
  536. *q = '';
  537. while(*p && ((*p == ' ') || (*p == 't'))) p++;
  538. strcpy(arg, p);
  539. p = arg + strlen(arg) - 1;
  540. /* ignore trailing whitespace */
  541. while(*p && ((*p == ' ') || (*p == 't'))) *p-- = '';
  542. if(*cmd == '') continue;
  543. /* insure the command field is lower case */
  544. for(p=cmd; *p; p++) if(isupper(*p)) *p = tolower(*p);
  545. savearg(cmd, arg);
  546. if(strcmp(cmd, "trustfile") == 0) {
  547. trustfile = strdup(arg);
  548. continue;
  549. }
  550. if(strcmp(cmd, "trust_info_url") == 0) {
  551. enlist(trust_info, arg);
  552. continue;
  553. }
  554. if(strcmp(cmd, "debug") == 0) {
  555. debug |= atoi(arg);
  556. continue;
  557. }
  558. if(strcmp(cmd, "add-forwarded-header") == 0) {
  559. add_forwarded = 1;
  560. continue;
  561. }
  562. if(strcmp(cmd, "single-threaded") == 0) {
  563. multi_threaded = 0;
  564. continue;
  565. }
  566. if(strcmp(cmd, "suppress-vanilla-wafer") == 0) {
  567. suppress_vanilla_wafer = 1;
  568. continue;
  569. }
  570. if(strcmp(cmd, "wafer") == 0) {
  571. enlist(wafer_list, arg);
  572. continue;
  573. }
  574. if(strcmp(cmd, "add-header") == 0) {
  575. enlist(xtra_list,  arg);
  576. continue;
  577. }
  578. if(strcmp(cmd, "cookiefile") == 0) {
  579. cookiefile = strdup(arg);
  580. continue;
  581. }
  582. if(strcmp(cmd, "logfile") == 0) {
  583. logfile = strdup(arg);
  584. continue;
  585. }
  586. if(strcmp(cmd, "blockfile") == 0) {
  587. blockfile = strdup(arg);
  588. continue;
  589. }
  590. if(strcmp(cmd, "jarfile") == 0) {
  591. jarfile = strdup(arg);
  592. continue;
  593. }
  594. if(strcmp(cmd, "listen-address") == 0) {
  595. haddr = strdup(arg);
  596. continue;
  597. }
  598. if(strcmp(cmd, "forwardfile") == 0) {
  599. forwardfile = strdup(arg);
  600. continue;
  601. }
  602. if(strcmp(cmd, "aclfile") == 0) {
  603. aclfile = strdup(arg);
  604. continue;
  605. }
  606. if(strcmp(cmd, "user-agent") == 0) {
  607. uagent = strdup(arg);
  608. continue;
  609. }
  610. if((strcmp(cmd, "referrer") == 0)
  611. || (strcmp(cmd, "referer" ) == 0)) {
  612. referrer = strdup(arg);
  613. continue;
  614. }
  615. if(strcmp(cmd, "from") == 0) {
  616. from = strdup(arg);
  617. continue;
  618. }
  619. if(strcmp(cmd, "hide-console") == 0) {
  620. hideConsole = 1;
  621. continue;
  622. }
  623. fprintf(logfp,
  624. "%s: unrecognized directive "
  625. "in configuration file "
  626. "at line number %d:n%s",
  627. prog, line_num, buf);
  628. err = 1;
  629. }
  630. fclose(configfp);
  631. }
  632. if(err) exit(1);
  633. #ifdef _WIN32
  634. InitWin32();
  635. #endif
  636. if(logfile) {
  637. FILE *tlog = fopen(logfile, "a");
  638. if(tlog == NULL) {
  639. fprintf(logfp, "%s: can't open logfile '%s': ",
  640. prog, logfile);
  641. fperror(logfp, "");
  642. err = 1;
  643. }
  644. logfp = tlog;
  645. }
  646. setbuf(logfp, NULL);
  647. if(cookiefile)   add_loader(load_cookiefile);
  648. if(blockfile)    add_loader(load_blockfile);
  649. if(trustfile)    add_loader(load_trustfile);
  650. if(forwardfile)  add_loader(load_forwardfile);
  651. if(aclfile)      add_loader(load_aclfile);
  652. if(jarfile) {
  653. jar = fopen(jarfile, "a");
  654. if(jar == NULL) {
  655. fprintf(logfp, "%s: can't open jarfile '%s': ",
  656. prog, jarfile);
  657. fperror(logfp, "");
  658. err = 1;
  659. }
  660. setbuf(jar, NULL);
  661. }
  662. if(haddr) {
  663. if((p = strchr(haddr, ':'))) {
  664. *p++ = '';
  665. if(*p) hport = atoi(p);
  666. }
  667. if(hport <= 0) {
  668. *--p = ':' ;
  669. fprintf(logfp, "%s: invalid bind port spec %s",
  670. prog, haddr);
  671. err = 1;
  672. }
  673. if(*haddr == '') haddr = NULL;
  674. }
  675. if(run_loader(NULL)) err = 1;
  676. if(err) exit(1);
  677. /* if we're logging cookies in a cookie jar,
  678.  * and the user has not supplied any wafers,
  679.  * and the user has not told us to suppress the vanilla wafer,
  680.  * then send the vanilla wafer.
  681.  */
  682. if((jarfile != NULL)
  683. && (wafer_list->next == NULL)
  684. && (suppress_vanilla_wafer == 0)) {
  685. enlist(wafer_list, VANILLA_WAFER);
  686. }
  687. if(DEBUG(CON)) {
  688. fprintf(logfp, "%s: bind (%s, %d)n",
  689. prog, haddr ? haddr : "INADDR_ANY", hport);
  690. }
  691. bfd = bind_port(haddr, hport);
  692. if(bfd < 0) {
  693. fprintf(logfp, "%s: can't bind %s:%d: ",
  694. prog, haddr ? haddr : "INADDR_ANY", hport);
  695. fperror(logfp, "");
  696. fprintf(logfp,
  697. "There may be another junkbuster or some other "
  698. "proxy running on port %dn", hport);
  699. err = 1;
  700. }
  701. if(err) exit(1);
  702. end_proxy_args();
  703. #ifndef _WIN32
  704. signal(SIGPIPE, SIG_IGN);
  705. signal(SIGCHLD, SIG_IGN);
  706. #endif
  707. #ifdef _WIN32
  708. {
  709. /* print a verbose messages about FAQ's and such */
  710. extern char *win32_blurb;
  711. if(logfp == stdout) fprintf(logfp, win32_blurb);
  712. }
  713. #endif
  714. for(;;) {
  715. #if !defined(_WIN32) && !defined(__BEOS__)
  716. while(waitpid(-1, NULL, WNOHANG) > 0) {
  717. /* zombie children */
  718. }
  719. #endif
  720. sweep();
  721. if(DEBUG(CON)) {
  722. fprintf(logfp, "%s: accept connection ... ", prog);
  723. }
  724. cfd = accept_connection(bfd);
  725. if(cfd < 0) {
  726. if(DEBUG(CON)) {
  727. fprintf(logfp, "%s: accept failed: ", prog);
  728. fperror(logfp, "");
  729. }
  730. continue;
  731. } else {
  732. if(DEBUG(CON)) {
  733. fprintf(logfp, "OKn");
  734. }
  735. }
  736. csp = (struct client_state *) malloc(sizeof(*csp));
  737. if(csp == NULL) {
  738. fprintf(logfp, "%s: malloc(%d) for csp failed: ", prog, sizeof(*csp));
  739. fperror(logfp, "");
  740. close_socket(cfd);
  741. continue;
  742. }
  743. memset(csp, '', sizeof(*csp));
  744. csp->active = 1;
  745. csp->cfd    = cfd;
  746. csp->sfd    =  -1;
  747. csp->ip_addr_str  = remote_ip_str;
  748. csp->ip_addr_long = remote_ip_long;
  749. /* add it to the list of clients */
  750. csp->next = clients->next;
  751. clients->next = csp;
  752. if(run_loader(csp)) {
  753. fprintf(logfp, "%s: a loader failed - must exitn", prog);
  754. exit(1);
  755. }
  756. if(multi_threaded) {
  757. int child_id;
  758. /* this is a switch() statment in the C preprocessor - ugh */
  759. #undef SELECTED_ONE_OPTION
  760. #if defined(_WIN32) && !defined(SELECTED_ONE_OPTION)
  761. #define SELECTED_ONE_OPTION
  762. child_id = _beginthread(
  763. (void*)serve,
  764. 64 * 1024,
  765. csp);
  766. #endif
  767. #if defined(__BEOS__) && !defined(SELECTED_ONE_OPTION)
  768. #define SELECTED_ONE_OPTION
  769. {
  770. thread_id tid = spawn_thread
  771. (server_thread, "server", B_NORMAL_PRIORITY, csp);
  772. if ((tid >= 0) && (resume_thread(tid) == B_OK)) {
  773. child_id = (int) tid;
  774. } else {
  775. child_id = -1;
  776. }
  777. }
  778. #endif
  779. #if !defined(SELECTED_ONE_OPTION)
  780. child_id = fork();
  781. #endif
  782. #undef SELECTED_ONE_OPTION
  783. /* end of cpp switch() */
  784. if(child_id < 0) { /* failed */
  785. fprintf(logfp, "%s: can't fork: ", prog);
  786. fperror(logfp, "");
  787. sprintf(buf , "%s: can't fork: errno = %d",
  788. prog, errno);
  789. write_socket(csp->cfd, buf, strlen(buf));
  790. close_socket(csp->cfd);
  791. csp->active = 0;
  792. sleep(5);
  793. continue;
  794. }
  795. #if !defined(_WIN32) && !defined(__BEOS__)
  796. /* This block is only needed when using fork().
  797.  * When using threads, the server thread was
  798.  * created and run by the call to _beginthread().
  799.  */
  800. if(child_id == 0) { /* child */
  801. serve(csp);
  802. _exit(0);
  803. } else { /* parent */
  804. /* in a fork()'d environment, the parent's
  805.  * copy of the client socket and the CSP
  806.  * are not used.
  807.  */
  808. close_socket(csp->cfd);
  809. csp->active = 0;
  810. }
  811. #endif
  812. } else {
  813. serve(csp);
  814. }
  815. }
  816. /* NOTREACHED */
  817. }
  818. char *
  819. safe_strerror(int err)
  820. {
  821. char buf[BUFSIZ];
  822. char *s = NULL;
  823. #ifndef   NOSTRERROR
  824. s = strerror(err);
  825. #endif /* NOSTRERROR */
  826. if(s == NULL) {
  827. sprintf(buf, "(errno = %d)", err);
  828. s = buf;
  829. }
  830. return(strdup(s));
  831. }
  832. void
  833. fperror(FILE *fp, char *str)
  834. {
  835. char *eno = safe_strerror(errno);
  836. if(str && *str) {
  837. fprintf(fp, "%s: %sn", str, eno);
  838. } else {
  839. fprintf(fp, "%sn", eno);
  840. }
  841. freez(eno);
  842. }