home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2000 January / PCW0001.ISO / software / hw / pc2000 / junkbust.exe / loaders.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-10-07  |  29.2 KB  |  1,449 lines

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