home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Spezial / SPEZIAL2_97.zip / SPEZIAL2_97.iso / ANWEND / ONLINE / IJB20OS2 / SOURCE / JCC.C < prev    next >
C/C++ Source or Header  |  1997-09-16  |  20KB  |  1,005 lines

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