]> git.proxmox.com Git - mirror_corosync.git/blame - exec/coroparse.c
mon: Remove leftover print of debug output to err
[mirror_corosync.git] / exec / coroparse.c
CommitLineData
2f552719 1/*
8a45e2b1 2 * Copyright (c) 2006, 2011 Red Hat, Inc.
2f552719
SD
3 *
4 * All rights reserved.
5 *
6 * Author: Patrick Caulfield (pcaulfie@redhat.com)
8a45e2b1 7 * Jan Friesse (jfriesse@redhat.com)
2f552719
SD
8 *
9 * This software licensed under BSD license, the text of which follows:
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions are met:
13 *
14 * - Redistributions of source code must retain the above copyright notice,
15 * this list of conditions and the following disclaimer.
16 * - Redistributions in binary form must reproduce the above copyright notice,
17 * this list of conditions and the following disclaimer in the documentation
18 * and/or other materials provided with the distribution.
19 * - Neither the name of the MontaVista Software, Inc. nor the names of its
20 * contributors may be used to endorse or promote products derived from this
21 * software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
27 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
33 * THE POSSIBILITY OF SUCH DAMAGE.
34 */
031c02f5
FDN
35
36#include <config.h>
37
2f552719
SD
38#include <sys/types.h>
39#include <sys/uio.h>
40#include <sys/socket.h>
1e0d40cd 41#include <sys/stat.h>
2f552719
SD
42#include <sys/un.h>
43#include <netinet/in.h>
44#include <arpa/inet.h>
45#include <unistd.h>
46#include <fcntl.h>
47#include <stdlib.h>
48#include <stdio.h>
49#include <errno.h>
2f552719 50#include <string.h>
ae229831 51#include <dirent.h>
6fd822c4 52#include <limits.h>
2290913d 53#include <stddef.h>
8a45e2b1
JF
54#include <grp.h>
55#include <pwd.h>
2f552719 56
8a45e2b1 57#include <corosync/list.h>
37e17e7a 58#include <qb/qbutil.h>
00434a4f 59#define LOGSYS_UTILS_ONLY 1
8ad583a5 60#include <corosync/logsys.h>
6f5e3293 61#include <corosync/icmap.h>
e1f53138 62
f763d3ba 63#include "main.h"
2f552719
SD
64#include "util.h"
65
8a45e2b1
JF
66enum parser_cb_type {
67 PARSER_CB_START,
68 PARSER_CB_END,
69 PARSER_CB_SECTION_START,
70 PARSER_CB_SECTION_END,
71 PARSER_CB_ITEM,
72};
73
74typedef int (*parser_cb_f)(const char *path,
75 char *key,
76 char *value,
77 enum parser_cb_type type,
78 const char **error_string,
79 void *user_data);
80
81enum main_cp_cb_data_state {
82 MAIN_CP_CB_DATA_STATE_NORMAL,
83 MAIN_CP_CB_DATA_STATE_TOTEM,
84 MAIN_CP_CB_DATA_STATE_INTERFACE,
85 MAIN_CP_CB_DATA_STATE_LOGGER_SUBSYS,
86 MAIN_CP_CB_DATA_STATE_UIDGID,
87 MAIN_CP_CB_DATA_STATE_LOGGING_DAEMON,
88 MAIN_CP_CB_DATA_STATE_MEMBER,
89 MAIN_CP_CB_DATA_STATE_QUORUM,
90};
91
92struct key_value_list_item {
93 char *key;
94 char *value;
95 struct list_head list;
96};
97
98struct main_cp_cb_data {
99 enum main_cp_cb_data_state state;
100
101 int ringnumber;
102 char *bindnetaddr;
103 char *mcastaddr;
104 char *broadcast;
105 int mcastport;
106 int ttl;
107
108 struct list_head logger_subsys_items_head;
109 char *subsys;
110 char *logging_daemon_name;
111 struct list_head member_items_head;
112};
113
114static int read_config_file_into_icmap(
23c64c64 115 const char **error_string);
2f552719
SD
116static char error_string_response[512];
117
8a45e2b1
JF
118static int uid_determine (const char *req_user)
119{
120 int pw_uid = 0;
121 struct passwd passwd;
122 struct passwd* pwdptr = &passwd;
123 struct passwd* temp_pwd_pt;
124 char *pwdbuffer;
125 int pwdlinelen;
126
127 pwdlinelen = sysconf (_SC_GETPW_R_SIZE_MAX);
128
129 if (pwdlinelen == -1) {
130 pwdlinelen = 256;
131 }
132
133 pwdbuffer = malloc (pwdlinelen);
134
135 if ((getpwnam_r (req_user, pwdptr, pwdbuffer, pwdlinelen, &temp_pwd_pt)) != 0) {
136 sprintf (error_string_response,
137 "The '%s' user is not found in /etc/passwd, please read the documentation.",
138 req_user);
139 return (-1);
140 }
141 pw_uid = passwd.pw_uid;
142 free (pwdbuffer);
143
144 return pw_uid;
145}
146
147static int gid_determine (const char *req_group)
148{
7c8e83ac 149 int corosync_gid = 0;
8a45e2b1
JF
150 struct group group;
151 struct group * grpptr = &group;
152 struct group * temp_grp_pt;
153 char *grpbuffer;
154 int grplinelen;
155
156 grplinelen = sysconf (_SC_GETGR_R_SIZE_MAX);
157
158 if (grplinelen == -1) {
159 grplinelen = 256;
160 }
161
162 grpbuffer = malloc (grplinelen);
163
164 if ((getgrnam_r (req_group, grpptr, grpbuffer, grplinelen, &temp_grp_pt)) != 0) {
165 sprintf (error_string_response,
166 "The '%s' group is not found in /etc/group, please read the documentation.",
167 req_group);
168 return (-1);
169 }
7c8e83ac 170 corosync_gid = group.gr_gid;
8a45e2b1 171 free (grpbuffer);
2f552719 172
7c8e83ac 173 return corosync_gid;
8a45e2b1 174}
3ffb151a
FDN
175static char *strchr_rs (const char *haystack, int byte)
176{
177 const char *end_address = strchr (haystack, byte);
178 if (end_address) {
179 end_address += 1; /* skip past { or = */
8a45e2b1
JF
180
181 while (*end_address == ' ' || *end_address == '\t')
182 end_address++;
3ffb151a
FDN
183 }
184
185 return ((char *) end_address);
186}
187
f763d3ba 188int coroparse_configparse (const char **error_string)
2f552719 189{
8a45e2b1 190 if (read_config_file_into_icmap(error_string)) {
2f552719
SD
191 return -1;
192 }
193
194 return 0;
195}
196
2f552719
SD
197static char *remove_whitespace(char *string)
198{
8a45e2b1
JF
199 char *start;
200 char *end;
2f552719 201
8a45e2b1
JF
202 start = string;
203 while (*start == ' ' || *start == '\t')
204 start++;
205
206 end = start+(strlen(start))-1;
2f552719
SD
207 while ((*end == ' ' || *end == '\t' || *end == ':' || *end == '{') && end > start)
208 end--;
209 if (end != start)
210 *(end+1) = '\0';
211
212 return start;
213}
214
ae229831 215
ae229831 216
2f552719 217static int parse_section(FILE *fp,
8a45e2b1 218 char *path,
ae229831 219 const char **error_string,
8a45e2b1
JF
220 parser_cb_f parser_cb,
221 void *user_data)
2f552719
SD
222{
223 char line[512];
224 int i;
225 char *loc;
99db3567 226 int ignore_line;
8a45e2b1
JF
227 char new_keyname[ICMAP_KEYNAME_MAXLEN];
228
229 if (strcmp(path, "") == 0) {
230 parser_cb("", NULL, NULL, PARSER_CB_START, error_string, user_data);
231 }
2f552719 232
94b64352
JF
233 while (fgets (line, sizeof (line), fp)) {
234 if (strlen(line) > 0) {
235 if (line[strlen(line) - 1] == '\n')
236 line[strlen(line) - 1] = '\0';
237 if (strlen (line) > 0 && line[strlen(line) - 1] == '\r')
238 line[strlen(line) - 1] = '\0';
239 }
2f552719
SD
240 /*
241 * Clear out white space and tabs
242 */
243 for (i = strlen (line) - 1; i > -1; i--) {
244 if (line[i] == '\t' || line[i] == ' ') {
245 line[i] = '\0';
246 } else {
247 break;
248 }
249 }
99db3567
JF
250
251 ignore_line = 1;
252 for (i = 0; i < strlen (line); i++) {
253 if (line[i] != '\t' && line[i] != ' ') {
254 if (line[i] != '#')
255 ignore_line = 0;
256
257 break;
258 }
259 }
2f552719
SD
260 /*
261 * Clear out comments and empty lines
262 */
99db3567 263 if (ignore_line) {
2f552719
SD
264 continue;
265 }
266
267 /* New section ? */
283011c6 268 if ((loc = strchr_rs (line, '{'))) {
2f552719
SD
269 char *section = remove_whitespace(line);
270
271 loc--;
272 *loc = '\0';
8a45e2b1
JF
273
274 strcpy(new_keyname, path);
275 if (strcmp(path, "") != 0) {
276 strcat(new_keyname, ".");
ae229831 277 }
8a45e2b1 278 strcat(new_keyname, section);
ae229831 279
8a45e2b1
JF
280 if (!parser_cb(new_keyname, NULL, NULL, PARSER_CB_SECTION_START, error_string, user_data)) {
281 return -1;
282 }
283
284 if (parse_section(fp, new_keyname, error_string, parser_cb, user_data))
2f552719
SD
285 return -1;
286 }
287
288 /* New key/value */
283011c6 289 if ((loc = strchr_rs (line, ':'))) {
2f552719
SD
290 char *key;
291 char *value;
292
293 *(loc-1) = '\0';
294 key = remove_whitespace(line);
295 value = remove_whitespace(loc);
8a45e2b1
JF
296
297 strcpy(new_keyname, path);
298 if (strcmp(path, "") != 0) {
299 strcat(new_keyname, ".");
300 }
301 strcat(new_keyname, key);
302
303 if (!parser_cb(new_keyname, key, value, PARSER_CB_ITEM, error_string, user_data)) {
304 return -1;
ae229831 305 }
2f552719
SD
306 }
307
8236a087 308 if (strchr_rs (line, '}')) {
8a45e2b1
JF
309 if (!parser_cb(path, NULL, NULL, PARSER_CB_SECTION_END, error_string, user_data)) {
310 return -1;
311 }
312
2f552719
SD
313 return 0;
314 }
315 }
316
8a45e2b1 317 if (strcmp(path, "") != 0) {
2f552719
SD
318 *error_string = "Missing closing brace";
319 return -1;
320 }
321
8a45e2b1
JF
322 if (strcmp(path, "") == 0) {
323 parser_cb("", NULL, NULL, PARSER_CB_END, error_string, user_data);
324 }
325
2f552719
SD
326 return 0;
327}
328
8a45e2b1
JF
329static int main_config_parser_cb(const char *path,
330 char *key,
331 char *value,
332 enum parser_cb_type type,
333 const char **error_string,
334 void *user_data)
ae229831 335{
8a45e2b1
JF
336 int i;
337 int add_as_string;
338 char key_name[ICMAP_KEYNAME_MAXLEN];
339 struct main_cp_cb_data *data = (struct main_cp_cb_data *)user_data;
340 struct key_value_list_item *kv_item;
341 struct list_head *iter, *iter_next;
342 int uid, gid;
343
344 switch (type) {
345 case PARSER_CB_START:
346 memset(data, 0, sizeof(struct main_cp_cb_data));
347 data->state = MAIN_CP_CB_DATA_STATE_NORMAL;
348 break;
349 case PARSER_CB_END:
350 break;
351 case PARSER_CB_ITEM:
352 add_as_string = 1;
353
354 switch (data->state) {
355 case MAIN_CP_CB_DATA_STATE_NORMAL:
356 break;
357 case MAIN_CP_CB_DATA_STATE_QUORUM:
358 if ((strcmp(path, "quorum.expected_votes") == 0) ||
359 (strcmp(path, "quorum.votes") == 0) ||
360 (strcmp(path, "quorum.quorumdev_poll") == 0) ||
10098dba 361 (strcmp(path, "quorum.last_man_standing_window") == 0) ||
8a45e2b1
JF
362 (strcmp(path, "quorum.leaving_timeout") == 0)) {
363 i = atoi(value);
364 icmap_set_uint32(path, i);
365 add_as_string = 0;
366 }
367
9589611d 368 if ((strcmp(path, "quorum.two_node") == 0) ||
e8d0af0b 369 (strcmp(path, "quorum.wait_for_all") == 0) ||
b41372c6 370 (strcmp(path, "quorum.auto_tie_breaker") == 0) ||
10098dba 371 (strcmp(path, "quorum.last_man_standing") == 0) ||
8a45e2b1
JF
372 (strcmp(path, "quorum.quorate") == 0)) {
373 i = atoi(value);
374 icmap_set_uint8(path, i);
375 add_as_string = 0;
376 }
377 break;
378 case MAIN_CP_CB_DATA_STATE_TOTEM:
379 if ((strcmp(path, "totem.version") == 0) ||
380 (strcmp(path, "totem.nodeid") == 0) ||
381 (strcmp(path, "totem.threads") == 0) ||
382 (strcmp(path, "totem.token") == 0) ||
383 (strcmp(path, "totem.token_retransmit") == 0) ||
384 (strcmp(path, "totem.hold") == 0) ||
385 (strcmp(path, "totem.token_retransmits_before_loss_const") == 0) ||
386 (strcmp(path, "totem.join") == 0) ||
387 (strcmp(path, "totem.send_join") == 0) ||
388 (strcmp(path, "totem.consensus") == 0) ||
389 (strcmp(path, "totem.merge") == 0) ||
390 (strcmp(path, "totem.downcheck") == 0) ||
391 (strcmp(path, "totem.fail_recv_const") == 0) ||
392 (strcmp(path, "totem.seqno_unchanged_const") == 0) ||
393 (strcmp(path, "totem.rrp_token_expired_timeout") == 0) ||
394 (strcmp(path, "totem.rrp_problem_count_timeout") == 0) ||
395 (strcmp(path, "totem.rrp_problem_count_threshold") == 0) ||
396 (strcmp(path, "totem.rrp_problem_count_mcast_threshold") == 0) ||
397 (strcmp(path, "totem.rrp_autorecovery_check_timeout") == 0) ||
398 (strcmp(path, "totem.heartbeat_failures_allowed") == 0) ||
399 (strcmp(path, "totem.max_network_delay") == 0) ||
400 (strcmp(path, "totem.window_size") == 0) ||
401 (strcmp(path, "totem.max_messages") == 0) ||
402 (strcmp(path, "totem.miss_count_const") == 0) ||
403 (strcmp(path, "totem.netmtu") == 0)) {
404 i = atoi(value);
405 icmap_set_uint32(path, i);
406 add_as_string = 0;
407 }
a919908e
SD
408 break;
409
8a45e2b1
JF
410 case MAIN_CP_CB_DATA_STATE_INTERFACE:
411 if (strcmp(path, "totem.interface.ringnumber") == 0) {
412 data->ringnumber = atoi(value);
413 add_as_string = 0;
414 }
415 if (strcmp(path, "totem.interface.bindnetaddr") == 0) {
416 data->bindnetaddr = strdup(value);
417 add_as_string = 0;
418 }
419 if (strcmp(path, "totem.interface.mcastaddr") == 0) {
420 data->mcastaddr = strdup(value);
421 add_as_string = 0;
422 }
423 if (strcmp(path, "totem.interface.broadcast") == 0) {
424 data->broadcast = strdup(value);
425 add_as_string = 0;
426 }
427 if (strcmp(path, "totem.interface.mcastport") == 0) {
428 data->mcastport = atoi(value);
429 if (data->mcastport < 0 || data->mcastport > 65535) {
430 *error_string = "Invalid multicast port (should be 0..65535)";
431
432 return (0);
433 };
434 add_as_string = 0;
435 }
436 if (strcmp(path, "totem.interface.ttl") == 0) {
437 data->ttl = atoi(value);
438 if (data->ttl < 0 || data->ttl > 255) {
439 *error_string = "Invalid TTL (should be 0..255)";
440
441 return (0);
442 };
443 add_as_string = 0;
444 }
445 break;
446 case MAIN_CP_CB_DATA_STATE_LOGGER_SUBSYS:
447 if (strcmp(key, "subsys") == 0) {
448 data->subsys = strdup(value);
449 if (data->subsys == NULL) {
450 *error_string = "Can't alloc memory";
451
452 return (0);
453 }
454 } else {
455 kv_item = malloc(sizeof(*kv_item));
456 if (kv_item == NULL) {
457 *error_string = "Can't alloc memory";
458
459 return (0);
460 }
461 memset(kv_item, 0, sizeof(*kv_item));
462
463 kv_item->key = strdup(key);
464 kv_item->value = strdup(value);
465 if (kv_item->key == NULL || kv_item->value == NULL) {
466 free(kv_item);
467 *error_string = "Can't alloc memory";
468
469 return (0);
470 }
471 list_init(&kv_item->list);
472 list_add(&kv_item->list, &data->logger_subsys_items_head);
473 }
474 add_as_string = 0;
475 break;
476 case MAIN_CP_CB_DATA_STATE_LOGGING_DAEMON:
477 if (strcmp(key, "subsys") == 0) {
478 data->subsys = strdup(value);
479 if (data->subsys == NULL) {
480 *error_string = "Can't alloc memory";
481
482 return (0);
483 }
484 } else if (strcmp(key, "name") == 0) {
485 data->logging_daemon_name = strdup(value);
486 if (data->logging_daemon_name == NULL) {
487 *error_string = "Can't alloc memory";
488
489 return (0);
490 }
491 } else {
492 kv_item = malloc(sizeof(*kv_item));
493 if (kv_item == NULL) {
494 *error_string = "Can't alloc memory";
495
496 return (0);
497 }
498 memset(kv_item, 0, sizeof(*kv_item));
499
500 kv_item->key = strdup(key);
501 kv_item->value = strdup(value);
502 if (kv_item->key == NULL || kv_item->value == NULL) {
503 free(kv_item);
504 *error_string = "Can't alloc memory";
505
506 return (0);
507 }
508 list_init(&kv_item->list);
509 list_add(&kv_item->list, &data->logger_subsys_items_head);
510 }
511 add_as_string = 0;
512 break;
513 case MAIN_CP_CB_DATA_STATE_UIDGID:
514 if (strcmp(key, "uid") == 0) {
515 uid = uid_determine(value);
516 if (uid == -1) {
517 *error_string = error_string_response;
518 return (0);
519 }
520 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "uidgid.uid.%u",
521 uid);
522 icmap_set_uint8(key_name, 1);
523 add_as_string = 0;
524 } else if (strcmp(key, "gid") == 0) {
525 gid = gid_determine(value);
526 if (gid == -1) {
527 *error_string = error_string_response;
528 return (0);
529 }
530 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "uidgid.gid.%u",
531 gid);
532 icmap_set_uint8(key_name, 1);
533 add_as_string = 0;
534 } else {
535 *error_string = "uidgid: Only uid and gid are allowed items";
536 return (0);
537 }
538 break;
539 case MAIN_CP_CB_DATA_STATE_MEMBER:
540 if (strcmp(key, "memberaddr") != 0) {
541 *error_string = "Only memberaddr is allowed in member section";
542
543 return (0);
544 }
545
546 kv_item = malloc(sizeof(*kv_item));
547 if (kv_item == NULL) {
548 *error_string = "Can't alloc memory";
549
550 return (0);
551 }
552 memset(kv_item, 0, sizeof(*kv_item));
553
554 kv_item->key = strdup(key);
555 kv_item->value = strdup(value);
556 if (kv_item->key == NULL || kv_item->value == NULL) {
557 free(kv_item);
558 *error_string = "Can't alloc memory";
559
560 return (0);
561 }
562 list_init(&kv_item->list);
563 list_add(&kv_item->list, &data->member_items_head);
564 add_as_string = 0;
565 break;
ae229831
JF
566 }
567
8a45e2b1
JF
568 if (add_as_string) {
569 icmap_set_string(path, value);
570 }
571 break;
572 case PARSER_CB_SECTION_START:
573 if (strcmp(path, "totem.interface") == 0) {
574 data->state = MAIN_CP_CB_DATA_STATE_INTERFACE;
575 data->ringnumber = 0;
576 data->mcastport = -1;
577 data->ttl = -1;
578 list_init(&data->member_items_head);
579 };
580 if (strcmp(path, "totem") == 0) {
581 data->state = MAIN_CP_CB_DATA_STATE_TOTEM;
582 };
583
584 if (strcmp(path, "logging.logger_subsys") == 0) {
585 data->state = MAIN_CP_CB_DATA_STATE_LOGGER_SUBSYS;
586 list_init(&data->logger_subsys_items_head);
587 data->subsys = NULL;
588 }
589 if (strcmp(path, "logging.logging_daemon") == 0) {
590 data->state = MAIN_CP_CB_DATA_STATE_LOGGING_DAEMON;
591 list_init(&data->logger_subsys_items_head);
592 data->subsys = NULL;
593 data->logging_daemon_name = NULL;
594 }
595 if (strcmp(path, "uidgid") == 0) {
596 data->state = MAIN_CP_CB_DATA_STATE_UIDGID;
ae229831 597 }
8a45e2b1
JF
598 if (strcmp(path, "totem.interface.member") == 0) {
599 data->state = MAIN_CP_CB_DATA_STATE_MEMBER;
600 }
601 if (strcmp(path, "quorum") == 0) {
602 data->state = MAIN_CP_CB_DATA_STATE_QUORUM;
603 }
604 break;
605 case PARSER_CB_SECTION_END:
606 switch (data->state) {
607 case MAIN_CP_CB_DATA_STATE_NORMAL:
608 break;
609 case MAIN_CP_CB_DATA_STATE_INTERFACE:
610 /*
611 * Create new interface section
612 */
613 if (data->bindnetaddr != NULL) {
614 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.bindnetaddr",
615 data->ringnumber);
616 icmap_set_string(key_name, data->bindnetaddr);
617
618 free(data->bindnetaddr);
619 data->bindnetaddr = NULL;
620 } else {
621 *error_string = "No bindnetaddr for interface";
622
623 return (0);
624 }
625
626 if (data->mcastaddr != NULL) {
627 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.mcastaddr",
628 data->ringnumber);
629 icmap_set_string(key_name, data->mcastaddr);
630
631 free(data->mcastaddr);
632 data->mcastaddr = NULL;
633 }
634
635 if (data->broadcast != NULL) {
636 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.broadcast",
637 data->ringnumber);
638 icmap_set_string(key_name, data->broadcast);
639
640 free(data->broadcast);
641 data->broadcast = NULL;
642 }
643
644 if (data->mcastport > -1) {
645 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.mcastport",
646 data->ringnumber);
647 icmap_set_uint16(key_name, data->mcastport);
648 }
649
650 if (data->ttl > -1) {
651 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.ttl",
652 data->ringnumber);
653 icmap_set_uint8(key_name, data->ttl);
654 }
655
656 i = 0;
657 for (iter = data->member_items_head.next;
658 iter != &data->member_items_head; iter = iter_next) {
659 kv_item = list_entry(iter, struct key_value_list_item, list);
660
661 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.member.%u",
662 data->ringnumber, i);
663 icmap_set_string(key_name, kv_item->value);
664
665 iter_next = iter->next;
666
667 free(kv_item->value);
668 free(kv_item->key);
669 free(kv_item);
670 i++;
671 }
672
673 data->state = MAIN_CP_CB_DATA_STATE_TOTEM;
674 break;
675 case MAIN_CP_CB_DATA_STATE_TOTEM:
676 data->state = MAIN_CP_CB_DATA_STATE_NORMAL;
677 break;
678 case MAIN_CP_CB_DATA_STATE_LOGGER_SUBSYS:
679 if (data->subsys == NULL) {
680 *error_string = "No subsys key in logger_subsys directive";
681
682 return (0);
683 }
684
685 for (iter = data->logger_subsys_items_head.next;
686 iter != &data->logger_subsys_items_head; iter = iter_next) {
687 kv_item = list_entry(iter, struct key_value_list_item, list);
688
689 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logger_subsys.%s.%s",
690 data->subsys, kv_item->key);
691 icmap_set_string(key_name, kv_item->value);
692
693 iter_next = iter->next;
694
695 free(kv_item->value);
696 free(kv_item->key);
697 free(kv_item);
698 }
699
700 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logger_subsys.%s.subsys",
701 data->subsys);
702 icmap_set_string(key_name, data->subsys);
703
704 free(data->subsys);
705
706 data->state = MAIN_CP_CB_DATA_STATE_NORMAL;
707 break;
708 case MAIN_CP_CB_DATA_STATE_LOGGING_DAEMON:
709 if (data->logging_daemon_name == NULL) {
710 *error_string = "No name key in logging_daemon directive";
711
712 return (0);
713 }
714
715 for (iter = data->logger_subsys_items_head.next;
716 iter != &data->logger_subsys_items_head; iter = iter_next) {
717 kv_item = list_entry(iter, struct key_value_list_item, list);
718
719 if (data->subsys == NULL) {
720 if (strcmp(data->logging_daemon_name, "corosync") == 0) {
721 snprintf(key_name, ICMAP_KEYNAME_MAXLEN,
722 "logging.%s",
723 kv_item->key);
724 } else {
725 snprintf(key_name, ICMAP_KEYNAME_MAXLEN,
726 "logging.logging_daemon.%s.%s",
727 data->logging_daemon_name, kv_item->key);
728 }
729 } else {
730 if (strcmp(data->logging_daemon_name, "corosync") == 0) {
731 snprintf(key_name, ICMAP_KEYNAME_MAXLEN,
732 "logging.logger_subsys.%s.%s",
733 data->subsys,
734 kv_item->key);
735 } else {
736 snprintf(key_name, ICMAP_KEYNAME_MAXLEN,
737 "logging.logging_daemon.%s.%s.%s",
738 data->logging_daemon_name, data->subsys,
739 kv_item->key);
740 }
741 }
742 icmap_set_string(key_name, kv_item->value);
743
744 iter_next = iter->next;
745
746 free(kv_item->value);
747 free(kv_item->key);
748 free(kv_item);
749 }
750
751 if (data->subsys == NULL) {
752 if (strcmp(data->logging_daemon_name, "corosync") != 0) {
753 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logging_daemon.%s.name",
754 data->logging_daemon_name);
755 icmap_set_string(key_name, data->logging_daemon_name);
756 }
757 } else {
758 if (strcmp(data->logging_daemon_name, "corosync") == 0) {
759 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logger_subsys.%s.subsys",
760 data->subsys);
761 icmap_set_string(key_name, data->subsys);
762
763 } else {
764 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logging_daemon.%s.%s.subsys",
765 data->logging_daemon_name, data->subsys);
766 icmap_set_string(key_name, data->subsys);
767 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logging_daemon.%s.%s.name",
768 data->logging_daemon_name, data->subsys);
769 icmap_set_string(key_name, data->logging_daemon_name);
770 }
771 }
772
773 free(data->subsys);
774 free(data->logging_daemon_name);
775
776 data->state = MAIN_CP_CB_DATA_STATE_NORMAL;
777 break;
778 case MAIN_CP_CB_DATA_STATE_UIDGID:
779 data->state = MAIN_CP_CB_DATA_STATE_UIDGID;
780 break;
781 case MAIN_CP_CB_DATA_STATE_MEMBER:
782 data->state = MAIN_CP_CB_DATA_STATE_INTERFACE;
783 break;
784 case MAIN_CP_CB_DATA_STATE_QUORUM:
785 data->state = MAIN_CP_CB_DATA_STATE_NORMAL;
786 break;
787 }
788 break;
ae229831
JF
789 }
790
8a45e2b1
JF
791 return (1);
792}
793
794static int uidgid_config_parser_cb(const char *path,
795 char *key,
796 char *value,
797 enum parser_cb_type type,
798 const char **error_string,
799 void *user_data)
800{
801 char key_name[ICMAP_KEYNAME_MAXLEN];
802 int uid, gid;
803
804 switch (type) {
805 case PARSER_CB_START:
806 break;
807 case PARSER_CB_END:
808 break;
809 case PARSER_CB_ITEM:
810 if (strcmp(path, "uidgid.uid") == 0) {
811 uid = uid_determine(value);
812 if (uid == -1) {
813 *error_string = error_string_response;
814 return (0);
815 }
816 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "uidgid.uid.%u",
817 uid);
818 icmap_set_uint8(key_name, 1);
819 } else if (strcmp(key, "uidgid.gid") == 0) {
820 gid = gid_determine(value);
821 if (gid == -1) {
822 *error_string = error_string_response;
823 return (0);
824 }
825 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "uidgid.gid.%u",
826 gid);
827 icmap_set_uint8(key_name, 1);
828 } else {
ae229831 829 *error_string = "uidgid: Only uid and gid are allowed items";
8a45e2b1 830 return (0);
ae229831 831 }
8a45e2b1
JF
832 break;
833 case PARSER_CB_SECTION_START:
834 if (strcmp(path, "uidgid") != 0) {
835 *error_string = "uidgid: Can't add subsection different then uidgid";
836 return (0);
837 };
838 break;
839 case PARSER_CB_SECTION_END:
840 break;
ae229831 841 }
2f552719 842
8a45e2b1 843 return (1);
ae229831
JF
844}
845
8a45e2b1 846static int read_uidgid_files_into_icmap(
ae229831
JF
847 const char **error_string)
848{
849 FILE *fp;
850 const char *dirname;
851 DIR *dp;
852 struct dirent *dirent;
2290913d 853 struct dirent *entry;
1bd8aba6 854 char filename[PATH_MAX + FILENAME_MAX + 1];
ae229831 855 int res = 0;
2290913d
AS
856 size_t len;
857 int return_code;
1e0d40cd 858 struct stat stat_buf;
8a45e2b1 859 char key_name[ICMAP_KEYNAME_MAXLEN];
ae229831 860
2135d91c 861 dirname = COROSYSCONFDIR "/uidgid.d";
ae229831
JF
862 dp = opendir (dirname);
863
864 if (dp == NULL)
865 return 0;
866
eda1e364
JF
867 len = offsetof(struct dirent, d_name) + NAME_MAX + 1;
868
2290913d 869 entry = malloc(len);
eda1e364 870 if (entry == NULL) {
c2a39cb8
JF
871 res = 0;
872 goto error_exit;
eda1e364 873 }
2290913d
AS
874
875 for (return_code = readdir_r(dp, entry, &dirent);
876 dirent != NULL && return_code == 0;
877 return_code = readdir_r(dp, entry, &dirent)) {
878
1e0d40cd
SD
879 snprintf(filename, sizeof (filename), "%s/%s", dirname, dirent->d_name);
880 stat (filename, &stat_buf);
881 if (S_ISREG(stat_buf.st_mode)) {
ae229831
JF
882
883 fp = fopen (filename, "r");
884 if (fp == NULL) continue;
885
8a45e2b1
JF
886 key_name[0] = 0;
887
888 res = parse_section(fp, key_name, error_string, uidgid_config_parser_cb, NULL);
ae229831
JF
889
890 fclose (fp);
891
892 if (res != 0) {
893 goto error_exit;
894 }
895 }
896 }
897
898error_exit:
2290913d 899 free (entry);
ae229831
JF
900 closedir(dp);
901
902 return res;
903}
2f552719 904
8a45e2b1
JF
905/* Read config file and load into icmap */
906static int read_config_file_into_icmap(
23c64c64 907 const char **error_string)
2f552719
SD
908{
909 FILE *fp;
23c64c64 910 const char *filename;
2f552719
SD
911 char *error_reason = error_string_response;
912 int res;
8a45e2b1
JF
913 char key_name[ICMAP_KEYNAME_MAXLEN];
914 struct main_cp_cb_data data;
2f552719
SD
915
916 filename = getenv ("COROSYNC_MAIN_CONFIG_FILE");
917 if (!filename)
2135d91c 918 filename = COROSYSCONFDIR "/corosync.conf";
2f552719
SD
919
920 fp = fopen (filename, "r");
23c64c64 921 if (fp == NULL) {
20f3331d 922 char error_str[100];
37e17e7a 923 const char *error_ptr = qb_strerror_r(errno, error_str, sizeof(error_str));
870046d0
SD
924 snprintf (error_reason, sizeof(error_string_response),
925 "Can't read file %s reason = (%s)\n",
00434a4f 926 filename, error_ptr);
2f552719
SD
927 *error_string = error_reason;
928 return -1;
929 }
930
8a45e2b1
JF
931 key_name[0] = 0;
932
933 res = parse_section(fp, key_name, error_string, main_config_parser_cb, &data);
2f552719
SD
934
935 fclose(fp);
936
ae229831 937 if (res == 0) {
8a45e2b1 938 res = read_uidgid_files_into_icmap(error_string);
ae229831
JF
939 }
940
94b64352
JF
941 if (res == 0) {
942 snprintf (error_reason, sizeof(error_string_response),
870046d0 943 "Successfully read main configuration file '%s'.\n", filename);
94b64352
JF
944 *error_string = error_reason;
945 }
2f552719
SD
946
947 return res;
948}