2 * Copyright (c) 2006, 2009 Red Hat, Inc.
6 * Author: Patrick Caulfield (pcaulfie@redhat.com)
8 * This software licensed under BSD license, the text of which follows:
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions are met:
13 * - Redistributions of source code must retain the above copyright notice,
14 * this list of conditions and the following disclaimer.
15 * - Redistributions in binary form must reproduce the above copyright notice,
16 * this list of conditions and the following disclaimer in the documentation
17 * and/or other materials provided with the distribution.
18 * - Neither the name of the MontaVista Software, Inc. nor the names of its
19 * contributors may be used to endorse or promote products derived from this
20 * software without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
32 * THE POSSIBILITY OF SUCH DAMAGE.
37 #include <sys/types.h>
39 #include <sys/socket.h>
42 #include <netinet/in.h>
43 #include <arpa/inet.h>
54 #include <corosync/lcr/lcr_comp.h>
55 #include <corosync/engine/objdb.h>
56 #include <corosync/engine/config.h>
60 static int read_config_file_into_objdb(
61 struct objdb_iface_ver0
*objdb
,
62 const char **error_string
);
63 static char error_string_response
[512];
66 static char *strchr_rs (const char *haystack
, int byte
)
68 const char *end_address
= strchr (haystack
, byte
);
70 end_address
+= 1; /* skip past { or = */
71 end_address
+= strspn (end_address
, " \t");
74 return ((char *) end_address
);
77 static int aisparser_readconfig (struct objdb_iface_ver0
*objdb
,
78 const char **error_string
)
80 if (read_config_file_into_objdb(objdb
, error_string
)) {
88 static char *remove_whitespace(char *string
)
90 char *start
= string
+strspn(string
, " \t");
91 char *end
= start
+(strlen(start
))-1;
93 while ((*end
== ' ' || *end
== '\t' || *end
== ':' || *end
== '{') && end
> start
)
101 #define PCHECK_ADD_SUBSECTION 1
102 #define PCHECK_ADD_ITEM 2
104 typedef int (*parser_check_item_f
)(struct objdb_iface_ver0
*objdb
,
105 hdb_handle_t parent_handle
,
108 const char **error_string
);
110 static int parse_section(FILE *fp
,
111 struct objdb_iface_ver0
*objdb
,
112 hdb_handle_t parent_handle
,
113 const char **error_string
,
114 parser_check_item_f parser_check_item_call
)
121 while (fgets (line
, sizeof (line
), fp
)) {
122 if (strlen(line
) > 0) {
123 if (line
[strlen(line
) - 1] == '\n')
124 line
[strlen(line
) - 1] = '\0';
125 if (strlen (line
) > 0 && line
[strlen(line
) - 1] == '\r')
126 line
[strlen(line
) - 1] = '\0';
129 * Clear out white space and tabs
131 for (i
= strlen (line
) - 1; i
> -1; i
--) {
132 if (line
[i
] == '\t' || line
[i
] == ' ') {
140 for (i
= 0; i
< strlen (line
); i
++) {
141 if (line
[i
] != '\t' && line
[i
] != ' ') {
149 * Clear out comments and empty lines
156 if ((loc
= strchr_rs (line
, '{'))) {
157 hdb_handle_t new_parent
;
158 char *section
= remove_whitespace(line
);
162 if (parser_check_item_call
) {
163 if (!parser_check_item_call(objdb
, parent_handle
, PCHECK_ADD_SUBSECTION
,
164 section
, error_string
))
168 objdb
->object_create (parent_handle
, &new_parent
,
169 section
, strlen (section
));
170 if (parse_section(fp
, objdb
, new_parent
, error_string
, parser_check_item_call
))
175 if ((loc
= strchr_rs (line
, ':'))) {
180 key
= remove_whitespace(line
);
181 value
= remove_whitespace(loc
);
182 if (parser_check_item_call
) {
183 if (!parser_check_item_call(objdb
, parent_handle
, PCHECK_ADD_ITEM
,
187 objdb
->object_key_create_typed (parent_handle
, key
,
188 value
, strlen (value
) + 1, OBJDB_VALUETYPE_STRING
);
191 if ((loc
= strchr_rs (line
, '}'))) {
196 if (parent_handle
!= OBJECT_PARENT_HANDLE
) {
197 *error_string
= "Missing closing brace";
204 static int parser_check_item_uidgid(struct objdb_iface_ver0
*objdb
,
205 hdb_handle_t parent_handle
,
208 const char **error_string
)
210 if (type
== PCHECK_ADD_SUBSECTION
) {
211 if (parent_handle
!= OBJECT_PARENT_HANDLE
) {
212 *error_string
= "uidgid: Can't add second level subsection";
216 if (strcmp (name
, "uidgid") != 0) {
217 *error_string
= "uidgid: Can't add subsection different then uidgid";
222 if (type
== PCHECK_ADD_ITEM
) {
223 if (!(strcmp (name
, "uid") == 0 || strcmp (name
, "gid") == 0)) {
224 *error_string
= "uidgid: Only uid and gid are allowed items";
232 static int parser_check_item_service(struct objdb_iface_ver0
*objdb
,
233 hdb_handle_t parent_handle
,
236 const char **error_string
)
238 if (type
== PCHECK_ADD_SUBSECTION
) {
239 if (parent_handle
!= OBJECT_PARENT_HANDLE
) {
240 *error_string
= "service: Can't add second level subsection";
244 if (strcmp (name
, "service") != 0) {
245 *error_string
= "service: Can't add subsection different then service";
250 if (type
== PCHECK_ADD_ITEM
) {
251 if (!(strcmp (name
, "name") == 0 || strcmp (name
, "ver") == 0)) {
252 *error_string
= "service: Only name and ver are allowed items";
260 static int read_uidgid_files_into_objdb(
261 struct objdb_iface_ver0
*objdb
,
262 const char **error_string
)
267 struct dirent
*dirent
;
268 struct dirent
*entry
;
269 char filename
[PATH_MAX
+ FILENAME_MAX
+ 1];
273 struct stat stat_buf
;
275 dirname
= COROSYSCONFDIR
"/uidgid.d";
276 dp
= opendir (dirname
);
281 len
= offsetof(struct dirent
, d_name
) +
282 pathconf(dirname
, _PC_NAME_MAX
) + 1;
285 for (return_code
= readdir_r(dp
, entry
, &dirent
);
286 dirent
!= NULL
&& return_code
== 0;
287 return_code
= readdir_r(dp
, entry
, &dirent
)) {
289 snprintf(filename
, sizeof (filename
), "%s/%s", dirname
, dirent
->d_name
);
290 stat (filename
, &stat_buf
);
291 if (S_ISREG(stat_buf
.st_mode
)) {
293 fp
= fopen (filename
, "r");
294 if (fp
== NULL
) continue;
296 res
= parse_section(fp
, objdb
, OBJECT_PARENT_HANDLE
, error_string
, parser_check_item_uidgid
);
313 static int read_service_files_into_objdb(
314 struct objdb_iface_ver0
*objdb
,
315 const char **error_string
)
320 struct dirent
*dirent
;
321 struct dirent
*entry
;
322 char filename
[PATH_MAX
+ FILENAME_MAX
+ 1];
324 struct stat stat_buf
;
328 dirname
= COROSYSCONFDIR
"/service.d";
329 dp
= opendir (dirname
);
334 len
= offsetof(struct dirent
, d_name
) +
335 pathconf(dirname
, _PC_NAME_MAX
) + 1;
338 for (return_code
= readdir_r(dp
, entry
, &dirent
);
339 dirent
!= NULL
&& return_code
== 0;
340 return_code
= readdir_r(dp
, entry
, &dirent
)) {
342 snprintf(filename
, sizeof (filename
), "%s/%s", dirname
, dirent
->d_name
);
343 stat (filename
, &stat_buf
);
344 if (S_ISREG(stat_buf
.st_mode
)) {
346 fp
= fopen (filename
, "r");
347 if (fp
== NULL
) continue;
349 res
= parse_section(fp
, objdb
, OBJECT_PARENT_HANDLE
, error_string
, parser_check_item_service
);
366 /* Read config file and load into objdb */
367 static int read_config_file_into_objdb(
368 struct objdb_iface_ver0
*objdb
,
369 const char **error_string
)
372 const char *filename
;
373 char *error_reason
= error_string_response
;
376 filename
= getenv ("COROSYNC_MAIN_CONFIG_FILE");
378 filename
= COROSYSCONFDIR
"/corosync.conf";
380 fp
= fopen (filename
, "r");
382 snprintf (error_reason
, sizeof(error_string_response
),
383 "Can't read file %s reason = (%s)\n",
384 filename
, strerror (errno
));
385 *error_string
= error_reason
;
389 res
= parse_section(fp
, objdb
, OBJECT_PARENT_HANDLE
, error_string
, NULL
);
394 res
= read_uidgid_files_into_objdb(objdb
, error_string
);
398 res
= read_service_files_into_objdb(objdb
, error_string
);
402 snprintf (error_reason
, sizeof(error_string_response
),
403 "Successfully read main configuration file '%s'.\n", filename
);
404 *error_string
= error_reason
;
411 * Dynamic Loader definition
414 struct config_iface_ver0 aisparser_iface_ver0
= {
415 .config_readconfig
= aisparser_readconfig
418 struct lcr_iface corosync_aisparser_ver0
[1] = {
420 .name
= "corosync_parser",
422 .versions_replace
= 0,
423 .versions_replace_count
= 0,
425 .dependency_count
= 0,
432 struct corosync_service_handler
*aisparser_get_handler_ver0 (void);
434 struct lcr_comp aisparser_comp_ver0
= {
436 .ifaces
= corosync_aisparser_ver0
439 #ifdef COROSYNC_SOLARIS
440 void corosync_lcr_component_register (void);
442 void corosync_lcr_component_register (void) {
444 __attribute__ ((constructor
)) static void corosync_lcr_component_register (void) {
446 lcr_interfaces_set (&corosync_aisparser_ver0
[0], &aisparser_iface_ver0
);
447 lcr_component_register (&aisparser_comp_ver0
);