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