1 /*
2 Copyright (c) 2002-2005, Miguel Mendez. All rights reserved.
3 Copyright (c) 2015, Chris Hutchinson. All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7
8 * Redistributions of source code must retain the above copyright notice,
9 this list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above copyright notice,
11 this list of conditions and the following disclaimer in the documentation
12 and/or other materials provided with the distribution.
13
14 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
18 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
25 $Id: parser.c 49 2015-11-09 11:42:43Z chrish $
26
27 */
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <fcntl.h>
33 #include <ctype.h>
34
35 #include "parser.h"
36
37 static int parseline(RC_NODE *);
38 int yylex(void);
39
40 static int tmp_knobs, tmp_strings;
41
42 /* RC_NODEs that look like knobs but aren't */
43
44 static char *except[] = { "swapfile" , "pccard_ifconfig", "nisdomainname",
45 "ip_portrange_first", "ip_portrange_last", "gif_interfaces",
46 "defaultrouter", "ipv6_defaultrouter", "keymap", "keyrate",
47 "keybell", "keychange", "cursor", "scrnmap", "font8x16",
48 "font8x14", "font8x8", "saver", "mousechar_start", "dumpdev",
49 "rand_irqs", "ipv6_default_interface", "ipv6_faith_prefix",
50 "isdn_fsdev", "isdn_screenflags", "amd_map_program",
51 "gbde_devices", "extra_netfs_types", "pcvt_keymap",
52 "pcvt_keydel", "pcvt_keyrate", "pcvt_lines",
53 "pcvt_blanktime", "pcvt_cursorh", "pcvt_cursorl", "sendmail_enable"
54 };
55
56
57 static int pending;
58
59 extern char *yytext;
60 extern FILE *yyin;
61
62 int
build_list(char * filename,RC_CONF * my_rc)63 build_list(char *filename, RC_CONF *my_rc)
64 {
65 RC_NODE scratch;
66 RC_NODE *alpha;
67 RC_NODE *current;
68 RC_NODE *old;
69 RC_NODE *foo, *bar;
70
71 int retval;
72
73 tmp_knobs = 0;
74 tmp_strings = 0;
75
76 alpha = malloc(sizeof(RC_NODE));
77 memset(alpha, 0, sizeof(RC_NODE));
78 current = alpha;
79 old = &scratch;
80
81 pending = 0;
82 retval = 0;
83
84 yyin = fopen(filename, "r");
85
86 /* First pass, build linked list of nodes */
87 do {
88
89 retval = parseline(current);
90 old = current;
91 current = malloc(sizeof(RC_NODE));
92 memset(current, 0, sizeof(RC_NODE));
93 old->next = current;
94 current->next = NULL;
95
96 } while (retval == 0);
97
98 /* Second pass, build knob and strings list */
99 if (tmp_knobs > 0) {
100
101 my_rc->knobs_ptr = malloc(tmp_knobs * sizeof(RC_NODE));
102 memset(my_rc->knobs_ptr, 0, (tmp_knobs * sizeof(RC_NODE)));
103
104 } else {
105
106 my_rc->knobs_ptr = malloc(sizeof(RC_NODE));
107 memset(my_rc->knobs_ptr, 0, (sizeof(RC_NODE)));
108
109 }
110
111 if (tmp_strings > 0) {
112
113 my_rc->string_ptr = malloc(tmp_strings * sizeof(RC_NODE));
114 memset(my_rc->string_ptr, 0, (tmp_strings * sizeof(RC_NODE)));
115
116 } else {
117
118 my_rc->string_ptr = malloc(sizeof(RC_NODE));
119 memset(my_rc->string_ptr, 0, (sizeof(RC_NODE)));
120
121 }
122
123 tmp_knobs = 0;
124 tmp_strings = 0;
125
126 /* Preserve original pointers */
127 foo = my_rc->knobs_ptr;
128 bar = my_rc->string_ptr;
129
130
131 current = alpha;
132 while (current->next != NULL) {
133
134 if (isalnum((int)*current->name)) {
135
136 if (current->knob == IS_KNOB) {
137
138 *foo = *current;
139 foo++;
140 tmp_knobs++;
141
142 } else {
143
144 *bar = *current;
145 bar++;
146 tmp_strings++;
147
148 }
149
150 }
151
152 current = current->next;
153
154 }
155
156 my_rc->knobs_size = tmp_knobs;
157 my_rc->string_size = tmp_strings;
158
159 fclose(yyin);
160 return 0;
161
162 }
163
164 static int
parseline(RC_NODE * current)165 parseline(RC_NODE *current)
166 {
167 char i;
168 int delta = 0,compos = 0;
169 int is_except = 0;
170 int foo;
171 int result = 1;
172
173 if (pending == 0) {
174
175 result = yylex();
176 if (result == 0) return(-1);
177
178 } else {
179
180 pending = 0;
181
182 }
183
184 delta = 0;
185 i = yytext[delta];
186
187 while (i != '=') {
188
189 current->name[delta] = i;
190 delta++;
191 i = yytext[delta];
192 }
193
194 current->name[delta] = (char) 0;
195
196 /* Exception list */
197 for (foo=0; foo < (sizeof(except)/sizeof(char *)); foo++) {
198
199 if (!strncmp(current->name, except[foo], 255)) {
200
201 is_except = 1;
202 break;
203
204 }
205 }
206
207
208 result = yylex();
209 if (result == 0) return(-1);
210
211 /* Check for KNOB_YES or KNOB_NO */
212 if (!strncmp(yytext, KNOB_YES, strlen(KNOB_YES))) {
213
214 current->knob = IS_KNOB;
215 current->knob_val = KNOB_IS_YES;
216 current->knob_orig = KNOB_IS_YES;
217 current->modified = MODIFIED_NO;
218 tmp_knobs++;
219
220 } else if (!strncmp(yytext, KNOB_NO, strlen(KNOB_NO)) && is_except == 0) {
221
222 current->knob = IS_KNOB;
223 current->knob_val = KNOB_IS_NO;
224 current->knob_orig = KNOB_IS_NO;
225 current->modified = MODIFIED_NO;
226 tmp_knobs++;
227
228 } else {
229
230 current->knob = NOT_KNOB;
231 delta = 0;
232 i = yytext[delta];
233 current->value[delta] = i;
234 current->orig[delta] = i;
235 delta++;
236
237 i = yytext[delta];
238
239 while (i != '"' && i != '\n' && i != (char) 0) {
240
241 current->value[delta] = i;
242 current->orig[delta] = i;
243 delta++;
244 i = yytext[delta];
245
246 }
247
248 current->value[delta] = (char) '"';
249 current->orig[delta] = (char) '"';
250 current->value[delta+1] = (char) 0;
251 current->orig[delta+1] = (char) 0;
252 current->modified = MODIFIED_NO;
253 tmp_strings++;
254
255 }
256
257
258 result = yylex();
259 if (result == 0) return(-1);
260 i = *yytext;
261 delta = 0;
262 if (i == '#') {
263
264 compos = 0;
265 delta++;
266 i = yytext[delta];
267 while (i != '\n') {
268
269 current->comment[compos] = i;
270 delta++;
271 compos++;
272 i = yytext[delta];
273
274 }
275
276 current->comment[compos] = (char) 0;
277
278 } else {
279
280 pending = 1;
281
282 }
283
284 return(0);
285
286 }
287
288 /*
289 * merge_lists receives two tuples of lists and merges the pairs, overriding the
290 * defaults list with the values in the rc list. It also allocates extra space
291 * for possible user additions.
292 */
293 int
merge_lists(RC_CONF * my_rc_defaults,RC_CONF * my_rc)294 merge_lists(RC_CONF *my_rc_defaults, RC_CONF *my_rc)
295 {
296 RC_NODE *rc_knobs_final;
297 RC_NODE *rc_str_final;
298 RC_NODE *baz, *bar, *aux;
299 int total_nodes;
300 int foo, j, k, asize;
301 int node_present;
302
303 total_nodes = my_rc_defaults->knobs_size;
304
305 asize = (my_rc_defaults->knobs_size + my_rc->knobs_size) * 2;
306
307 #ifdef VERBOSE_CONSOLE
308 printf("Allocated %i bytes for %i knobs.\n", asize * sizeof(RC_NODE), total_nodes);
309 #endif
310
311 /* merge knobs */
312 rc_knobs_final = malloc(asize * sizeof(RC_NODE));
313 memset(rc_knobs_final, 0, (asize * sizeof(RC_NODE)));
314
315 memcpy(rc_knobs_final, my_rc_defaults->knobs_ptr,
316 my_rc_defaults->knobs_size * sizeof(RC_NODE));
317
318 baz = my_rc->knobs_ptr;
319 bar = rc_knobs_final;
320
321 for (j = 0; j<total_nodes; j++) {
322
323 baz = my_rc->knobs_ptr;
324 for (foo = 0; foo < my_rc->knobs_size; foo++) {
325
326 if (!strncmp(bar->name, baz->name, 255)) {
327 #ifdef VERBOSE_CONSOLE
328 printf("Overridden---> %s\n", bar->name);
329 #endif
330 bar->knob_val = baz->knob_val;
331 bar->knob_orig = baz->knob_orig;
332
333 }
334
335 baz++;
336
337 }
338
339 bar++;
340
341 }
342
343 /* add values present in rc.conf but not in the defaults file */
344 total_nodes = my_rc_defaults->knobs_size;
345 baz = my_rc->knobs_ptr;
346
347 for (j = 0; j < my_rc->knobs_size; j++) {
348
349 node_present = 0;
350 bar = my_rc_defaults->knobs_ptr;
351
352 for (k = 0; k < my_rc_defaults->knobs_size; k++) {
353
354 if (!strncmp(baz->name, bar->name, 255)) node_present = 1;
355 bar++;
356
357 }
358
359 aux = rc_knobs_final;
360 for (k = 0; k < total_nodes; k++) {
361
362 if (!strncmp(baz->name, aux->name, 255)) {
363
364 #ifdef VERBOSE_CONSOLE
365 printf("Dupe -> %s\n", aux->name);
366 #endif
367 node_present = 1;
368 aux->knob_val = baz->knob_val;
369 aux->knob_orig = baz->knob_orig;
370
371 }
372
373 aux++;
374
375 }
376
377 if (node_present == 0) {
378
379 memcpy((rc_knobs_final+total_nodes), baz, sizeof(RC_NODE));
380 total_nodes++;
381
382 }
383
384 baz++;
385
386 }
387
388 my_rc_defaults->knobs_size = total_nodes;
389 my_rc_defaults->knobs_ptr = rc_knobs_final;
390
391 asize = (my_rc_defaults->string_size + my_rc->string_size) * 2;
392
393 #ifdef VERBOSE_CONSOLE
394 printf("Allocated %i bytes for strings.\n", asize * sizeof(RC_NODE));
395 #endif
396
397 /* merge strings */
398 rc_str_final = malloc(asize * sizeof(RC_NODE));
399 memset(rc_str_final, 0, (asize * sizeof(RC_NODE)));
400
401 memcpy(rc_str_final, my_rc_defaults->string_ptr,
402 my_rc_defaults->string_size * sizeof(RC_NODE));
403
404 baz = my_rc->string_ptr;
405 bar = rc_str_final;
406
407
408 for (j = 0; j < my_rc_defaults->string_size; j++) {
409
410 baz = my_rc->string_ptr;
411 for (foo = 0; foo < my_rc->string_size; foo++) {
412
413 if (!strncmp(bar->name, baz->name, 255)) {
414
415 #ifdef VERBOSE_CONSOLE
416 fprintf(stderr,"Overridden---> %s\n", bar->name);
417 #endif
418 memset(bar->value, 0, 255);
419 strncpy(bar->value, baz->value, 255);
420
421 memset(bar->orig, 0, 255);
422 strncpy(bar->orig, baz->orig, 255);
423
424 }
425
426 baz++;
427
428 }
429
430 bar++;
431
432 }
433
434 /* add values present in rc.conf but not in the defaults file */
435 total_nodes = my_rc_defaults->string_size;
436
437 baz = my_rc->string_ptr;
438 for (j = 0; j < my_rc->string_size; j++) {
439
440 node_present = 0;
441 bar = my_rc_defaults->string_ptr;
442
443 for (k = 0; k < my_rc_defaults->string_size; k++) {
444
445 if (!strncmp(baz->name, bar->name, 255)) node_present=1;
446 bar++;
447
448 }
449
450
451 aux = rc_str_final;
452 for (k=0; k < total_nodes; k++) {
453
454 if (!strncmp(baz->name, aux->name, 255)) {
455
456 #ifdef VERBOSE_CONSOLE
457 printf("Dupe -> %s\n", aux->name);
458 #endif
459
460 node_present = 1;
461 strncpy(aux->value, baz->value, 255);
462 strncpy(aux->orig, baz->orig, 255);
463
464 }
465
466 aux++;
467
468 }
469
470
471 if (node_present == 0) {
472
473 #ifdef VERBOSE_CONSOLE
474 printf("Adding new string: %s\n", baz->name);
475 #endif
476 memcpy((rc_str_final+total_nodes), baz,sizeof(RC_NODE));
477 total_nodes++;
478 }
479
480 baz++;
481
482 }
483
484 my_rc_defaults->string_size = total_nodes;
485 my_rc_defaults->string_ptr = rc_str_final;
486
487 /* everything went ok */
488 return 0;
489
490 }
491
492 void
list_sort(RC_NODE * rc_data,int num)493 list_sort(RC_NODE *rc_data, int num)
494 {
495 int i, j, retval, changed;
496 RC_NODE *list;
497 RC_NODE temp;
498
499 list = rc_data;
500
501 do {
502
503 changed = 0;
504 for (i = 0; i < num-1; i++) {
505 for (j = i; j < num-1-i; j++) {
506
507 retval = strncmp(list[j].name, list[j+1].name, 255);
508
509 if (retval >= 1) {
510 #ifdef VERBOSE_CONSOLE
511 printf("Sorting: %s (%x) > %s (%x)\n", list[j].name, list+j,
512 list[j+1].name, list+j+1);
513 #endif
514 memcpy(&temp, (list+j), sizeof(RC_NODE));
515 memcpy((list+j), (list+j+1), sizeof(RC_NODE));
516 memcpy((list+j+1), &temp, sizeof(RC_NODE));
517 changed = 1;
518 }
519 }
520 }
521
522 } while (changed == 1);
523
524 }
525