1 %{
2 #include <crm_internal.h>
3 
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <assert.h>
8 #include <crm/crm.h>
9 #include <standalone_config.h>
10 
11 extern int _line_count;
12 extern int yylex (void);
13 extern void yyset_in  (FILE * in_str  );
14 int yyerror(const char *foo);
15 static void handle_line_value(void);
16 static void reset_line(void);
17 static void add_line_value(char *key, char *val);
18 
19 enum line_type {
20 	STANDALONE_LINE_DEVICE = 0,
21 	STANDALONE_LINE_OPTION,
22 	STANDALONE_LINE_PRIORITY,
23 	STANDALONE_LINE_PORT
24 };
25 
26 static struct {
27 	enum line_type type;
28 	char *name;
29 	char *agent;
30 	char *keys[STANDALONE_CFG_MAX_KEYVALS];
31 	char *vals[STANDALONE_CFG_MAX_KEYVALS];
32 	int val_count;
33 	unsigned int priority;
34 } line_val = { 0, };
35 
36 %}
37 
38 %token <sval> T_VAL
39 %token T_DEVICE T_CONNECT T_PORTMAP T_PRIO
40 %token T_EQ T_ENDL T_UNFENCE T_OPTIONS
41 %left T_VAL
42 
43 %start stuff
44 
45 %union {
46 	char *sval;
47 	int ival;
48 }
49 
50 %%
51 
52 devline:
53 	T_DEVICE T_VAL T_VAL T_ENDL {
54 		line_val.name = $2;
55 		line_val.agent = $3;
56 		line_val.type = STANDALONE_LINE_DEVICE;
57 		handle_line_value();
58 	} |
59 	T_DEVICE T_VAL T_VAL assigns T_ENDL {
60 		line_val.name = $2;
61 		line_val.agent = $3;
62 		line_val.type = STANDALONE_LINE_DEVICE;
63 		handle_line_value();
64 	}
65 	;
66 
67 optline:
68 	T_OPTIONS T_VAL assigns T_ENDL {
69 		line_val.name = $2;
70 		line_val.type = STANDALONE_LINE_OPTION;
71 		handle_line_value();
72 	}
73 	;
74 
75 prioline:
76 	T_PRIO T_VAL T_VAL vals T_ENDL {
77 		int priority = crm_atoi($3, NULL);
78 
79 		if (priority != -1) {
80 			line_val.name = $2;
81 			line_val.priority = priority;
82 			line_val.type = STANDALONE_LINE_PRIORITY;
83 			handle_line_value();
84 		} else {
85 			crm_err("Standalone Config parser error: priority value, %s, on line %d is not a valid positive integer", $3, _line_count);
86 			reset_line();
87 		}
88 	}
89 	;
90 
91 portline:
92 	T_PORTMAP T_VAL portinfo T_ENDL {
93 		line_val.name = $2;
94 		line_val.type = STANDALONE_LINE_PORT;
95 		handle_line_value();
96 	}
97 	;
98 
99 val:
100 	T_VAL {
101 		add_line_value(NULL, $1);
102 	}
103 	;
104 
105 vals:
106 	vals val |
107 	val
108 	;
109 
110 portinfo:
111 	assigns |
112 	vals
113 	;
114 
115 assign:
116 	T_VAL T_EQ T_VAL {
117 		add_line_value($1, $3);
118 	}
119 	;
120 
121 assigns:
122 	assigns assign |
123 	assign
124 	;
125 
126 stuff:
127 	T_ENDL stuff |
128 	//unfline stuff |
129 	devline stuff |
130 	portline stuff |
131 	optline stuff |
132 	prioline stuff |
133 	//unfline |
134 	portline |
135 	devline |
136 	optline |
137 	prioline |
138 	T_ENDL
139 	;
140 
141 %%
142 
143 int
144 yyerror(const char *foo)
145 {
146 	crm_err("Standalone Config parser error: %s on line %d", foo, _line_count);
147 	return 0;
148 }
149 
150 static void
add_line_value(char * key,char * val)151 add_line_value(char *key, char *val)
152 {
153 	if (line_val.val_count < STANDALONE_CFG_MAX_KEYVALS) {
154 		line_val.keys[line_val.val_count] = key;
155 		line_val.vals[line_val.val_count] = val;
156 		line_val.val_count++;
157 	}
158 }
159 
160 static void
reset_line()161 reset_line()
162 {
163 	int i;
164 	crm_free(line_val.name);
165 	crm_free(line_val.agent);
166 
167 	for (i = 0; i < line_val.val_count; i++) {
168 		crm_free(line_val.keys[i]);
169 		crm_free(line_val.vals[i]);
170 	}
171 
172 	memset(&line_val, 0, sizeof(line_val));
173 }
174 
175 static void
handle_line_value(void)176 handle_line_value(void)
177 {
178 	int i;
179 	int res = 0;
180 
181 	switch (line_val.type) {
182 	case STANDALONE_LINE_DEVICE:
183 		res |= standalone_cfg_add_device(line_val.name, line_val.agent);
184 		/* fall through */
185 	case STANDALONE_LINE_OPTION:
186 		for (i = 0; i < line_val.val_count; i++) {
187 			res |= standalone_cfg_add_device_options(line_val.name,
188 				line_val.keys[i],
189 				line_val.vals[i]);
190 		}
191 		break;
192 	case STANDALONE_LINE_PRIORITY:
193 		for (i = 0; i < line_val.val_count; i++) {
194 			res |= standalone_cfg_add_node_priority(line_val.name,
195 				line_val.vals[i], /* fence device name */
196 				line_val.priority);
197 		}
198 		break;
199 	case STANDALONE_LINE_PORT:
200 		for (i = 0; i < line_val.val_count; i++) {
201 			if (line_val.keys[i]) {
202 				res |= standalone_cfg_add_node(line_val.keys[i],
203 					line_val.name,
204 					line_val.vals[i]);
205 			} else {
206 				/* if value only, that means it is just a node name */
207 				res |= standalone_cfg_add_node(line_val.vals[i],
208 					line_val.name,
209 					NULL);
210 			}
211 		}
212 		break;
213 	}
214 
215 	if (res) {
216 		crm_err("Standalone Config parser error on line %d", _line_count);
217 	}
218 	reset_line();
219 }
220 
221 int
standalone_cfg_read_file(const char * file_path)222 standalone_cfg_read_file(const char *file_path)
223 {
224 	FILE *fp = fopen(file_path, "r");
225 
226 	if (!fp) {
227 		return -1;
228 	}
229 
230 	/* redirect parse input from stdin to our file */
231 	yyset_in(fp);
232 	yyparse();
233 	fclose(fp);
234 
235 	return 0;
236 }
237 
238