Moving simple CGI functions from cgi.c to new file cgisimple.c
[privoxy.git] / cgisimple.c
1 const char cgisimple_rcs[] = "$Id: cgi.c,v 1.26 2001/09/16 15:47:37 jongfoster Exp $";
2 /*********************************************************************
3  *
4  * File        :  $Source: /cvsroot/ijbswa/current/cgi.c,v $
5  *
6  * Purpose     :  Simple CGIs to get information about JunkBuster's
7  *                status.
8  *                
9  *                Functions declared include:
10  * 
11  *
12  * Copyright   :  Written by and Copyright (C) 2001 the SourceForge
13  *                IJBSWA team.  http://ijbswa.sourceforge.net
14  *
15  *                Based on the Internet Junkbuster originally written
16  *                by and Copyright (C) 1997 Anonymous Coders and 
17  *                Junkbusters Corporation.  http://www.junkbusters.com
18  *
19  *                This program is free software; you can redistribute it 
20  *                and/or modify it under the terms of the GNU General
21  *                Public License as published by the Free Software
22  *                Foundation; either version 2 of the License, or (at
23  *                your option) any later version.
24  *
25  *                This program is distributed in the hope that it will
26  *                be useful, but WITHOUT ANY WARRANTY; without even the
27  *                implied warranty of MERCHANTABILITY or FITNESS FOR A
28  *                PARTICULAR PURPOSE.  See the GNU General Public
29  *                License for more details.
30  *
31  *                The GNU General Public License should be included with
32  *                this file.  If not, you can view it at
33  *                http://www.gnu.org/copyleft/gpl.html
34  *                or write to the Free Software Foundation, Inc., 59
35  *                Temple Place - Suite 330, Boston, MA  02111-1307, USA.
36  *
37  * Revisions   :
38  *    $Log: cgi.c,v $
39  *
40  **********************************************************************/
41 \f
42
43 #include "config.h"
44
45 #include <stdio.h>
46 #include <sys/types.h>
47 #include <stdlib.h>
48 #include <ctype.h>
49 #include <string.h>
50 #include <assert.h>
51
52 #ifdef _WIN32
53 #define snprintf _snprintf
54 #endif /* def _WIN32 */
55
56 #include "project.h"
57 #include "cgi.h"
58 #include "cgisimple.h"
59 #include "list.h"
60 #include "encode.h"
61 #include "ssplit.h"
62 #include "jcc.h"
63 #include "filters.h"
64 #include "actions.h"
65 #include "errlog.h"
66 #include "miscutil.h"
67 #include "loadcfg.h"
68
69 const char cgisimple_h_rcs[] = CGISIMPLE_H_VERSION;
70
71
72 static char *show_rcs(void);
73 static void show_defines(struct map *exports);
74
75
76 /*********************************************************************
77  *
78  * Function    :  cgi_default
79  *
80  * Description :  CGI function that is called if no action was given.
81  *                Lists menu of available unhidden CGIs.
82  *               
83  * Parameters  :
84  *           1 :  csp = Current client state (buffers, headers, etc...)
85  *           2 :  rsp = http_response data structure for output
86  *           3 :  parameters = map of cgi parameters
87  *
88  * Returns     :  0
89  *
90  *********************************************************************/
91 int cgi_default(struct client_state *csp, struct http_response *rsp,
92                 struct map *parameters)
93 {
94    char *p;
95    char *tmp = NULL;
96    struct map * exports = default_exports(csp, "");
97
98    /* If there were other parameters, export a dump as "cgi-parameters" */
99    if(parameters)
100    {
101       p = dump_map(parameters);
102       tmp = strsav(tmp, "<p>What made you think this cgi takes parameters?\n"
103                         "Anyway, here they are, in case you're interested:</p>\n");
104       tmp = strsav(tmp, p);
105       map(exports, "cgi-parameters", 1, tmp, 0);
106       free(p);
107    }
108    else
109    {
110       map(exports, "cgi-parameters", 1, "", 1);
111    }
112
113    rsp->body = template_load(csp, "default");
114    template_fill(&rsp->body, exports);
115    free_map(exports);
116    return(0);
117
118 }
119
120
121 /*********************************************************************
122  *
123  * Function    :  cgi_send_banner
124  *
125  * Description :  CGI function that returns a banner. 
126  *
127  * Parameters  :
128  *           1 :  csp = Current client state (buffers, headers, etc...)
129  *           2 :  rsp = http_response data structure for output
130  *           3 :  parameters = map of cgi parameters
131  *
132  * CGI Parameters :
133  *           type : Selects the type of banner between "trans" and "jb".
134  *                  Defaults to "jb" if absent or != "trans".
135  *
136  * Returns     :  0
137  *
138  *********************************************************************/
139 int cgi_send_banner(struct client_state *csp, struct http_response *rsp,
140                     struct map *parameters)
141 {
142    if(strcmp(lookup(parameters, "type"), "trans"))
143    {
144       rsp->body = bindup(image_junkbuster_gif_data, image_junkbuster_gif_length);
145       rsp->content_length = image_junkbuster_gif_length;
146    }
147    else
148    {
149       rsp->body = bindup(image_blank_gif_data, image_blank_gif_length);
150       rsp->content_length = image_blank_gif_length;
151    }   
152
153    enlist(rsp->headers, "Content-Type: image/gif");
154    rsp->is_static = 1;
155
156    return(0);
157
158 }
159
160
161 /*********************************************************************
162  *
163  * Function    :  cgi_show_version
164  *
165  * Description :  CGI function that returns a a web page describing the
166  *                file versions of IJB.
167  *
168  * Parameters  :
169  *           1 :  csp = Current client state (buffers, headers, etc...)
170  *           2 :  rsp = http_response data structure for output
171  *           3 :  parameters = map of cgi parameters
172  *
173  * CGI Parameters :
174  *           type : Selects the type of banner between "trans" and "jb".
175  *                  Defaults to "jb" if absent or != "trans".
176  *
177  * Returns     :  0
178  *
179  *********************************************************************/
180 int cgi_show_version(struct client_state *csp, struct http_response *rsp,
181                      struct map *parameters)
182 {
183    struct map * exports = default_exports(csp, "show-version");
184
185    map(exports, "sourceversions", 1, show_rcs(), 0);  
186
187    rsp->body = template_load(csp, "show-version");
188    template_fill(&rsp->body, exports);
189    free_map(exports);
190    return(0);
191
192 }
193
194  
195 /*********************************************************************
196  *
197  * Function    :  cgi_show_status
198  *
199  * Description :  CGI function that returns a a web page describing the
200  *                current status of IJB.
201  *
202  * Parameters  :
203  *           1 :  csp = Current client state (buffers, headers, etc...)
204  *           2 :  rsp = http_response data structure for output
205  *           3 :  parameters = map of cgi parameters
206  *
207  * CGI Parameters :
208  *           type : Selects the type of banner between "trans" and "jb".
209  *                  Defaults to "jb" if absent or != "trans".
210  *
211  * Returns     :  0
212  *
213  *********************************************************************/
214 int cgi_show_status(struct client_state *csp, struct http_response *rsp,
215                     struct map *parameters)
216 {
217    char *s = NULL;
218    int i;
219
220    FILE * fp;
221    char buf[BUFFER_SIZE];
222    char * p;
223    const char * filename = NULL;
224    char * file_description = NULL;
225 #ifdef FEATURE_STATISTICS
226    float perc_rej;   /* Percentage of http requests rejected */
227    int local_urls_read;
228    int local_urls_rejected;
229 #endif /* ndef FEATURE_STATISTICS */
230
231    struct map * exports = default_exports(csp, "show-status");
232
233    switch (*(lookup(parameters, "file")))
234    {
235    case 'p':
236       if (csp->actions_list)
237       {
238          filename = csp->actions_list->filename;
239          file_description = "Actions List";
240       }
241       break;
242
243    case 'r':
244       if (csp->rlist)
245       {
246          filename = csp->rlist->filename;
247          file_description = "Regex Filter List";
248       }
249       break;
250
251 #ifdef FEATURE_TRUST
252    case 't':
253       if (csp->tlist)
254       {
255          filename = csp->tlist->filename;
256          file_description = "Trust List";
257       }
258       break;
259 #endif /* def FEATURE_TRUST */
260    }
261
262    if (NULL != filename)
263    {
264       map(exports, "file-description", 1, file_description, 1);
265       map(exports, "filepath", 1, html_encode(filename), 0);
266
267       if ((fp = fopen(filename, "r")) == NULL)
268       {
269          map(exports, "content", 1, "<h1>ERROR OPENING FILE!</h1>", 1);
270       }
271       else
272       {
273          while (fgets(buf, sizeof(buf), fp))
274          {
275             p = html_encode(buf);
276             if (p)
277             {
278                s = strsav(s, p);
279                freez(p);
280                s = strsav(s, "<br>");
281             }
282          }
283          fclose(fp);
284          map(exports, "contents", 1, s, 0);
285       }
286       rsp->body = template_load(csp, "show-status-file");
287       template_fill(&rsp->body, exports);
288       free_map(exports);
289       return(0);
290
291    }
292
293    map(exports, "redirect-url", 1, REDIRECT_URL, 1);
294    
295    s = NULL;
296    for (i=0; i < Argc; i++)
297    {
298       s = strsav(s, Argv[i]);
299       s = strsav(s, " ");
300    }
301    map(exports, "invocation", 1, s, 0);
302
303    map(exports, "options", 1, csp->config->proxy_args, 1);
304    show_defines(exports);
305
306 #ifdef FEATURE_STATISTICS
307    local_urls_read     = urls_read;
308    local_urls_rejected = urls_rejected;
309
310    /*
311     * Need to alter the stats not to include the fetch of this
312     * page.
313     *
314     * Can't do following thread safely! doh!
315     *
316     * urls_read--;
317     * urls_rejected--; * This will be incremented subsequently *
318     */
319
320    if (local_urls_read == 0)
321    {
322       map_block_killer(exports, "have-stats");
323    }
324    else
325    {
326       map_block_killer(exports, "have-no-stats");
327
328       perc_rej = (float)local_urls_rejected * 100.0F /
329             (float)local_urls_read;
330
331       sprintf(buf, "%d", local_urls_read);
332       map(exports, "requests-received", 1, buf, 1);
333
334       sprintf(buf, "%d", local_urls_rejected);
335       map(exports, "requests-blocked", 1, buf, 1);
336
337       sprintf(buf, "%6.2f", perc_rej);
338       map(exports, "percent-blocked", 1, buf, 1);
339    }
340
341 #else /* ndef FEATURE_STATISTICS */
342    map_block_killer(exports, "statistics");
343 #endif /* ndef FEATURE_STATISTICS */
344
345    if (csp->actions_list)
346    {
347       map(exports, "actions-filename", 1,  csp->actions_list->filename, 1);
348    }
349    else
350    {
351       map(exports, "actions-filename", 1, "None specified", 1);
352    }
353
354    if (csp->rlist)
355    {
356       map(exports, "re-filter-filename", 1,  csp->rlist->filename, 1);
357    }
358    else
359    {
360       map(exports, "re-filter-filename", 1, "None specified", 1);
361    }
362
363 #ifdef FEATURE_TRUST
364    if (csp->tlist)
365    {
366       map(exports, "trust-filename", 1,  csp->tlist->filename, 1);
367    }
368    else
369    {
370        map(exports, "trust-filename", 1, "None specified", 1);
371    }
372 #else
373    map_block_killer(exports, "trust-support");
374 #endif /* ndef FEATURE_TRUST */
375
376    rsp->body = template_load(csp, "show-status");
377    template_fill(&rsp->body, exports);
378    free_map(exports);
379    return(0);
380
381 }
382
383  
384 /*********************************************************************
385  *
386  * Function    :  cgi_show_url_info
387  *
388  * Description :  CGI function that determines and shows which actions
389  *                junkbuster will perform for a given url, and which
390  *                matches starting from the defaults have lead to that.
391  *
392  * Parameters  :
393  *           1 :  csp = Current client state (buffers, headers, etc...)
394  *           2 :  rsp = http_response data structure for output
395  *           3 :  parameters = map of cgi parameters
396  *
397  * CGI Parameters :
398  *            url : The url whose actions are to be determined.
399  *                  If url is unset, the url-given conditional will be
400  *                  set, so that all but the form can be suppressed in
401  *                  the template.
402  *
403  * Returns     :  0
404  *
405  *********************************************************************/
406 int cgi_show_url_info(struct client_state *csp, struct http_response *rsp,
407                       struct map *parameters)
408 {
409    char *url_param;
410    char *host = NULL;
411    struct map * exports = default_exports(csp, "show-url-info");
412
413    if (NULL == (url_param = strdup(lookup(parameters, "url"))) || *url_param == '\0')
414    {
415       map_block_killer(exports, "url-given");
416       map(exports, "url", 1, "", 1);
417    }
418    else
419    {
420       char *matches = NULL;
421       char *path;
422       char *s;
423       int port = 80;
424       int hits = 0;
425       struct file_list *fl;
426       struct url_actions *b;
427       struct url_spec url[1];
428       struct current_action_spec action[1];
429       
430       host = url_param;
431       host += (strncmp(url_param, "http://", 7)) ? 0 : 7;
432
433       map(exports, "url", 1, host, 1);
434       map(exports, "url-html", 1, html_encode(host), 0);
435
436       init_current_action(action);
437
438       s = current_action_to_text(action);
439       map(exports, "default", 1, s , 0);
440
441       if (((fl = csp->actions_list) == NULL) || ((b = fl->f) == NULL))
442       {
443          map(exports, "matches", 1, "none" , 1);
444          map(exports, "final", 1, lookup(exports, "default"), 1);
445
446          freez(url_param);
447          free_current_action(action);
448
449          rsp->body = template_load(csp, "show-url-info");
450          template_fill(&rsp->body, exports);
451          free_map(exports);
452
453          return 0;
454       }
455
456       s = strchr(host, '/');
457       if (s != NULL)
458       {
459          path = strdup(s);
460          *s = '\0';
461       }
462       else
463       {
464          path = strdup("");
465       }
466       s = strchr(host, ':');
467       if (s != NULL)
468       {
469          *s++ = '\0';
470          port = atoi(s);
471          s = NULL;
472       }
473
474       *url = dsplit(host);
475
476       /* if splitting the domain fails, punt */
477       if (url->dbuf == NULL)
478       {
479          map(exports, "matches", 1, "none" , 1);
480          map(exports, "final", 1, lookup(exports, "default"), 1);
481
482          freez(url_param);
483          freez(path);
484          free_current_action(action);
485
486          rsp->body = template_load(csp, "show-url-info");
487          template_fill(&rsp->body, exports);
488          free_map(exports);
489
490          return 0;
491       }
492
493       for (b = b->next; NULL != b; b = b->next)
494       {
495          if ((b->url->port == 0) || (b->url->port == port))
496          {
497             if ((b->url->domain[0] == '\0') || (domaincmp(b->url, url) == 0))
498             {
499                if ((b->url->path == NULL) ||
500 #ifdef REGEX
501                   (regexec(b->url->preg, path, 0, NULL, 0) == 0)
502 #else
503                   (strncmp(b->url->path, path, b->url->pathlen) == 0)
504 #endif
505                )
506                {
507                   s = actions_to_text(b->action);
508                   matches = strsav(matches, "<b>{");
509                   matches = strsav(matches, s);
510                   matches = strsav(matches, " }</b><br>\n<code>");
511                   matches = strsav(matches, b->url->spec);
512                   matches = strsav(matches, "</code><br>\n<br>\n");
513                   freez(s);
514
515                   merge_current_action(action, b->action);
516                   hits++;
517                }
518             }
519          }
520       }
521
522       if (hits)
523       {
524          map(exports, "matches", 1, matches , 0);
525       }
526       else
527       {
528          map(exports, "matches", 1, "none", 1);
529       }
530       matches = NULL;
531
532       freez(url->dbuf);
533       freez(url->dvec);
534
535       freez(url_param);
536       freez(path);
537
538       s = current_action_to_text(action);
539       map(exports, "final", 1, s, 0);
540       s = NULL;
541
542       free_current_action(action);
543    }
544
545    rsp->body = template_load(csp, "show-url-info");
546    template_fill(&rsp->body, exports);
547    free_map(exports);
548    return 0;
549
550 }
551
552
553 /*********************************************************************
554  *
555  * Function    :  cgi_robots_txt
556  *
557  * Description :  CGI function to return "/robots.txt".
558  *
559  * Parameters  :
560  *           1 :  csp = Current client state (buffers, headers, etc...)
561  *           2 :  rsp = http_response data structure for output
562  *           3 :  parameters = map of cgi parameters
563  *
564  * CGI Parameters : None
565  *
566  * Returns     :  0
567  *
568  *********************************************************************/
569 int cgi_robots_txt(struct client_state *csp, struct http_response *rsp,
570                    struct map *parameters)
571 {
572    char buf[100];
573
574    rsp->body = strdup(
575       "# This is the Internet Junkbuster control interface.\n"
576       "# It isn't very useful to index it, and you're likely to break stuff.\n"
577       "# So go away!\n"
578       "\n"
579       "User-agent: *\n"
580       "Disallow: /\n"
581       "\n");
582
583    enlist_unique(rsp->headers, "Content-Type: text/plain", 13);
584
585    rsp->is_static = 1;
586
587    get_http_time(7 * 24 * 60 * 60, buf); /* 7 days into future */
588    enlist_unique_header(rsp->headers, "Expires", buf);
589
590    return 0;
591 }
592
593
594 /*********************************************************************
595  *
596  * Function    :  show_defines
597  *
598  * Description :  Create a string with all conditional #defines used
599  *                when building
600  *
601  * Parameters  :  None
602  *
603  * Returns     :  string 
604  *
605  *********************************************************************/
606 static void show_defines(struct map *exports)
607 {
608
609 #ifdef FEATURE_ACL
610    map_conditional(exports, "FEATURE_ACL", 1);
611 #else /* ifndef FEATURE_ACL */
612    map_conditional(exports, "FEATURE_ACL", 0);
613 #endif /* ndef FEATURE_ACL */
614
615 #ifdef FEATURE_COOKIE_JAR
616    map_conditional(exports, "FEATURE_COOKIE_JAR", 1);
617 #else /* ifndef FEATURE_COOKIE_JAR */
618    map_conditional(exports, "FEATURE_COOKIE_JAR", 0);
619 #endif /* ndef FEATURE_COOKIE_JAR */
620
621 #ifdef FEATURE_DENY_GZIP
622    map_conditional(exports, "FEATURE_DENY_GZIP", 1);
623 #else /* ifndef FEATURE_DENY_GZIP */
624    map_conditional(exports, "FEATURE_DENY_GZIP", 0);
625 #endif /* ndef FEATURE_DENY_GZIP */
626
627 #ifdef FEATURE_FAST_REDIRECTS
628    map_conditional(exports, "FEATURE_FAST_REDIRECTS", 1);
629 #else /* ifndef FEATURE_FAST_REDIRECTS */
630    map_conditional(exports, "FEATURE_FAST_REDIRECTS", 0);
631 #endif /* ndef FEATURE_FAST_REDIRECTS */
632
633 #ifdef FEATURE_FORCE_LOAD
634    map_conditional(exports, "FEATURE_FORCE_LOAD", 1);
635 #else /* ifndef FEATURE_FORCE_LOAD */
636    map_conditional(exports, "FEATURE_FORCE_LOAD", 0);
637 #endif /* ndef FEATURE_FORCE_LOAD */
638
639 #ifdef FEATURE_IMAGE_BLOCKING
640    map_conditional(exports, "FEATURE_IMAGE_BLOCKING", 1);
641 #else /* ifndef FEATURE_IMAGE_BLOCKING */
642    map_conditional(exports, "FEATURE_IMAGE_BLOCKING", 0);
643 #endif /* ndef FEATURE_IMAGE_BLOCKING */
644
645 #ifdef FEATURE_IMAGE_DETECT_MSIE
646    map_conditional(exports, "FEATURE_IMAGE_DETECT_MSIE", 1);
647 #else /* ifndef FEATURE_IMAGE_DETECT_MSIE */
648    map_conditional(exports, "FEATURE_IMAGE_DETECT_MSIE", 0);
649 #endif /* ndef FEATURE_IMAGE_DETECT_MSIE */
650
651 #ifdef FEATURE_KILL_POPUPS
652    map_conditional(exports, "FEATURE_KILL_POPUPS", 1);
653 #else /* ifndef FEATURE_KILL_POPUPS */
654    map_conditional(exports, "FEATURE_KILL_POPUPS", 0);
655 #endif /* ndef FEATURE_KILL_POPUPS */
656
657 #ifdef FEATURE_PTHREAD
658    map_conditional(exports, "FEATURE_PTHREAD", 1);
659 #else /* ifndef FEATURE_PTHREAD */
660    map_conditional(exports, "FEATURE_PTHREAD", 0);
661 #endif /* ndef FEATURE_PTHREAD */
662
663 #ifdef FEATURE_STATISTICS
664    map_conditional(exports, "FEATURE_STATISTICS", 1);
665 #else /* ifndef FEATURE_STATISTICS */
666    map_conditional(exports, "FEATURE_STATISTICS", 0);
667 #endif /* ndef FEATURE_STATISTICS */
668
669 #ifdef FEATURE_TOGGLE
670    map_conditional(exports, "FEATURE_TOGGLE", 1);
671 #else /* ifndef FEATURE_TOGGLE */
672    map_conditional(exports, "FEATURE_TOGGLE", 0);
673 #endif /* ndef FEATURE_TOGGLE */
674
675 #ifdef FEATURE_TRUST
676    map_conditional(exports, "FEATURE_TRUST", 1);
677 #else /* ifndef FEATURE_TRUST */
678    map_conditional(exports, "FEATURE_TRUST", 0);
679 #endif /* ndef FEATURE_TRUST */
680
681 #ifdef REGEX_GNU
682    map_conditional(exports, "REGEX_GNU", 1);
683 #else /* ifndef REGEX_GNU */
684    map_conditional(exports, "REGEX_GNU", 0);
685 #endif /* def REGEX_GNU */
686
687 #ifdef REGEX_PCRE
688    map_conditional(exports, "REGEX_PCRE", 1);
689 #else /* ifndef REGEX_PCRE */
690    map_conditional(exports, "REGEX_PCRE", 0);
691 #endif /* def REGEX_PCRE */
692
693 #ifdef STATIC_PCRE
694    map_conditional(exports, "STATIC_PCRE", 1);
695 #else /* ifndef STATIC_PCRE */
696    map_conditional(exports, "STATIC_PCRE", 0);
697 #endif /* ndef STATIC_PCRE */
698
699 #ifdef STATIC_PCRS
700    map_conditional(exports, "STATIC_PCRS", 1);
701 #else /* ifndef STATIC_PCRS */
702    map_conditional(exports, "STATIC_PCRS", 0);
703 #endif /* ndef STATIC_PCRS */
704
705    map(exports, "FORCE_PREFIX", 1, FORCE_PREFIX, 1);
706 }
707
708
709 /*********************************************************************
710  *
711  * Function    :  show_rcs
712  *
713  * Description :  Create a string with the rcs info for all sourcefiles
714  *
715  * Parameters  :  None
716  *
717  * Returns     :  string 
718  *
719  *********************************************************************/
720 static char *show_rcs(void)
721 {
722    char *b = NULL;
723    char buf[BUFFER_SIZE];
724
725    /* Instead of including *all* dot h's in the project (thus creating a
726     * tremendous amount of dependencies), I will concede to declaring them
727     * as extern's.  This forces the developer to add to this list, but oh well.
728     */
729
730 #define SHOW_RCS(__x)            \
731    {                             \
732       extern const char __x[];   \
733       sprintf(buf, "%s\n", __x); \
734       b = strsav(b, buf);        \
735    }
736
737    /* In alphabetical order */
738    SHOW_RCS(actions_h_rcs)
739    SHOW_RCS(actions_rcs)
740    SHOW_RCS(cgi_h_rcs)
741    SHOW_RCS(cgi_rcs)
742 #ifdef FEATURE_CGI_EDIT_ACTIONS
743    SHOW_RCS(cgiedit_h_rcs)
744    SHOW_RCS(cgiedit_rcs)
745 #endif /* def FEATURE_CGI_EDIT_ACTIONS */
746    SHOW_RCS(cgisimple_h_rcs)
747    SHOW_RCS(cgisimple_rcs)
748 #ifdef __MINGW32__
749    SHOW_RCS(cygwin_h_rcs)
750 #endif
751    SHOW_RCS(deanimate_h_rcs)
752    SHOW_RCS(deanimate_rcs)
753    SHOW_RCS(encode_h_rcs)
754    SHOW_RCS(encode_rcs)
755    SHOW_RCS(errlog_h_rcs)
756    SHOW_RCS(errlog_rcs)
757    SHOW_RCS(filters_h_rcs)
758    SHOW_RCS(filters_rcs)
759    SHOW_RCS(gateway_h_rcs)
760    SHOW_RCS(gateway_rcs)
761 #ifdef GNU_REGEX
762    SHOW_RCS(gnu_regex_h_rcs)
763    SHOW_RCS(gnu_regex_rcs)
764 #endif /* def GNU_REGEX */
765    SHOW_RCS(jbsockets_h_rcs)
766    SHOW_RCS(jbsockets_rcs)
767    SHOW_RCS(jcc_h_rcs)
768    SHOW_RCS(jcc_rcs)
769 #ifdef FEATURE_KILL_POPUPS
770    SHOW_RCS(killpopup_h_rcs)
771    SHOW_RCS(killpopup_rcs)
772 #endif /* def FEATURE_KILL_POPUPS */
773    SHOW_RCS(list_h_rcs)
774    SHOW_RCS(list_rcs)
775    SHOW_RCS(loadcfg_h_rcs)
776    SHOW_RCS(loadcfg_rcs)
777    SHOW_RCS(loaders_h_rcs)
778    SHOW_RCS(loaders_rcs)
779    SHOW_RCS(miscutil_h_rcs)
780    SHOW_RCS(miscutil_rcs)
781    SHOW_RCS(parsers_h_rcs)
782    SHOW_RCS(parsers_rcs)
783    SHOW_RCS(pcrs_rcs)
784    SHOW_RCS(pcrs_h_rcs)
785    SHOW_RCS(project_h_rcs)
786    SHOW_RCS(ssplit_h_rcs)
787    SHOW_RCS(ssplit_rcs)
788 #ifdef _WIN32
789 #ifndef _WIN_CONSOLE
790    SHOW_RCS(w32log_h_rcs)
791    SHOW_RCS(w32log_rcs)
792    SHOW_RCS(w32res_h_rcs)
793    SHOW_RCS(w32taskbar_h_rcs)
794    SHOW_RCS(w32taskbar_rcs)
795 #endif /* ndef _WIN_CONSOLE */
796    SHOW_RCS(win32_h_rcs)
797    SHOW_RCS(win32_rcs)
798 #endif /* def _WIN32 */
799
800 #undef SHOW_RCS
801
802    return(b);
803 }
804
805
806 /*
807   Local Variables:
808   tab-width: 3
809   end:
810 */