home *** CD-ROM | disk | FTP | other *** search
/ Freelog 24 / Freelog024.iso / Popup / Junkbuster / loaders.c < prev    next >
C/C++ Source or Header  |  1998-10-30  |  25KB  |  1,243 lines

  1. char *loaders_rcs = "$Id: loaders.c,v 1.24 1998/10/22 15:30:38 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.  
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <sys/types.h>
  10. #include <string.h>
  11. #include <malloc.h>
  12. #include <errno.h>
  13. #include <sys/stat.h>
  14. #include <ctype.h>
  15.  
  16. #ifndef _WIN32
  17. #include <unistd.h>
  18. #endif
  19.  
  20. #ifdef REGEX
  21. #include <gnu_regex.h>
  22. #endif
  23.  
  24. #include "jcc.h"
  25.  
  26.  
  27. /* sweep() is basically a mark and sweep garbage collector.
  28.  * it is run (by the parent thread) every once in a while to reclaim memory.
  29.  *
  30.  * it uses a mark and sweep strategy:
  31.  *   1) mark all files as inactive
  32.  *
  33.  *   2) check with each client:
  34.  *       if it is active,   mark its files as active
  35.  *       if it is inactive, free its resources
  36.  *
  37.  *   3) free the resources of all of the files that
  38.  *      are still marked as inactive (and are obsolete).
  39.  *
  40.  *   N.B. files that are not obsolete don't have an unloader defined.
  41.  */
  42.  
  43. void
  44. sweep()
  45. {
  46.     struct file_list *fl, *nfl;
  47.     struct client_state *csp, *ncsp;
  48.  
  49.     /* clear all of the file's active flags */
  50.     for(fl = files->next; fl ; fl = fl->next) {
  51.         fl->active = 0;
  52.     }
  53.  
  54.     for(csp = clients; csp && (ncsp = csp->next) ; csp = csp->next) {
  55.         if(ncsp->active) {
  56.             /* mark this client's files as active */
  57.             if(ncsp->alist) ncsp->alist->active = 1;
  58.             if(ncsp->blist) ncsp->blist->active = 1;
  59.             if(ncsp->clist) ncsp->clist->active = 1;
  60.             if(ncsp->tlist) ncsp->tlist->active = 1;
  61.         } else {
  62.             /* this client one is not active,
  63.              * release its resources
  64.              */
  65.             csp->next = ncsp->next;
  66.  
  67.             freez(ncsp->ip_addr_str);
  68.             freez(ncsp->referrer);
  69.             freez(ncsp->x_forwarded);
  70.             freez(ncsp->ip_addr_str);
  71.             freez(ncsp->iob->buf);
  72.  
  73.             free_http_request(ncsp->http);
  74.  
  75.             destroy_list(ncsp->headers);
  76.             destroy_list(ncsp->cookie_list);
  77.  
  78.             freez(ncsp);
  79.         }
  80.     }
  81.  
  82.     for(fl = files; fl && (nfl = fl->next) ; fl = fl->next) {
  83.         if(nfl->active == 0) {
  84.             if(nfl->unloader) {
  85.                 fl->next = nfl->next;
  86.  
  87.                 (nfl->unloader)(nfl->f);
  88.  
  89.                 freez(nfl->proxy_args);
  90.  
  91.                 freez(nfl);
  92.             }
  93.         }
  94.     }
  95. }
  96.  
  97. void
  98. unload_url(struct url_spec *url)
  99. {
  100.     if(url == NULL) return;
  101.  
  102.     freez(url->spec);
  103.     freez(url->domain);
  104.     freez(url->dbuf);
  105.     freez(url->dvec);
  106.     freez(url->path);
  107. #ifdef REGEX
  108.     if(url->preg) {
  109.         regfree(url->preg);
  110.         freez(url->preg);
  111.     }
  112. #endif
  113. }
  114.  
  115. void
  116. unload_blockfile(struct block_spec *b)
  117. {
  118.     if(b == NULL) return;
  119.  
  120.     unload_blockfile(b->next);
  121.  
  122.     unload_url(b->url);
  123.  
  124.     freez(b);
  125. }
  126.  
  127. void
  128. unload_cookiefile(struct cookie_spec *b)
  129. {
  130.     if(b == NULL) return;
  131.  
  132.     unload_cookiefile(b->next);
  133.  
  134.     unload_url(b->url);
  135.  
  136.     freez(b);
  137. }
  138.  
  139. void
  140. unload_trustfile(struct block_spec *b)
  141. {
  142.     if(b == NULL) return;
  143.  
  144.     unload_trustfile(b->next);
  145.  
  146.     unload_url(b->url);
  147.  
  148.     freez(b);
  149. }
  150.  
  151. void
  152. unload_forwardfile(struct forward_spec *b)
  153. {
  154.     if(b == NULL) return;
  155.  
  156.     unload_forwardfile(b->next);
  157.  
  158.     unload_url(b->url);
  159.  
  160.     freez(b->gw->gateway_host);
  161.     freez(b->gw->forward_host);
  162.  
  163.     freez(b);
  164. }
  165.  
  166. static struct file_list *current_blockfile;
  167. static struct file_list *current_cookiefile;
  168. static struct file_list *current_trustfile;
  169. static struct file_list *current_forwardfile;
  170.  
  171. int
  172. load_blockfile(struct client_state *csp)
  173. {
  174.     FILE *fp;
  175.  
  176.     struct block_spec *b, *bl;
  177.     char  buf[BUFSIZ], *p, *q;
  178.     int port, reject;
  179.     struct file_list *fs;
  180.     static struct stat prev[1], curr[1];
  181.     struct url_spec url[1];
  182.  
  183.     if(stat(blockfile, curr) < 0) {
  184.         goto load_blockfile_error;
  185.     }
  186.  
  187.     if(current_blockfile && (prev->st_mtime == curr->st_mtime)) {
  188.         csp->blist = current_blockfile;
  189.         return(0);
  190.     }
  191.  
  192.     fs = (struct file_list  *) zalloc(sizeof(*fs));
  193.     bl = (struct block_spec *) zalloc(sizeof(*bl));
  194.  
  195.     if((fs == NULL) || (bl == NULL)) {
  196.         goto load_blockfile_error;
  197.     }
  198.  
  199.     fs->f = bl;
  200.  
  201.     fs->next    = files->next;
  202.     files->next = fs;
  203.  
  204.     if(csp) {
  205.         csp->blist = fs;
  206.     }
  207.  
  208.     *prev = *curr;
  209.  
  210.     if((fp = fopen(blockfile, "r")) == NULL) {
  211.         goto load_blockfile_error;
  212.     }
  213.     
  214.     p = url_encode(html_code_map, blockfile);
  215.  
  216.     sprintf(buf, "<h2>The file `%s' contains the following patterns</h2>\n", p);
  217.     freez(p);
  218.  
  219.     fs->proxy_args = strsav(fs->proxy_args, buf);
  220.  
  221.     fs->proxy_args = strsav(fs->proxy_args, "<pre>");
  222.  
  223.     while(fgets(buf, sizeof(buf), fp)) {
  224.  
  225.         if((p = url_encode(html_code_map, buf))) {
  226.             fs->proxy_args = strsav(fs->proxy_args, p);
  227.         }
  228.         freez(p);
  229.         fs->proxy_args = strsav(fs->proxy_args, "<br>");
  230.  
  231.         if((p = strpbrk(buf, "\r\n")) != NULL) {
  232.             *p = '\0';
  233.         }
  234.  
  235.         /* comments */
  236.         if((p = strchr(buf, '#'))) *p = '\0';
  237.  
  238.         /* elide white-space */
  239.         for(p = q = buf; *q ; q++) {
  240.             if(!isspace(*q)) *p++ = *q;
  241.         }
  242.  
  243.         *p = '\0';
  244.  
  245.         reject = 1;
  246.  
  247.         if(*buf == '~') {
  248.             reject = 0;
  249.             p = buf;
  250.             q = p+1;
  251.             while ((*p++ = *q++)) {
  252.                 /* nop */
  253.             }
  254.         }
  255.  
  256.         /* skip blank lines */
  257.         if(*buf == '\0') continue;
  258.  
  259.         /* allocate a new node */
  260.         if(((b            = zalloc(sizeof(*b)))            == NULL)
  261. #ifdef REGEX
  262.         || ((b->url->preg = zalloc(sizeof(*b->url->preg))) == NULL)
  263. #endif
  264.         ) {
  265.             fclose(fp);
  266.             goto load_blockfile_error;
  267.         }
  268.  
  269.         /* add it to the list */
  270.         b->next  = bl->next;
  271.         bl->next = b;
  272.  
  273.         /* save a copy of the orignal specification */
  274.         if((b->url->spec = strdup(buf)) == NULL) {
  275.             fclose(fp);
  276.             goto load_blockfile_error;
  277.         }
  278.  
  279.         b->reject = reject;
  280.  
  281.         if((p = strchr(buf, '/'))) {
  282.             b->url->path    = strdup(p);
  283.             b->url->pathlen = strlen(b->url->path);
  284.             *p = '\0';
  285.         } else {
  286.             b->url->path    = NULL;
  287.             b->url->pathlen = 0;
  288.         }
  289. #ifdef REGEX
  290.         if(b->url->path) {
  291.             int errcode;
  292.             char rebuf[BUFSIZ];
  293.  
  294.             sprintf(rebuf, "^(%s)", b->url->path);
  295.  
  296.             errcode = regcomp(b->url->preg, rebuf,
  297.                     (REG_EXTENDED|REG_NOSUB|REG_ICASE));
  298.  
  299.             if(errcode) {
  300.                 size_t errlen =
  301.                     regerror(errcode,
  302.                         b->url->preg, buf, sizeof(buf));
  303.  
  304.                 buf[errlen] = '\0';
  305.  
  306.                 fprintf(logfp,
  307.                     "%s: error compiling %s: %s\n",
  308.                         prog, b->url->spec, buf);
  309.                 fclose(fp);
  310.                 goto load_blockfile_error;
  311.             }
  312.         } else {
  313.             freez(b->url->preg);
  314.         }
  315. #endif
  316.         if((p = strchr(buf, ':')) == NULL) {
  317.             port = 0;
  318.         } else {
  319.             *p++ = '\0';
  320.             port = atoi(p);
  321.         }
  322.  
  323.         b->url->port = port;
  324.  
  325.         if((b->url->domain = strdup(buf)) == NULL) {
  326.             fclose(fp);
  327.             goto load_blockfile_error;
  328.         }
  329.  
  330.         /* split domain into components */
  331.         *url = dsplit(b->url->domain);
  332.         b->url->dbuf = url->dbuf;
  333.         b->url->dcnt = url->dcnt;
  334.         b->url->dvec = url->dvec;
  335.     }
  336.     fs->proxy_args = strsav(fs->proxy_args, "</pre>");
  337.  
  338.     fclose(fp);
  339.  
  340.     /* the old one is now obsolete */
  341.     if(current_blockfile) {
  342.         current_blockfile->unloader = unload_blockfile;
  343.     }
  344.  
  345.     current_blockfile = fs;
  346.  
  347.     return(0);
  348.  
  349. load_blockfile_error:
  350.     fprintf(logfp, "%s: can't load blockfile '%s': ",
  351.         prog, blockfile);
  352.     fperror(logfp, "");
  353.     return(-1);
  354. }
  355.  
  356. int
  357. load_cookiefile(struct client_state *csp)
  358. {
  359.     FILE *fp;
  360.  
  361.     struct cookie_spec *b, *bl;
  362.     char  buf[BUFSIZ], *p, *q;
  363.     char *tmp_vec[BUFSIZ];
  364.     int port, user_cookie, server_cookie;
  365.     static struct stat prev[1], curr[1];
  366.     static struct file_list *fs;
  367.     struct url_spec url[1];
  368.  
  369.     if(stat(cookiefile, curr) < 0) {
  370.         goto load_cookie_error;
  371.     }
  372.  
  373.     if(current_cookiefile && (prev->st_mtime == curr->st_mtime)) {
  374.         csp->clist = current_cookiefile;
  375.         return(0);
  376.     }
  377.  
  378.     fs = (struct file_list   *) zalloc(sizeof(*fs));
  379.         bl = (struct cookie_spec *) zalloc(sizeof(*bl));
  380.  
  381.     if((fs == NULL) || (bl == NULL)) {
  382.         goto load_cookie_error;
  383.     }
  384.  
  385.     fs->f = bl;
  386.  
  387.     fs->next    = files->next;
  388.     files->next = fs;
  389.  
  390.     if(csp) {
  391.         csp->clist = fs;
  392.     }
  393.  
  394.     *prev = *curr;
  395.     
  396.     if((fp = fopen(cookiefile, "r")) == NULL) {
  397.         goto load_cookie_error;
  398.     }
  399.  
  400.     p = url_encode(html_code_map, cookiefile);
  401.  
  402.     sprintf(buf, "<h2>The file `%s' contains the following patterns</h2>\n", p);
  403.  
  404.     freez(p);
  405.  
  406.     fs->proxy_args = strsav(fs->proxy_args, buf);
  407.  
  408.     fs->proxy_args = strsav(fs->proxy_args, "<pre>");
  409.  
  410.     while(fgets(buf, sizeof(buf), fp)) {
  411.  
  412.         if((p = url_encode(html_code_map, buf))) {
  413.             fs->proxy_args = strsav(fs->proxy_args, p);
  414.         }
  415.         freez(p);
  416.         fs->proxy_args = strsav(fs->proxy_args, "<br>");
  417.  
  418.         if((p = strpbrk(buf, "\r\n")) != NULL) {
  419.             *p = '\0';
  420.         }
  421.  
  422.         /* comments */
  423.         if((p = strchr(buf, '#'))) *p = '\0';
  424.  
  425.         /* elide white-space */
  426.         for(p = q = buf; *q ; q++) {
  427.             if(!isspace(*q)) *p++ = *q;
  428.         }
  429.  
  430.         *p = '\0';
  431.  
  432.         p = buf;
  433.  
  434.         switch((int)*p) {
  435.         case '>':
  436.             server_cookie = 0;
  437.             user_cookie   = 1;
  438.             p++;
  439.             break;
  440.         case '<':
  441.             server_cookie = 1;
  442.             user_cookie   = 0;
  443.             p++;
  444.             break;
  445.         case '~':
  446.             server_cookie = 0;
  447.             user_cookie   = 0;
  448.             p++;
  449.             break;
  450.         default:
  451.             server_cookie = 1;
  452.             user_cookie   = 1;
  453.             break;
  454.         }
  455.  
  456.         /* elide any of the "special" chars from the
  457.          * front of the pattern
  458.          */
  459.         q = buf;
  460.         if(p > q) while ((*q++ = *p++)) {
  461.             /* nop */
  462.         }
  463.  
  464.         /* skip blank lines */
  465.         if(*buf == '\0') continue;
  466.  
  467.         /* allocate a new node */
  468.         if(((b            = zalloc(sizeof(*b)))            == NULL)
  469. #ifdef REGEX
  470.         || ((b->url->preg = zalloc(sizeof(*b->url->preg))) == NULL)
  471. #endif
  472.         ) {
  473.             fclose(fp);
  474.             goto load_cookie_error;
  475.         }
  476.  
  477.         /* add it to the list */
  478.         b->next  = bl->next;
  479.         bl->next = b;
  480.  
  481.         /* save a copy of the orignal specification */
  482.         if((b->url->spec = strdup(buf)) == NULL) {
  483.             fclose(fp);
  484.             goto load_cookie_error;
  485.         }
  486.  
  487.         b->send_user_cookie     = user_cookie;
  488.         b->accept_server_cookie = server_cookie;
  489.  
  490.         if((p = strchr(buf, '/'))) {
  491.             b->url->path    = strdup(p);
  492.             b->url->pathlen = strlen(b->url->path);
  493.             *p = '\0';
  494.         } else {
  495.             b->url->path    = NULL;
  496.             b->url->pathlen = 0;
  497.         }
  498. #ifdef REGEX
  499.         if(b->url->path) {
  500.             int errcode;
  501.             char rebuf[BUFSIZ];
  502.  
  503.             sprintf(rebuf, "^(%s)", b->url->path);
  504.  
  505.             errcode = regcomp(b->url->preg, rebuf,
  506.                     (REG_EXTENDED|REG_NOSUB|REG_ICASE));
  507.             if(errcode) {
  508.                 size_t errlen =
  509.                     regerror(errcode,
  510.                         b->url->preg, buf, sizeof(buf));
  511.  
  512.                 buf[errlen] = '\0';
  513.  
  514.                 fprintf(logfp,
  515.                     "%s: error compiling %s: %s\n",
  516.                         prog, b->url->spec, buf);
  517.                 fclose(fp);
  518.                 goto load_cookie_error;
  519.             }
  520.         } else {
  521.             freez(b->url->preg);
  522.         }
  523. #endif
  524.         if((p = strchr(buf, ':')) == NULL) {
  525.             port = 0;
  526.         } else {
  527.             *p++ = '\0';
  528.             port = atoi(p);
  529.         }
  530.  
  531.         b->url->port = port;
  532.  
  533.         if((b->url->domain = strdup(buf)) == NULL) {
  534.             fclose(fp);
  535.             goto load_cookie_error;
  536.         }
  537.  
  538.         /* split domain into components */
  539.         *url = dsplit(b->url->domain, tmp_vec);
  540.         b->url->dbuf = url->dbuf;
  541.         b->url->dcnt = url->dcnt;
  542.         b->url->dvec = url->dvec;
  543.     }
  544.  
  545.     fs->proxy_args = strsav(fs->proxy_args, "</pre>");
  546.  
  547.     fclose(fp);
  548.  
  549.     /* the old one is now obsolete */
  550.     if(current_cookiefile) {
  551.         current_cookiefile->unloader = unload_cookiefile;
  552.     }
  553.  
  554.     current_cookiefile = fs;
  555.  
  556.     return(0);
  557.  
  558. load_cookie_error:
  559.     fprintf(logfp, "%s: can't load cookiefile '%s': ",
  560.         prog, cookiefile);
  561.     fperror(logfp, "");
  562.     return(-1);
  563. }
  564.  
  565. int
  566. load_trustfile(struct client_state *csp)
  567. {
  568.     FILE *fp;
  569.  
  570.     struct block_spec *b, *bl;
  571.     struct url_spec **tl;
  572.  
  573.     char  buf[BUFSIZ], *p, *q;
  574.     int port, reject, trusted;
  575.     struct file_list *fs;
  576.     static struct stat prev[1], curr[1];
  577.     struct url_spec url[1];
  578.  
  579.     if(stat(trustfile, curr) < 0) {
  580.         goto load_trustfile_error;
  581.     }
  582.  
  583.     if(current_trustfile && (prev->st_mtime == curr->st_mtime)) {
  584.         csp->tlist = current_trustfile;
  585.         return(0);
  586.     }
  587.  
  588.     fs = (struct file_list  *) zalloc(sizeof(*fs));
  589.     bl = (struct block_spec *) zalloc(sizeof(*bl));
  590.  
  591.     if((fs == NULL) || (bl == NULL)) {
  592.         goto load_trustfile_error;
  593.     }
  594.  
  595.     fs->f = bl;
  596.  
  597.     fs->next    = files->next;
  598.     files->next = fs;
  599.  
  600.     if(csp) {
  601.         csp->tlist = fs;
  602.     }
  603.  
  604.     *prev = *curr;
  605.  
  606.     if((fp = fopen(trustfile, "r")) == NULL) {
  607.         goto load_trustfile_error;
  608.     }
  609.     
  610.     p = url_encode(html_code_map, trustfile);
  611.  
  612.     sprintf(buf, "<h2>The file `%s' contains the following patterns</h2>\n", p);
  613.  
  614.     freez(p);
  615.  
  616.     fs->proxy_args = strsav(fs->proxy_args, buf);
  617.  
  618.     fs->proxy_args = strsav(fs->proxy_args, "<pre>");
  619.  
  620.     tl = trust_list;
  621.  
  622.     while(fgets(buf, sizeof(buf), fp)) {
  623.  
  624.         if((p = url_encode(html_code_map, buf))) {
  625.             fs->proxy_args = strsav(fs->proxy_args, p);
  626.         }
  627.         freez(p);
  628.         fs->proxy_args = strsav(fs->proxy_args, "<br>");
  629.  
  630.         if((p = strpbrk(buf, "\r\n")) != NULL) {
  631.             *p = '\0';
  632.         }
  633.  
  634.         /* comments */
  635.         if((p = strchr(buf, '#'))) *p = '\0';
  636.  
  637.         /* elide white-space */
  638.         for(p = q = buf; *q ; q++) {
  639.             if(!isspace(*q)) *p++ = *q;
  640.         }
  641.  
  642.         *p = '\0';
  643.  
  644.         trusted = 0;
  645.         reject  = 1;
  646.  
  647.         if(*buf == '+') {
  648.             trusted = 1;
  649.             *buf = '~';
  650.         }
  651.  
  652.         if(*buf == '~') {
  653.             reject = 0;
  654.             p = buf;
  655.             q = p+1;
  656.             while ((*p++ = *q++)) {
  657.                 /* nop */
  658.             }
  659.         }
  660.  
  661.         /* skip blank lines */
  662.         if(*buf == '\0') continue;
  663.  
  664.         /* allocate a new node */
  665.         if(((b            = zalloc(sizeof(*b)))            == NULL)
  666. #ifdef REGEX
  667.         || ((b->url->preg = zalloc(sizeof(*b->url->preg))) == NULL)
  668. #endif
  669.         ) {
  670.             fclose(fp);
  671.             goto load_trustfile_error;
  672.         }
  673.  
  674.         /* add it to the list */
  675.         b->next  = bl->next;
  676.         bl->next = b;
  677.  
  678.         /* save a copy of the orignal specification */
  679.         if((b->url->spec = strdup(buf)) == NULL) {
  680.             fclose(fp);
  681.             goto load_trustfile_error;
  682.         }
  683.  
  684.         b->reject = reject;
  685.  
  686.         if((p = strchr(buf, '/'))) {
  687.             b->url->path    = strdup(p);
  688.             b->url->pathlen = strlen(b->url->path);
  689.             *p = '\0';
  690.         } else {
  691.             b->url->path    = NULL;
  692.             b->url->pathlen = 0;
  693.         }
  694. #ifdef REGEX
  695.         if(b->url->path) {
  696.             int errcode;
  697.             char rebuf[BUFSIZ];
  698.  
  699.             sprintf(rebuf, "^(%s)", b->url->path);
  700.  
  701.             errcode = regcomp(b->url->preg, rebuf,
  702.                     (REG_EXTENDED|REG_NOSUB|REG_ICASE));
  703.  
  704.             if(errcode) {
  705.                 size_t errlen =
  706.                     regerror(errcode,
  707.                         b->url->preg, buf, sizeof(buf));
  708.  
  709.                 buf[errlen] = '\0';
  710.  
  711.                 fprintf(logfp,
  712.                     "%s: error compiling %s: %s\n",
  713.                         prog, b->url->spec, buf);
  714.                 fclose(fp);
  715.                 goto load_trustfile_error;
  716.             }
  717.         } else {
  718.             freez(b->url->preg);
  719.         }
  720. #endif
  721.         if((p = strchr(buf, ':')) == NULL) {
  722.             port = 0;
  723.         } else {
  724.             *p++ = '\0';
  725.             port = atoi(p);
  726.         }
  727.  
  728.         b->url->port = port;
  729.  
  730.         if((b->url->domain = strdup(buf)) == NULL) {
  731.             fclose(fp);
  732.             goto load_trustfile_error;
  733.         }
  734.  
  735.         /* split domain into components */
  736.         *url = dsplit(b->url->domain);
  737.         b->url->dbuf = url->dbuf;
  738.         b->url->dcnt = url->dcnt;
  739.         b->url->dvec = url->dvec;
  740.  
  741.         /* save a pointer to URL's spec
  742.          * in the list of trusted URL's, too
  743.          */
  744.         if(trusted) *tl++ = b->url;
  745.     }
  746.  
  747.     fs->proxy_args = strsav(fs->proxy_args, "</pre>");
  748.  
  749.     *tl = NULL;
  750.  
  751.     fclose(fp);
  752.  
  753.     /* the old one is now obsolete */
  754.     if(current_trustfile) {
  755.         current_trustfile->unloader = unload_trustfile;
  756.     }
  757.  
  758.     current_trustfile = fs;
  759.  
  760.     return(0);
  761.  
  762. load_trustfile_error:
  763.     fprintf(logfp, "%s: can't load trustfile '%s': ",
  764.         prog, trustfile);
  765.     fperror(logfp, "");
  766.     return(-1);
  767. }
  768.  
  769. int
  770. load_forwardfile(struct client_state *csp)
  771. {
  772.     FILE *fp;
  773.  
  774.     struct forward_spec *b, *bl;
  775.     char  buf[BUFSIZ], *p, *q, *tmp;
  776.     char  *vec[4];
  777.     int port, n, reject;
  778.     struct file_list *fs;
  779.     struct gateway *gw;
  780.     static struct stat prev[1], curr[1];
  781.     struct url_spec url[1];
  782.  
  783.     if(stat(forwardfile, curr) < 0) {
  784.         goto load_forwardfile_error;
  785.     }
  786.  
  787.     if(current_forwardfile && (prev->st_mtime == curr->st_mtime)) {
  788.         csp->flist = current_forwardfile;
  789.         return(0);
  790.     }
  791.  
  792.     fs = (struct file_list    *) zalloc(sizeof(*fs));
  793.     bl = (struct forward_spec *) zalloc(sizeof(*bl));
  794.  
  795.     if((fs == NULL) || (bl == NULL)) {
  796.         goto load_forwardfile_error;
  797.     }
  798.  
  799.     memset(fs, '\0', sizeof(*fs));
  800.     memset(bl, '\0', sizeof(*bl));
  801.  
  802.     fs->f = bl;
  803.  
  804.     fs->next    = files->next;
  805.     files->next = fs;
  806.  
  807.     if(csp) {
  808.         csp->flist = fs;
  809.     }
  810.  
  811.     *prev = *curr;
  812.  
  813.     if((fp = fopen(forwardfile, "r")) == NULL) {
  814.         goto load_forwardfile_error;
  815.     }
  816.     
  817.     p = url_encode(html_code_map, forwardfile);
  818.  
  819.     sprintf(buf, "<h2>The file `%s' contains the following patterns</h2>\n", p);
  820.  
  821.     freez(p);
  822.  
  823.     fs->proxy_args = strsav(fs->proxy_args, buf);
  824.  
  825.     tmp = NULL;
  826.  
  827.     fs->proxy_args = strsav(fs->proxy_args, "<pre>");
  828.  
  829.     while(fgets(buf, sizeof(buf), fp)) {
  830.  
  831.         freez(tmp);
  832.  
  833.         if((p = url_encode(html_code_map, buf))) {
  834.             fs->proxy_args = strsav(fs->proxy_args, p);
  835.         }
  836.         freez(p);
  837.         fs->proxy_args = strsav(fs->proxy_args, "<br>");
  838.  
  839.         if((p = strpbrk(buf, "\r\n")) != NULL) {
  840.             *p = '\0';
  841.         }
  842.  
  843.         /* comments */
  844.         if((p = strchr(buf, '#'))) *p = '\0';
  845.  
  846.         /* skip blank lines */
  847.         if(*buf == '\0') continue;
  848.  
  849.         tmp = strdup(buf);
  850.  
  851.         n = ssplit(tmp, " \t", vec, SZ(vec), 1, 1);
  852.  
  853.         if(n != 4) {
  854.             fprintf(stderr, "error in forwardfile: %s\n", buf);
  855.             continue;
  856.         }
  857.  
  858.         strcpy(buf, vec[0]);
  859.  
  860.         reject = 1;
  861.  
  862.         if(*buf == '~') {
  863.             reject = 0;
  864.             p = buf;
  865.             q = p+1;
  866.             while ((*p++ = *q++)) {
  867.                 /* nop */
  868.             }
  869.         }
  870.  
  871.         /* skip blank lines */
  872.         if(*buf == '\0') continue;
  873.  
  874.         /* allocate a new node */
  875.         if(((b            = zalloc(sizeof(*b)))            == NULL)
  876. #ifdef REGEX
  877.         || ((b->url->preg = zalloc(sizeof(*b->url->preg))) == NULL)
  878. #endif
  879.         ) {
  880.             fclose(fp);
  881.             goto load_forwardfile_error;
  882.         }
  883.  
  884.         /* add it to the list */
  885.         b->next  = bl->next;
  886.         bl->next = b;
  887.  
  888.         /* save a copy of the orignal specification */
  889.         if((b->url->spec = strdup(buf)) == NULL) {
  890.             fclose(fp);
  891.             goto load_forwardfile_error;
  892.         }
  893.  
  894.         b->reject = reject;
  895.  
  896.         if((p = strchr(buf, '/'))) {
  897.             b->url->path    = strdup(p);
  898.             b->url->pathlen = strlen(b->url->path);
  899.             *p = '\0';
  900.         } else {
  901.             b->url->path    = NULL;
  902.             b->url->pathlen = 0;
  903.         }
  904. #ifdef REGEX
  905.         if(b->url->path) {
  906.             int errcode;
  907.             char rebuf[BUFSIZ];
  908.  
  909.             sprintf(rebuf, "^(%s)", b->url->path);
  910.  
  911.             errcode = regcomp(b->url->preg, rebuf,
  912.                     (REG_EXTENDED|REG_NOSUB|REG_ICASE));
  913.  
  914.             if(errcode) {
  915.                 size_t errlen =
  916.                     regerror(errcode,
  917.                         b->url->preg, buf, sizeof(buf));
  918.  
  919.                 buf[errlen] = '\0';
  920.  
  921.                 fprintf(logfp,
  922.                     "%s: error compiling %s: %s\n",
  923.                         prog, b->url->spec, buf);
  924.                 fclose(fp);
  925.                 goto load_forwardfile_error;
  926.             }
  927.         } else {
  928.             freez(b->url->preg);
  929.         }
  930. #endif
  931.         if((p = strchr(buf, ':')) == NULL) {
  932.             port = 0;
  933.         } else {
  934.             *p++ = '\0';
  935.             port = atoi(p);
  936.         }
  937.  
  938.         b->url->port = port;
  939.  
  940.         if((b->url->domain = strdup(buf)) == NULL) {
  941.             fclose(fp);
  942.             goto load_forwardfile_error;
  943.         }
  944.  
  945.         /* split domain into components */
  946.         *url = dsplit(b->url->domain);
  947.         b->url->dbuf = url->dbuf;
  948.         b->url->dcnt = url->dcnt;
  949.         b->url->dvec = url->dvec;
  950.  
  951.         /* now parse the gateway specs */
  952.  
  953.         p = vec[2];
  954.  
  955.         for(gw = gateways; gw->name; gw++) {
  956.             if(strcmp(gw->name, p) == 0) {
  957.                 break;
  958.             }
  959.         }
  960.  
  961.         if(gw->name == NULL) {
  962.             goto load_forwardfile_error;
  963.         }
  964.  
  965.         /* save this as the gateway type */
  966.         *b->gw = *gw;
  967.  
  968.         /* now parse the gateway host[:port] spec */
  969.         p = vec[3];
  970.  
  971.         if(strcmp(p, ".") != 0) {
  972.             b->gw->gateway_host = strdup(p);
  973.  
  974.             if((p = strchr(b->gw->gateway_host, ':'))) {
  975.                 *p++ = '\0';
  976.                 b->gw->gateway_port = atoi(p);
  977.             }
  978.  
  979.             if(b->gw->gateway_port <= 0) {
  980.                 goto load_forwardfile_error;
  981.             }
  982.         }
  983.  
  984.         /* now parse the forwarding spec */
  985.         p = vec[1];
  986.  
  987.         if(strcmp(p, ".") != 0) {
  988.             b->gw->forward_host = strdup(p);
  989.  
  990.             if((p = strchr(b->gw->forward_host, ':'))) {
  991.                 *p++ = '\0';
  992.                 b->gw->forward_port = atoi(p);
  993.             }
  994.  
  995.             if(b->gw->forward_port <= 0) {
  996.                 b->gw->forward_port = 8000;
  997.             }
  998.         }
  999.     }
  1000.  
  1001.     fs->proxy_args = strsav(fs->proxy_args, "</pre>");
  1002.  
  1003.     freez(tmp);
  1004.  
  1005.     fclose(fp);
  1006.  
  1007.     /* the old one is now obsolete */
  1008.     if(current_forwardfile) {
  1009.         current_forwardfile->unloader = unload_forwardfile;
  1010.     }
  1011.  
  1012.     current_forwardfile = fs;
  1013.  
  1014.     return(0);
  1015.  
  1016. load_forwardfile_error:
  1017.     fprintf(logfp, "%s: can't load forwardfile '%s': ",
  1018.         prog, forwardfile);
  1019.     fperror(logfp, "");
  1020.     return(-1);
  1021. }
  1022.  
  1023. #define JUNKBUSTERS "http://www.junkbusters.com"
  1024. #define OPT "href=\"" JUNKBUSTERS "/ht/en/ijb" VERSION_MAJOR "man.html#"
  1025.  
  1026. /* strsav() takes a pointer to a string stored in a dynamically allocated
  1027.  * buffer and a pointer to a string and returns a pointer to a new dynamically
  1028.  * allocated space that contains the concatenation of the two input strings
  1029.  * the previous space is free()'d by realloc().
  1030.  */
  1031. char *
  1032. strsav(char *old, char *text_to_append)
  1033. {
  1034.     int old_len, new_len;
  1035.     char *p;
  1036.  
  1037.     if(( text_to_append == NULL)
  1038.     || (*text_to_append == '\0')) {
  1039.         return(old);
  1040.     }
  1041.  
  1042.     if(old) {
  1043.         old_len = strlen(old);
  1044.     } else {
  1045.         old_len = 0;
  1046.     }
  1047.  
  1048.     new_len = old_len + strlen(text_to_append) + 1;
  1049.  
  1050.     if(old) {
  1051.         if((p = realloc(old, new_len)) == NULL) {
  1052.             fprintf(logfp, "%s: realloc(%d) bytes for proxy_args failed!\n", prog, new_len);
  1053.             exit(1);
  1054.         }
  1055.     } else {
  1056.         if((p = malloc(new_len)) == NULL) {
  1057.             fprintf(logfp, "%s: malloc(%d) bytes for proxy_args failed!\n", prog, new_len);
  1058.             exit(1);
  1059.         }
  1060.     }
  1061.  
  1062.     strcpy(p + old_len, text_to_append);
  1063.     return(p);
  1064. }
  1065.  
  1066. void
  1067. savearg(char *c, char *o)
  1068. {
  1069.     char buf[BUFSIZ];
  1070.     static int one_shot = 1;
  1071.  
  1072.     if(one_shot) {
  1073.         one_shot = 0;
  1074.         proxy_args->invocation = strsav(proxy_args->invocation,
  1075.             "<br>\n"
  1076.             "and the following options were set "
  1077.             "in the configuration file"
  1078.             "<br><br>\n"
  1079.         );
  1080.     }
  1081.  
  1082.     *buf = '\0';
  1083.  
  1084.     if(c && *c) {
  1085.         if((c = url_encode(html_code_map, c))) {
  1086.             sprintf(buf, "<a " OPT "%s\">%s</a> ", c, c);
  1087.         }
  1088.         freez(c);
  1089.     }
  1090.     if(o && *o) { 
  1091.         if((o = url_encode(html_code_map, o))) {
  1092.             if(strncmpic(o, "http://", 7) == 0) {
  1093.                 strcat(buf, "<a href=\"");
  1094.                 strcat(buf, o);
  1095.                 strcat(buf, "\">");
  1096.                 strcat(buf, o);
  1097.                 strcat(buf, "</a>");
  1098.             } else {
  1099.                 strcat(buf, o);
  1100.             }
  1101.         }
  1102.         freez(o);
  1103.     }
  1104.  
  1105.     strcat(buf, "<br>\n");
  1106.  
  1107.     proxy_args->invocation = strsav(proxy_args->invocation, buf);
  1108. }
  1109.  
  1110.  
  1111. void
  1112. init_proxy_args(int argc, char *argv[])
  1113. {
  1114.     struct gateway *g;
  1115.     int i;
  1116.  
  1117.     proxy_args->header = strsav(proxy_args->header,
  1118.         "HTTP/1.0 200 OK\n"
  1119.         "Server: IJ/" VERSION "\n"
  1120.         "Content-type: text/html\n\n"
  1121.  
  1122.         "<html>"
  1123.         "<head>"
  1124.         "<title>Internet Junkbuster Proxy Status</title>"
  1125.         "</head>\n"
  1126.         "<body bgcolor=\"#f8f8f0\" link=\"#000078\" alink=\"#ff0022\" vlink=\"#787878\">\n"
  1127.         "<center>\n"
  1128.         "<h1>" BANNER "\n"
  1129.         "<a href=\"" JUNKBUSTERS "/ht/en/ijb" VERSION_MAJOR "faq.html#show\">Proxy Status</a>\n"
  1130.         "</h1></center>\n"
  1131.         "<h2>You are using the " BANNER " <sup><small><small>TM</small></small></sup></h2>\n"
  1132.         "Version: IJ/" VERSION "\n"
  1133.         "<p>\n"
  1134.     );
  1135.  
  1136.     proxy_args->header = strsav(proxy_args->header,
  1137.         "<h2>The program was invoked as follows</h2>\n");
  1138.  
  1139.     for(i=0; i < argc; i++) {
  1140.         proxy_args->header = strsav(proxy_args->header, argv[i]);
  1141.         proxy_args->header = strsav(proxy_args->header, " ");
  1142.     }
  1143.     proxy_args->header = strsav(proxy_args->header, "<br>\n");
  1144.  
  1145.     proxy_args->gateways = strsav(proxy_args->gateways,
  1146.         "<h2>It supports the following gateway protocols:</h2>\n");
  1147.  
  1148.     for(g = gateways; g->name; g++) {
  1149.         proxy_args->gateways = strsav(proxy_args->gateways, g->name);
  1150.         proxy_args->gateways = strsav(proxy_args->gateways, " ");
  1151.     }
  1152.     proxy_args->gateways = strsav(proxy_args->gateways, "<br>\n");
  1153. }
  1154.  
  1155. void
  1156. end_proxy_args()
  1157. {
  1158.     char buf[BUFSIZ];
  1159.     char *b = NULL;
  1160.  
  1161.     extern char    *acl_rcs, *bind_rcs, *conn_rcs, *encode_rcs,
  1162.             *jcc_rcs, *loaders_rcs, *parsers_rcs, *filters_rcs,
  1163.             *socks4_rcs, *ssplit_rcs, *gnu_regex_rcs, *win32_rcs;
  1164.  
  1165.     b = strsav(b, "<h2>Source versions:</h2>\n");
  1166.     b = strsav(b, "<pre>");
  1167.     sprintf(buf, "%s\n", jcc_rcs       );    b = strsav(b, buf);
  1168.     sprintf(buf, "%s\n", parsers_rcs   );    b = strsav(b, buf);
  1169.     sprintf(buf, "%s\n", filters_rcs   );    b = strsav(b, buf);
  1170.     sprintf(buf, "%s\n", loaders_rcs   );    b = strsav(b, buf);
  1171.     sprintf(buf, "%s\n", conn_rcs      );    b = strsav(b, buf);
  1172.     sprintf(buf, "%s\n", bind_rcs      );    b = strsav(b, buf);
  1173.     sprintf(buf, "%s\n", encode_rcs    );    b = strsav(b, buf);
  1174.     sprintf(buf, "%s\n", socks4_rcs    );    b = strsav(b, buf);
  1175.     sprintf(buf, "%s\n", ssplit_rcs    );    b = strsav(b, buf);
  1176.     sprintf(buf, "%s\n", acl_rcs       );    b = strsav(b, buf);
  1177.     sprintf(buf, "%s\n", gnu_regex_rcs );    b = strsav(b, buf);
  1178.     sprintf(buf, "%s\n", win32_rcs     );    b = strsav(b, buf);
  1179.     b = strsav(b, "</pre>");
  1180.  
  1181. #ifdef REGEX
  1182.     b = strsav(b, "<p>This " BANNER " supports POSIX regular expressions in the path specs.\n");
  1183. #endif
  1184.  
  1185.  
  1186.     b = strsav(b,
  1187.         "<small><small><p>\n"
  1188.         "Code and documentation of the " BANNER " Proxy"
  1189.         "<sup><small>TM</small></sup>\n"
  1190.         "<a href=\""  JUNKBUSTERS "/ht/en/legal.html#copy\">\n" "Copyright</a>© 1997 Junkbusters Corporation\n"
  1191.         "<a href=\"" JUNKBUSTERS "/ht/en/legal.html#marks\"><sup><small>TM</small></sup></a><br>\n"
  1192.         "Copying and distribution permitted under the"
  1193.         "<a href=\""  JUNKBUSTERS "/ht/en/gpl.html\">\n"
  1194.         "<small>GNU</small></a> "
  1195.         "General Public License.\n"
  1196.         "</small>"
  1197.         "<address><kbd>webmaster@junkbusters.com</kbd></address>"
  1198.         "</small>"
  1199.         "</body></html>\n"
  1200.     );
  1201.  
  1202.     proxy_args->trailer = b;
  1203. }
  1204.  
  1205. void
  1206. add_loader(int (*loader)())
  1207. {
  1208.     int i;
  1209.  
  1210.     for(i=0; i < NLOADERS; i++) {
  1211.         if(loaders[i] == NULL) {
  1212.             loaders[i] = loader;
  1213.             break;
  1214.         }
  1215.     }
  1216. }
  1217.  
  1218. int
  1219. run_loader(struct client_state *csp)
  1220. {
  1221.     int ret = 0;
  1222.     int i;
  1223.  
  1224.     for(i=0; i < NLOADERS; i++) {
  1225.         if(loaders[i] == NULL) break;
  1226.         ret |= (loaders[i])(csp);
  1227.     }
  1228.     return(ret);
  1229. }
  1230.  
  1231. /* the way calloc() ought to be -acjc */
  1232. void *
  1233. zalloc(int size)
  1234. {
  1235.     void *ret;
  1236.  
  1237.     if((ret = malloc(size))) {
  1238.         memset(ret, '\0', size);
  1239.     }
  1240.     return(ret);
  1241. }
  1242.  
  1243.