fixes init script for non ipv6 enabled systems #472755
[packages/xinetd.git] / xinetd / includedir.c
1 /*
2  * (c) Copyright 1998-2001 by Rob Braun
3  * All rights reserved.  The file named COPYRIGHT specifies the terms
4  * and conditions for redistribution.
5  */
6 #include "config.h"
7 #include <sys/types.h>
8 #include <dirent.h>
9 #include <sys/stat.h>
10 #include <unistd.h>
11 #include <fcntl.h>
12 #include <syslog.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <errno.h>
17
18 #include "pset.h"
19 #include "str.h"
20 #include "includedir.h"
21 #include "msg.h"
22 #include "parse.h"
23 #include "sio.h"
24
25 #if !defined(NAME_MAX)
26    #ifdef FILENAME_MAX
27    #define NAME_MAX FILENAME_MAX
28    #else
29    #define NAME_MAX 256
30    #endif
31 #endif
32
33 static int compfunc( const void *_a, const void *_b )
34 {
35    char **a = (char **)_a;
36    char **b = (char **)_b;
37
38    if( a == NULL || a[0] == NULL )
39       return -1;
40    if( b == NULL || b[0] == NULL )
41       return 1;
42    return strcmp(a[0], b[0]);
43 }
44
45 void handle_includedir(const char *service_name, struct configuration *confp)
46 {
47    char *filename;
48    pset_h dir_list;
49    DIR *dirfp;
50    struct dirent *direntry;
51    char *storename;
52    struct stat sb;
53    int u, incfd, len_sn;
54    const char *func = "handle_includedir";
55
56    if( service_name == NULL )
57       return;
58
59    dir_list = pset_create(0, 0);
60    if( dir_list == NULL )
61       return;
62
63    len_sn = strlen(service_name);
64    filename = (char *)malloc(len_sn + NAME_MAX + 2);
65    if (! filename) {
66       parsemsg( LOG_ERR, func, ES_NOMEM );
67       return;
68    }
69    errno = 0;
70    dirfp = opendir(service_name);
71    if (! dirfp) {
72       parsemsg( LOG_ERR, func, "Unable to read included directory: %s", service_name);
73       free(filename);
74       return;
75    }
76    /* Get the list of files in the directory */
77    while ((direntry = readdir(dirfp)) != 0) {
78       storename = new_string(direntry->d_name);
79       if( storename == NULL ) {
80          parsemsg( LOG_ERR, func, ES_NOMEM );
81          free( filename );
82          return;
83       }
84       pset_add(dir_list, storename);
85    }
86    closedir(dirfp);
87
88    /* Sort the list using "compfunc" */
89    pset_sort(dir_list, compfunc);
90
91    /* Now, traverse the list in alphabetic order 
92     * (as determined by strcmp).
93     */
94    for( u = 0; (unsigned)u < pset_count(dir_list); u++ ) {
95       storename = pset_pointer(dir_list, u);
96
97       /* Don't try to parse any files containing a dot ('.')
98       * or ending with a tilde ('~'). This catches the case of 
99       * '.' and '..', as well as preventing the parsing of 
100       * many editor files, temporary files and those saved by RPM
101       * package upgrades.
102       */
103       if ( !storename[0] /* Shouldn't happen */ || 
104                       strchr(storename, '.') ||
105                       storename[strlen(storename)-1] == '~') {
106          pset_remove(dir_list, storename);
107          free(storename);
108          u--;
109          continue;
110       }
111
112       strx_sprint(filename, len_sn+NAME_MAX+1, "%s/%s",
113          service_name, storename);
114
115       if( stat(filename, &sb) < 0 ) {
116          parsemsg( LOG_ERR, func, "Unable to stat includedir file %s", filename);
117          pset_remove(dir_list, storename);
118          free(storename);
119          u--;
120          continue;
121       }
122
123       /* Only open it if it's a regular file. */
124       if( !S_ISREG(sb.st_mode) ) {
125           msg( LOG_ERR, func,
126          "%s is not a regular file. It is being skipped.",
127          filename );
128           pset_remove(dir_list, storename);
129           free(storename);
130           u--;
131           continue;
132       }
133       incfd = open(filename, O_RDONLY);
134       if( incfd < 0 ) {
135          parsemsg( LOG_ERR, func, "Unable to open included configuration file: %s", filename);
136          pset_remove(dir_list, storename);
137          free(storename);
138          u--;
139          continue;
140       }
141       parsemsg( LOG_DEBUG,func,"Reading included configuration file: %s",filename);
142       parse_conf_file(incfd, confp, filename);
143
144       /* 
145        * parse_conf_file eventually calls Srdline, try Sclosing to 
146        * unmmap memory. 
147        */
148       Sclose(incfd);
149       pset_remove(dir_list, storename);
150       free(storename);
151       u--;
152    }
153    if ( errno != 0) {
154       parsemsg( LOG_ERR, func, "Error reading included directory: %s", service_name);
155    }
156    pset_destroy(dir_list);
157    free(filename);
158 }