1 /*      $Id: config_file.c,v 5.34 2010/07/11 03:28:21 jarodwilson Exp $      */
2 
3 /****************************************************************************
4  ** config_file.c ***********************************************************
5  ****************************************************************************
6  *
7  * config_file.c - parses the config file of lircd
8  *
9  * Copyright (C) 1998 Pablo d'Angelo <pablo@ag-trek.allgaeu.org>
10  *
11  */
12 
13 #ifdef HAVE_CONFIG_H
14 # include <config.h>
15 #endif
16 
17 #include <errno.h>
18 #include <limits.h>
19 #include <unistd.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <libgen.h>
24 #include <sys/socket.h>
25 #include <sys/un.h>
26 #include <sys/stat.h>
27 #include <sys/types.h>
28 #include <fcntl.h>
29 #include <ctype.h>
30 
31 #include "lircd.h"
32 #include "ir_remote.h"
33 #include "config_file.h"
34 #include "transmit.h"
35 
36 #define LINE_LEN 1024
37 #define MAX_INCLUDES 10
38 
39 const char *whitespace = " \t";
40 
41 static int line;
42 static int parse_error;
43 
44 static struct ir_remote *read_config_recursive(FILE * f, const char *name, int depth);
45 static void calculate_signal_lengths(struct ir_remote *remote);
46 
init_void_array(struct void_array * ar,size_t chunk_size,size_t item_size)47 void **init_void_array(struct void_array *ar, size_t chunk_size, size_t item_size)
48 {
49 	ar->chunk_size = chunk_size;
50 	ar->item_size = item_size;
51 	ar->nr_items = 0;
52 	if (!(ar->ptr = calloc(chunk_size, ar->item_size))) {
53 		logprintf(LOG_ERR, "out of memory");
54 		parse_error = 1;
55 		return (NULL);
56 	}
57 	return (ar->ptr);
58 }
59 
add_void_array(struct void_array * ar,void * dataptr)60 int add_void_array(struct void_array *ar, void *dataptr)
61 {
62 	void *ptr;
63 
64 	if ((ar->nr_items % ar->chunk_size) == (ar->chunk_size) - 1) {
65 		/* I hope this works with the right alignment,
66 		   if not we're screwed */
67 		if (!(ptr = realloc(ar->ptr, ar->item_size * ((ar->nr_items) + (ar->chunk_size + 1))))) {
68 			logprintf(LOG_ERR, "out of memory");
69 			parse_error = 1;
70 			return (0);
71 		}
72 		ar->ptr = ptr;
73 	}
74 	memcpy((ar->ptr) + (ar->item_size * ar->nr_items), dataptr, ar->item_size);
75 	ar->nr_items = (ar->nr_items) + 1;
76 	memset((ar->ptr) + (ar->item_size * ar->nr_items), 0, ar->item_size);
77 	return (1);
78 }
79 
get_void_array(struct void_array * ar)80 inline void *get_void_array(struct void_array *ar)
81 {
82 	return (ar->ptr);
83 }
84 
s_malloc(size_t size)85 void *s_malloc(size_t size)
86 {
87 	void *ptr;
88 	if ((ptr = malloc(size)) == NULL) {
89 		logprintf(LOG_ERR, "out of memory");
90 		parse_error = 1;
91 		return (NULL);
92 	}
93 	memset(ptr, 0, size);
94 	return (ptr);
95 }
96 
s_strdup(char * string)97 inline char *s_strdup(char *string)
98 {
99 	char *ptr;
100 	if (!(ptr = strdup(string))) {
101 		logprintf(LOG_ERR, "out of memory");
102 		parse_error = 1;
103 		return (NULL);
104 	}
105 	return (ptr);
106 }
107 
s_strtocode(const char * val)108 inline ir_code s_strtocode(const char *val)
109 {
110 	ir_code code = 0;
111 	char *endptr;
112 
113 	errno = 0;
114 	code = strtoull(val, &endptr, 0);
115 	if ((code == (__u64) - 1 && errno == ERANGE) || strlen(endptr) != 0 || strlen(val) == 0) {
116 		logprintf(LOG_ERR, "error in configfile line %d:", line);
117 		logprintf(LOG_ERR, "\"%s\": must be a valid (__u64) number", val);
118 		parse_error = 1;
119 		return (0);
120 	}
121 	return (code);
122 }
123 
s_strtou32(char * val)124 __u32 s_strtou32(char *val)
125 {
126 	__u32 n;
127 	char *endptr;
128 
129 	n = strtoul(val, &endptr, 0);
130 	if (!*val || *endptr) {
131 		logprintf(LOG_ERR, "error in configfile line %d:", line);
132 		logprintf(LOG_ERR, "\"%s\": must be a valid (__u32) number", val);
133 		parse_error = 1;
134 		return (0);
135 	}
136 	return (n);
137 }
138 
s_strtoi(char * val)139 int s_strtoi(char *val)
140 {
141 	char *endptr;
142 	long n;
143 	int h;
144 
145 	n = strtol(val, &endptr, 0);
146 	h = (int)n;
147 	if (!*val || *endptr || n != ((long)h)) {
148 		logprintf(LOG_ERR, "error in configfile line %d:", line);
149 		logprintf(LOG_ERR, "\"%s\": must be a valid (int) number", val);
150 		parse_error = 1;
151 		return (0);
152 	}
153 	return (h);
154 }
155 
s_strtoui(char * val)156 unsigned int s_strtoui(char *val)
157 {
158 	char *endptr;
159 	__u32 n;
160 	unsigned int h;
161 
162 	n = strtoul(val, &endptr, 0);
163 	h = (unsigned int)n;
164 	if (!*val || *endptr || n != ((__u32) h)) {
165 		logprintf(LOG_ERR, "error in configfile line %d:", line);
166 		logprintf(LOG_ERR, "\"%s\": must be a valid (unsigned int) number", val);
167 		parse_error = 1;
168 		return (0);
169 	}
170 	return (h);
171 }
172 
s_strtolirc_t(char * val)173 lirc_t s_strtolirc_t(char *val)
174 {
175 	__u32 n;
176 	lirc_t h;
177 	char *endptr;
178 
179 	n = strtoul(val, &endptr, 0);
180 	h = (lirc_t) n;
181 	if (!*val || *endptr || n != ((__u32) h)) {
182 		logprintf(LOG_ERR, "error in configfile line %d:", line);
183 		logprintf(LOG_ERR, "\"%s\": must be a valid (lirc_t) number", val);
184 		parse_error = 1;
185 		return (0);
186 	}
187 	if (h < 0) {
188 		logprintf(LOG_WARNING, "error in configfile line %d:", line);
189 		logprintf(LOG_WARNING, "\"%s\" is out of range", val);
190 	}
191 	return (h);
192 }
193 
checkMode(int is_mode,int c_mode,char * error)194 int checkMode(int is_mode, int c_mode, char *error)
195 {
196 	if (is_mode != c_mode) {
197 		logprintf(LOG_ERR, "fatal error in configfile line %d:", line);
198 		logprintf(LOG_ERR, "\"%s\" isn't valid at this position", error);
199 		parse_error = 1;
200 		return (0);
201 	}
202 	return (1);
203 }
204 
addSignal(struct void_array * signals,char * val)205 int addSignal(struct void_array *signals, char *val)
206 {
207 	unsigned int t;
208 
209 	t = s_strtoui(val);
210 	if (parse_error)
211 		return 0;
212 	if (!add_void_array(signals, &t))
213 		return 0;
214 
215 	return 1;
216 }
217 
defineCode(char * key,char * val,struct ir_ncode * code)218 struct ir_ncode *defineCode(char *key, char *val, struct ir_ncode *code)
219 {
220 	memset(code, 0, sizeof(*code));
221 	code->name = s_strdup(key);
222 	code->code = s_strtocode(val);
223 	LOGPRINTF(3, "      %-20s 0x%016llX", code->name, code->code);
224 	return (code);
225 }
226 
defineNode(struct ir_ncode * code,const char * val)227 struct ir_code_node *defineNode(struct ir_ncode *code, const char *val)
228 {
229 	struct ir_code_node *node;
230 
231 	node = s_malloc(sizeof(*node));
232 	if (node == NULL)
233 		return NULL;
234 
235 	node->code = s_strtocode(val);
236 	node->next = NULL;
237 
238 	LOGPRINTF(3, "                           0x%016llX", node->code);
239 
240 	if (code->current == NULL) {
241 		code->next = node;
242 		code->current = node;
243 	} else {
244 		code->current->next = node;
245 		code->current = node;
246 	}
247 	return node;
248 }
249 
parseFlags(char * val)250 int parseFlags(char *val)
251 {
252 	struct flaglist *flaglptr;
253 	int flags = 0;
254 	char *flag, *help;
255 
256 	flag = help = val;
257 	while (flag != NULL) {
258 		while (*help != '|' && *help != 0)
259 			help++;
260 		if (*help == '|') {
261 			*help = 0;
262 			help++;
263 		} else {
264 			help = NULL;
265 		}
266 
267 		flaglptr = all_flags;
268 		while (flaglptr->name != NULL) {
269 			if (strcasecmp(flaglptr->name, flag) == 0) {
270 				if (flaglptr->flag & IR_PROTOCOL_MASK && flags & IR_PROTOCOL_MASK) {
271 					logprintf(LOG_ERR, "error in configfile line %d:", line);
272 					logprintf(LOG_ERR, "multiple protocols given in flags: \"%s\"", flag);
273 					parse_error = 1;
274 					return (0);
275 				}
276 				flags = flags | flaglptr->flag;
277 				LOGPRINTF(3, "flag %s recognized", flaglptr->name);
278 				break;
279 			}
280 			flaglptr++;
281 		}
282 		if (flaglptr->name == NULL) {
283 			logprintf(LOG_ERR, "error in configfile line %d:", line);
284 			logprintf(LOG_ERR, "unknown flag: \"%s\"", flag);
285 			parse_error = 1;
286 			return (0);
287 		}
288 		flag = help;
289 	}
290 	LOGPRINTF(2, "flags value: %d", flags);
291 
292 	return (flags);
293 }
294 
defineRemote(char * key,char * val,char * val2,struct ir_remote * rem)295 int defineRemote(char *key, char *val, char *val2, struct ir_remote *rem)
296 {
297 	if ((strcasecmp("name", key)) == 0) {
298 		if (rem->name != NULL)
299 			free(rem->name);
300 		rem->name = s_strdup(val);
301 		LOGPRINTF(1, "parsing %s remote", val);
302 		return (1);
303 	}
304 #ifdef DYNCODES
305 	if ((strcasecmp("dyncodes_name", key)) == 0) {
306 		if (rem->dyncodes_name != NULL) {
307 			free(rem->dyncodes_name);
308 		}
309 		rem->dyncodes_name = s_strdup(val);
310 		return (1);
311 	}
312 #endif
313 	else if ((strcasecmp("bits", key)) == 0) {
314 		rem->bits = s_strtoi(val);
315 		return (1);
316 	} else if (strcasecmp("flags", key) == 0) {
317 		rem->flags |= parseFlags(val);
318 		return (1);
319 	} else if (strcasecmp("eps", key) == 0) {
320 		rem->eps = s_strtoi(val);
321 		return (1);
322 	} else if (strcasecmp("aeps", key) == 0) {
323 		rem->aeps = s_strtoi(val);
324 		return (1);
325 	} else if (strcasecmp("plead", key) == 0) {
326 		rem->plead = s_strtolirc_t(val);
327 		return (1);
328 	} else if (strcasecmp("ptrail", key) == 0) {
329 		rem->ptrail = s_strtolirc_t(val);
330 		return (1);
331 	} else if (strcasecmp("pre_data_bits", key) == 0) {
332 		rem->pre_data_bits = s_strtoi(val);
333 		return (1);
334 	} else if (strcasecmp("pre_data", key) == 0) {
335 		rem->pre_data = s_strtocode(val);
336 		return (1);
337 	} else if (strcasecmp("post_data_bits", key) == 0) {
338 		rem->post_data_bits = s_strtoi(val);
339 		return (1);
340 	} else if (strcasecmp("post_data", key) == 0) {
341 		rem->post_data = s_strtocode(val);
342 		return (1);
343 	} else if (strcasecmp("gap", key) == 0) {
344 		if (val2 != NULL) {
345 			rem->gap2 = s_strtou32(val2);
346 		}
347 		rem->gap = s_strtou32(val);
348 		return (val2 != NULL ? 2 : 1);
349 	} else if (strcasecmp("repeat_gap", key) == 0) {
350 		rem->repeat_gap = s_strtou32(val);
351 		return (1);
352 	}
353 	/* obsolete: use toggle_bit_mask instead */
354 	else if (strcasecmp("toggle_bit", key) == 0) {
355 		rem->toggle_bit = s_strtoi(val);
356 		return 1;
357 	} else if (strcasecmp("toggle_bit_mask", key) == 0) {
358 		rem->toggle_bit_mask = s_strtocode(val);
359 		return 1;
360 	} else if (strcasecmp("toggle_mask", key) == 0) {
361 		rem->toggle_mask = s_strtocode(val);
362 		return (1);
363 	} else if (strcasecmp("rc6_mask", key) == 0) {
364 		rem->rc6_mask = s_strtocode(val);
365 		return (1);
366 	} else if (strcasecmp("ignore_mask", key) == 0) {
367 		rem->ignore_mask = s_strtocode(val);
368 		return (1);
369 	}
370 	/* obsolete name */
371 	else if (strcasecmp("repeat_bit", key) == 0) {
372 		rem->toggle_bit = s_strtoi(val);
373 		return (1);
374 	} else if (strcasecmp("suppress_repeat", key) == 0) {
375 		rem->suppress_repeat = s_strtoi(val);
376 		return (1);
377 	} else if (strcasecmp("min_repeat", key) == 0) {
378 		rem->min_repeat = s_strtoi(val);
379 		return (1);
380 	} else if (strcasecmp("min_code_repeat", key) == 0) {
381 		rem->min_code_repeat = s_strtoi(val);
382 		return (1);
383 	} else if (strcasecmp("frequency", key) == 0) {
384 		rem->freq = s_strtoui(val);
385 		return (1);
386 	} else if (strcasecmp("duty_cycle", key) == 0) {
387 		rem->duty_cycle = s_strtoui(val);
388 		return (1);
389 	} else if (strcasecmp("baud", key) == 0) {
390 		rem->baud = s_strtoui(val);
391 		return (1);
392 	} else if (strcasecmp("serial_mode", key) == 0) {
393 		if (val[0] < '5' || val[0] > '9') {
394 			logprintf(LOG_ERR, "error in configfile line %d:", line);
395 			logprintf(LOG_ERR, "bad bit count");
396 			parse_error = 1;
397 			return 0;
398 		}
399 		rem->bits_in_byte = val[0] - '0';
400 		switch (toupper(val[1])) {
401 		case 'N':
402 			rem->parity = IR_PARITY_NONE;
403 			break;
404 		case 'E':
405 			rem->parity = IR_PARITY_EVEN;
406 			break;
407 		case 'O':
408 			rem->parity = IR_PARITY_ODD;
409 			break;
410 		default:
411 			logprintf(LOG_ERR, "error in configfile line %d:", line);
412 			logprintf(LOG_ERR, "unsupported parity mode");
413 			parse_error = 1;
414 			return 0;
415 		}
416 		if (strcmp(val + 2, "1.5") == 0) {
417 			rem->stop_bits = 3;
418 		} else {
419 			rem->stop_bits = s_strtoui(val + 2) * 2;
420 		}
421 		return (1);
422 	} else if (val2 != NULL) {
423 		if (strcasecmp("header", key) == 0) {
424 			rem->phead = s_strtolirc_t(val);
425 			rem->shead = s_strtolirc_t(val2);
426 			return (2);
427 		} else if (strcasecmp("three", key) == 0) {
428 			rem->pthree = s_strtolirc_t(val);
429 			rem->sthree = s_strtolirc_t(val2);
430 			return (2);
431 		} else if (strcasecmp("two", key) == 0) {
432 			rem->ptwo = s_strtolirc_t(val);
433 			rem->stwo = s_strtolirc_t(val2);
434 			return (2);
435 		} else if (strcasecmp("one", key) == 0) {
436 			rem->pone = s_strtolirc_t(val);
437 			rem->sone = s_strtolirc_t(val2);
438 			return (2);
439 		} else if (strcasecmp("zero", key) == 0) {
440 			rem->pzero = s_strtolirc_t(val);
441 			rem->szero = s_strtolirc_t(val2);
442 			return (2);
443 		} else if (strcasecmp("foot", key) == 0) {
444 			rem->pfoot = s_strtolirc_t(val);
445 			rem->sfoot = s_strtolirc_t(val2);
446 			return (2);
447 		} else if (strcasecmp("repeat", key) == 0) {
448 			rem->prepeat = s_strtolirc_t(val);
449 			rem->srepeat = s_strtolirc_t(val2);
450 			return (2);
451 		} else if (strcasecmp("pre", key) == 0) {
452 			rem->pre_p = s_strtolirc_t(val);
453 			rem->pre_s = s_strtolirc_t(val2);
454 			return (2);
455 		} else if (strcasecmp("post", key) == 0) {
456 			rem->post_p = s_strtolirc_t(val);
457 			rem->post_s = s_strtolirc_t(val2);
458 			return (2);
459 		}
460 	}
461 	if (val2) {
462 		logprintf(LOG_ERR, "error in configfile line %d:", line);
463 		logprintf(LOG_ERR, "unknown definiton: \"%s %s %s\"", key, val, val2);
464 	} else {
465 		logprintf(LOG_ERR, "error in configfile line %d:", line);
466 		logprintf(LOG_ERR, "unknown definiton or too few arguments: \"%s %s\"", key, val);
467 	}
468 	parse_error = 1;
469 	return (0);
470 }
471 
sanityChecks(struct ir_remote * rem)472 static int sanityChecks(struct ir_remote *rem)
473 {
474 	struct ir_ncode *codes;
475 	struct ir_code_node *node;
476 
477 	if (!rem->name) {
478 		logprintf(LOG_ERR, "you must specify a remote name");
479 		return 0;
480 	}
481 	if (rem->gap == 0) {
482 		logprintf(LOG_WARNING, "you should specify a valid gap value");
483 	}
484 	if (has_repeat_gap(rem) && is_const(rem)) {
485 		logprintf(LOG_WARNING, "repeat_gap will be ignored if CONST_LENGTH flag is set");
486 	}
487 
488 	if (is_raw(rem))
489 		return 1;
490 
491 	if ((rem->pre_data & gen_mask(rem->pre_data_bits)) != rem->pre_data) {
492 		logprintf(LOG_WARNING, "invalid pre_data found for %s", rem->name);
493 		rem->pre_data &= gen_mask(rem->pre_data_bits);
494 	}
495 	if ((rem->post_data & gen_mask(rem->post_data_bits)) != rem->post_data) {
496 		logprintf(LOG_WARNING, "invalid post_data found for %s", rem->name);
497 		rem->post_data &= gen_mask(rem->post_data_bits);
498 	}
499 	for (codes = rem->codes; codes->name != NULL; codes++) {
500 		if ((codes->code & gen_mask(rem->bits)) != codes->code) {
501 			logprintf(LOG_WARNING, "invalid code found for %s: %s", rem->name, codes->name);
502 			codes->code &= gen_mask(rem->bits);
503 		}
504 		for (node = codes->next; node != NULL; node = node->next) {
505 			if ((node->code & gen_mask(rem->bits)) != node->code) {
506 				logprintf(LOG_WARNING, "invalid code found for %s: %s", rem->name, codes->name);
507 				node->code &= gen_mask(rem->bits);
508 			}
509 		}
510 	}
511 
512 	return 1;
513 }
514 
sort_by_bit_count(struct ir_remote * remotes)515 struct ir_remote *sort_by_bit_count(struct ir_remote *remotes)
516 {
517 	struct ir_remote *top, *rem, *next, *prev, *scan;
518 
519 	rem = remotes;
520 	top = NULL;
521 	while (rem != NULL) {
522 		next = rem->next;
523 
524 		scan = top;
525 		prev = NULL;
526 		while (scan && bit_count(scan) <= bit_count(rem)) {
527 			prev = scan;
528 			scan = scan->next;
529 		}
530 		if (prev) {
531 			prev->next = rem;
532 		} else {
533 			top = rem;
534 		}
535 		if (scan) {
536 			rem->next = scan;
537 		} else {
538 			rem->next = NULL;
539 		}
540 
541 		rem = next;
542 	}
543 
544 	return top;
545 }
546 
lirc_parse_include(char * s)547 static const char *lirc_parse_include(char *s)
548 {
549 	char *last;
550 	size_t len;
551 
552 	len = strlen(s);
553 	if (len < 2) {
554 		return NULL;
555 	}
556 	last = s + len - 1;
557 	while (last > s && strchr(whitespace, *last) != NULL) {
558 		last--;
559 	}
560 	if (last <= s) {
561 		return NULL;
562 	}
563 	if (*s != '"' && *s != '<') {
564 		return NULL;
565 	}
566 	if (*s == '"' && *last != '"') {
567 		return NULL;
568 	} else if (*s == '<' && *last != '>') {
569 		return NULL;
570 	}
571 	*last = 0;
572 	memmove(s, s + 1, len - 2 + 1);	/* terminating 0 is copied, and
573 					   maybe more, but we don't care */
574 	return s;
575 }
576 
lirc_parse_relative(char * dst,size_t dst_size,const char * child,const char * current)577 static const char *lirc_parse_relative(char *dst, size_t dst_size, const char *child, const char *current)
578 {
579 	char *dir;
580 	size_t dirlen;
581 
582 	if (!current)
583 		return child;
584 
585 	/* Not a relative path */
586 	if (*child == '/')
587 		return child;
588 
589 	if (strlen(current) >= dst_size) {
590 		return NULL;
591 	}
592 	strcpy(dst, current);
593 	dir = dirname(dst);
594 	dirlen = strlen(dir);
595 	if (dir != dst) {
596 		memmove(dst, dir, dirlen + 1);
597 	}
598 
599 	if (dirlen + 1 + strlen(child) + 1 > dst_size) {
600 		return NULL;
601 	}
602 	strcat(dst, "/");
603 	strcat(dst, child);
604 
605 	return dst;
606 }
607 
read_config(FILE * f,const char * name)608 struct ir_remote *read_config(FILE * f, const char *name)
609 {
610 	return read_config_recursive(f, name, 0);
611 }
612 
read_config_recursive(FILE * f,const char * name,int depth)613 static struct ir_remote *read_config_recursive(FILE * f, const char *name, int depth)
614 {
615 	char buf[LINE_LEN + 1], *key, *val, *val2;
616 	int len, argc;
617 	struct ir_remote *top_rem = NULL, *rem = NULL;
618 	struct void_array codes_list, raw_codes, signals;
619 	struct ir_ncode raw_code = { NULL, 0, 0, NULL };
620 	struct ir_ncode name_code = { NULL, 0, 0, NULL };
621 	struct ir_ncode *code;
622 	int mode = ID_none;
623 
624 	line = 0;
625 	parse_error = 0;
626 	LOGPRINTF(2, "parsing '%s'", name);
627 
628 	while (fgets(buf, LINE_LEN, f) != NULL) {
629 		line++;
630 		len = strlen(buf);
631 		if (len == LINE_LEN && buf[len - 1] != '\n') {
632 			logprintf(LOG_ERR, "line %d too long in config file", line);
633 			parse_error = 1;
634 			break;
635 		}
636 
637 		if (len > 0) {
638 			len--;
639 			if (buf[len] == '\n')
640 				buf[len] = 0;
641 		}
642 		if (len > 0) {
643 			len--;
644 			if (buf[len] == '\r')
645 				buf[len] = 0;
646 		}
647 		/* ignore comments */
648 		if (buf[0] == '#') {
649 			continue;
650 		}
651 		key = strtok(buf, whitespace);
652 		/* ignore empty lines */
653 		if (key == NULL)
654 			continue;
655 		val = strtok(NULL, whitespace);
656 		if (val != NULL) {
657 			val2 = strtok(NULL, whitespace);
658 			LOGPRINTF(3, "\"%s\" \"%s\"", key, val);
659 			if (strcasecmp("include", key) == 0) {
660 				FILE *childFile;
661 				const char *childName;
662 				const char *fullPath;
663 				char result[FILENAME_MAX + 1];
664 
665 				if (depth > MAX_INCLUDES) {
666 					logprintf(LOG_ERR, "error opening child file defined at %s:%d", name, line);
667 					logprintf(LOG_ERR, "too many files included");
668 					parse_error = -1;
669 					break;
670 				}
671 
672 				childName = lirc_parse_include(val);
673 				if (!childName) {
674 					logprintf(LOG_ERR, "error parsing child file value defined at line %d:", line);
675 					logprintf(LOG_ERR, "invalid quoting");
676 					parse_error = -1;
677 					break;
678 				}
679 
680 				fullPath = lirc_parse_relative(result, sizeof(result), childName, name);
681 				if (!fullPath) {
682 					logprintf(LOG_ERR, "error composing relative file path defined at line %d:",
683 						  line);
684 					logprintf(LOG_ERR, "resulting path too long");
685 					parse_error = -1;
686 					break;
687 				}
688 
689 				childFile = fopen(fullPath, "r");
690 				if (childFile == NULL) {
691 					logprintf(LOG_ERR, "error opening child file '%s' defined at line %d:",
692 						  fullPath, line);
693 					logprintf(LOG_ERR, "ignoring this child file for now.");
694 				} else {
695 					int save_line = line;
696 
697 					if (!top_rem) {
698 						/* create first remote */
699 						LOGPRINTF(2, "creating first remote");
700 						rem = read_config_recursive(childFile, fullPath, depth + 1);
701 						if (rem != (void *)-1 && rem != NULL) {
702 							top_rem = rem;
703 						} else {
704 							rem = NULL;
705 						}
706 					} else {
707 						/* create new remote */
708 						LOGPRINTF(2, "creating next remote");
709 						rem->next = read_config_recursive(childFile, fullPath, depth + 1);
710 						if (rem->next != (void *)-1 && rem->next != NULL) {
711 							rem = rem->next;
712 						} else {
713 							rem->next = NULL;
714 						}
715 					}
716 					fclose(childFile);
717 					line = save_line;
718 				}
719 			} else if (strcasecmp("begin", key) == 0) {
720 				if (strcasecmp("codes", val) == 0) {
721 					/* init codes mode */
722 					LOGPRINTF(2, "    begin codes");
723 					if (!checkMode(mode, ID_remote, "begin codes"))
724 						break;
725 					if (rem->codes) {
726 						logprintf(LOG_ERR, "error in configfile line %d:", line);
727 						logprintf(LOG_ERR, "codes are already defined");
728 						parse_error = 1;
729 						break;
730 					}
731 
732 					init_void_array(&codes_list, 30, sizeof(struct ir_ncode));
733 					mode = ID_codes;
734 				} else if (strcasecmp("raw_codes", val) == 0) {
735 					/* init raw_codes mode */
736 					LOGPRINTF(2, "    begin raw_codes");
737 					if (!checkMode(mode, ID_remote, "begin raw_codes"))
738 						break;
739 					if (rem->codes) {
740 						logprintf(LOG_ERR, "error in configfile line %d:", line);
741 						logprintf(LOG_ERR, "codes are already defined");
742 						parse_error = 1;
743 						break;
744 					}
745 					set_protocol(rem, RAW_CODES);
746 					raw_code.code = 0;
747 					init_void_array(&raw_codes, 30, sizeof(struct ir_ncode));
748 					mode = ID_raw_codes;
749 				} else if (strcasecmp("remote", val) == 0) {
750 					/* create new remote */
751 					LOGPRINTF(1, "parsing remote");
752 					if (!checkMode(mode, ID_none, "begin remote"))
753 						break;
754 					mode = ID_remote;
755 					if (!top_rem) {
756 						/* create first remote */
757 						LOGPRINTF(2, "creating first remote");
758 						rem = top_rem = s_malloc(sizeof(struct ir_remote));
759 					} else {
760 						/* create new remote */
761 						LOGPRINTF(2, "creating next remote");
762 						rem->next = s_malloc(sizeof(struct ir_remote));;
763 						rem = rem->next;
764 					}
765 				} else if (mode == ID_codes) {
766 					code = defineCode(key, val, &name_code);
767 					while (!parse_error && val2 != NULL) {
768 						struct ir_code_node *node;
769 
770 						if (val2[0] == '#')
771 							break;	/* comment */
772 						node = defineNode(code, val2);
773 						val2 = strtok(NULL, whitespace);
774 					}
775 					code->current = NULL;
776 					add_void_array(&codes_list, code);
777 				} else {
778 					logprintf(LOG_ERR, "error in configfile line %d:", line);
779 					logprintf(LOG_ERR, "unknown section \"%s\"", val);
780 					parse_error = 1;
781 				}
782 				if (!parse_error && val2 != NULL) {
783 					logprintf(LOG_WARNING, "garbage after '%s' token in line %d ignored", val,
784 						  line);
785 				}
786 			} else if (strcasecmp("end", key) == 0) {
787 
788 				if (strcasecmp("codes", val) == 0) {
789 					/* end Codes mode */
790 					LOGPRINTF(2, "    end codes");
791 					if (!checkMode(mode, ID_codes, "end codes"))
792 						break;
793 					rem->codes = get_void_array(&codes_list);
794 					mode = ID_remote;	/* switch back */
795 
796 				} else if (strcasecmp("raw_codes", val) == 0) {
797 					/* end raw codes mode */
798 					LOGPRINTF(2, "    end raw_codes");
799 
800 					if (mode == ID_raw_name) {
801 						raw_code.signals = get_void_array(&signals);
802 						raw_code.length = signals.nr_items;
803 						if (raw_code.length % 2 == 0) {
804 							logprintf(LOG_ERR, "error in configfile line %d:", line);
805 							logprintf(LOG_ERR, "bad signal length");
806 							parse_error = 1;
807 						}
808 						if (!add_void_array(&raw_codes, &raw_code))
809 							break;
810 						mode = ID_raw_codes;
811 					}
812 					if (!checkMode(mode, ID_raw_codes, "end raw_codes"))
813 						break;
814 					rem->codes = get_void_array(&raw_codes);
815 					mode = ID_remote;	/* switch back */
816 				} else if (strcasecmp("remote", val) == 0) {
817 					/* end remote mode */
818 					LOGPRINTF(2, "end remote");
819 					/* print_remote(rem); */
820 					if (!checkMode(mode, ID_remote, "end remote"))
821 						break;
822 					if (!sanityChecks(rem)) {
823 						parse_error = 1;
824 						break;
825 					}
826 #                                       ifdef DYNCODES
827 					if (rem->dyncodes_name == NULL) {
828 						rem->dyncodes_name = s_strdup("unknown");
829 					}
830 					rem->dyncodes[0].name = rem->dyncodes_name;
831 					rem->dyncodes[1].name = rem->dyncodes_name;
832 #                                       endif
833 					/* not really necessary because we
834 					   clear the alloced memory */
835 					rem->next = NULL;
836 					rem->last_code = NULL;
837 					mode = ID_none;	/* switch back */
838 				} else if (mode == ID_codes) {
839 					code = defineCode(key, val, &name_code);
840 					while (!parse_error && val2 != NULL) {
841 						struct ir_code_node *node;
842 
843 						if (val2[0] == '#')
844 							break;	/* comment */
845 						node = defineNode(code, val2);
846 						val2 = strtok(NULL, whitespace);
847 					}
848 					code->current = NULL;
849 					add_void_array(&codes_list, code);
850 				} else {
851 					logprintf(LOG_ERR, "error in configfile line %d:", line);
852 					logprintf(LOG_ERR, "unknown section %s", val);
853 					parse_error = 1;
854 				}
855 				if (!parse_error && val2 != NULL) {
856 					logprintf(LOG_WARNING, "garbage after '%s'" " token in line %d ignored", val,
857 						  line);
858 				}
859 			} else {
860 				switch (mode) {
861 				case ID_remote:
862 					argc = defineRemote(key, val, val2, rem);
863 					if (!parse_error
864 					    && ((argc == 1 && val2 != NULL)
865 						|| (argc == 2 && val2 != NULL && strtok(NULL, whitespace) != NULL))) {
866 						logprintf(LOG_WARNING, "garbage after '%s'" " token in line %d ignored",
867 							  key, line);
868 					}
869 					break;
870 				case ID_codes:
871 					code = defineCode(key, val, &name_code);
872 					while (!parse_error && val2 != NULL) {
873 						struct ir_code_node *node;
874 
875 						if (val2[0] == '#')
876 							break;	/* comment */
877 						node = defineNode(code, val2);
878 						val2 = strtok(NULL, whitespace);
879 					}
880 					code->current = NULL;
881 					add_void_array(&codes_list, code);
882 					break;
883 				case ID_raw_codes:
884 				case ID_raw_name:
885 					if (strcasecmp("name", key) == 0) {
886 						LOGPRINTF(3, "Button: \"%s\"", val);
887 						if (mode == ID_raw_name) {
888 							raw_code.signals = get_void_array(&signals);
889 							raw_code.length = signals.nr_items;
890 							if (raw_code.length % 2 == 0) {
891 								logprintf(LOG_ERR, "error in configfile line %d:",
892 									  line);
893 								logprintf(LOG_ERR, "bad signal length");
894 								parse_error = 1;
895 							}
896 							if (!add_void_array(&raw_codes, &raw_code))
897 								break;
898 						}
899 						if (!(raw_code.name = s_strdup(val))) {
900 							break;
901 						}
902 						raw_code.code++;
903 						init_void_array(&signals, 50, sizeof(lirc_t));
904 						mode = ID_raw_name;
905 						if (!parse_error && val2 != NULL) {
906 							logprintf(LOG_WARNING,
907 								  "garbage after '%s'" " token in line %d ignored", key,
908 								  line);
909 						}
910 					} else {
911 						if (mode == ID_raw_codes) {
912 							logprintf(LOG_ERR, "no name for signal defined at line %d",
913 								  line);
914 							parse_error = 1;
915 							break;
916 						}
917 						if (!addSignal(&signals, key))
918 							break;
919 						if (!addSignal(&signals, val))
920 							break;
921 						if (val2) {
922 							if (!addSignal(&signals, val2)) {
923 								break;
924 							}
925 						}
926 						while ((val = strtok(NULL, whitespace))) {
927 							if (!addSignal(&signals, val))
928 								break;
929 						}
930 					}
931 					break;
932 				}
933 			}
934 		} else if (mode == ID_raw_name) {
935 			if (!addSignal(&signals, key)) {
936 				break;
937 			}
938 		} else {
939 			logprintf(LOG_ERR, "error in configfile line %d", line);
940 			parse_error = 1;
941 			break;
942 		}
943 		if (parse_error) {
944 			break;
945 		}
946 	}
947 	if (mode != ID_none) {
948 		switch (mode) {
949 		case ID_raw_name:
950 			if (raw_code.name != NULL) {
951 				free(raw_code.name);
952 				if (get_void_array(&signals) != NULL)
953 					free(get_void_array(&signals));
954 			}
955 		case ID_raw_codes:
956 			rem->codes = get_void_array(&raw_codes);
957 			break;
958 		case ID_codes:
959 			rem->codes = get_void_array(&codes_list);
960 			break;
961 		}
962 		if (!parse_error) {
963 			logprintf(LOG_ERR, "unexpected end of file");
964 			parse_error = 1;
965 		}
966 	}
967 	if (parse_error) {
968 		static int print_error = 1;
969 
970 		if (print_error) {
971 			logprintf(LOG_ERR, "reading of file '%s' failed", name);
972 			print_error = 0;
973 		}
974 		free_config(top_rem);
975 		if (depth == 0)
976 			print_error = 1;
977 		return ((void *)-1);
978 	}
979 	/* kick reverse flag */
980 	/* handle RC6 flag to be backwards compatible: previous RC-6
981 	   config files did not set rc6_mask */
982 	rem = top_rem;
983 	while (rem != NULL) {
984 		if ((!is_raw(rem)) && rem->flags & REVERSE) {
985 			struct ir_ncode *codes;
986 
987 			if (has_pre(rem)) {
988 				rem->pre_data = reverse(rem->pre_data, rem->pre_data_bits);
989 			}
990 			if (has_post(rem)) {
991 				rem->post_data = reverse(rem->post_data, rem->post_data_bits);
992 			}
993 			codes = rem->codes;
994 			while (codes->name != NULL) {
995 				codes->code = reverse(codes->code, rem->bits);
996 				codes++;
997 			}
998 			rem->flags = rem->flags & (~REVERSE);
999 			rem->flags = rem->flags | COMPAT_REVERSE;
1000 			/* don't delete the flag because we still need
1001 			   it to remain compatible with older versions
1002 			 */
1003 		}
1004 		if (rem->flags & RC6 && rem->rc6_mask == 0 && rem->toggle_bit > 0) {
1005 			int all_bits = bit_count(rem);
1006 
1007 			rem->rc6_mask = ((ir_code) 1) << (all_bits - rem->toggle_bit);
1008 		}
1009 		if (rem->toggle_bit > 0) {
1010 			int all_bits = bit_count(rem);
1011 
1012 			if (has_toggle_bit_mask(rem)) {
1013 				logprintf(LOG_WARNING, "%s uses both toggle_bit and toggle_bit_mask", rem->name);
1014 			} else {
1015 				rem->toggle_bit_mask = ((ir_code) 1) << (all_bits - rem->toggle_bit);
1016 			}
1017 			rem->toggle_bit = 0;
1018 		}
1019 		if (has_toggle_bit_mask(rem)) {
1020 			if (!is_raw(rem) && rem->codes) {
1021 				rem->toggle_bit_mask_state = (rem->codes->code & rem->toggle_bit_mask);
1022 				if (rem->toggle_bit_mask_state) {
1023 					/* start with state set to 0 for backwards compatibility */
1024 					rem->toggle_bit_mask_state ^= rem->toggle_bit_mask;
1025 				}
1026 			}
1027 		}
1028 		if (is_serial(rem)) {
1029 			lirc_t base;
1030 
1031 			if (rem->baud > 0) {
1032 				base = 1000000 / rem->baud;
1033 				if (rem->pzero == 0 && rem->szero == 0) {
1034 					rem->pzero = base;
1035 				}
1036 				if (rem->pone == 0 && rem->sone == 0) {
1037 					rem->sone = base;
1038 				}
1039 			}
1040 			if (rem->bits_in_byte == 0) {
1041 				rem->bits_in_byte = 8;
1042 			}
1043 		}
1044 		if (rem->min_code_repeat > 0) {
1045 			if (!has_repeat(rem) || rem->min_code_repeat > rem->min_repeat) {
1046 				logprintf(LOG_WARNING, "invalid min_code_repeat value");
1047 				rem->min_code_repeat = 0;
1048 			}
1049 		}
1050 		calculate_signal_lengths(rem);
1051 		rem = rem->next;
1052 	}
1053 
1054 	top_rem = sort_by_bit_count(top_rem);
1055 #       if defined(DEBUG) && !defined(DAEMONIZE)
1056 	/*fprint_remotes(stderr, top_rem); */
1057 #       endif
1058 	return (top_rem);
1059 }
1060 
calculate_signal_lengths(struct ir_remote * remote)1061 void calculate_signal_lengths(struct ir_remote *remote)
1062 {
1063 	if (is_const(remote)) {
1064 		remote->min_total_signal_length = min_gap(remote);
1065 		remote->max_total_signal_length = max_gap(remote);
1066 	} else {
1067 		remote->min_gap_length = min_gap(remote);
1068 		remote->max_gap_length = max_gap(remote);
1069 	}
1070 
1071 	lirc_t min_signal_length = 0, max_signal_length = 0;
1072 	lirc_t max_pulse = 0, max_space = 0;
1073 	int first_sum = 1;
1074 	struct ir_ncode *c = remote->codes;
1075 	int i;
1076 
1077 	while (c->name) {
1078 		struct ir_ncode code = *c;
1079 		struct ir_code_node *next = code.next;
1080 		int first = 1;
1081 		int repeat = 0;
1082 		do {
1083 			if (first) {
1084 				first = 0;
1085 			} else {
1086 				code.code = next->code;
1087 				next = next->next;
1088 			}
1089 			for (repeat = 0; repeat < 2; repeat++) {
1090 				if (init_sim(remote, &code, repeat)) {
1091 					lirc_t sum = send_buffer.sum;
1092 
1093 					if (sum) {
1094 						if (first_sum || sum < min_signal_length) {
1095 							min_signal_length = sum;
1096 						}
1097 						if (first_sum || sum > max_signal_length) {
1098 							max_signal_length = sum;
1099 						}
1100 						first_sum = 0;
1101 					}
1102 					for (i = 0; i < send_buffer.wptr; i++) {
1103 						if (i & 1) {	/* space */
1104 							if (send_buffer.data[i] > max_space) {
1105 								max_space = send_buffer.data[i];
1106 							}
1107 						} else {	/* pulse */
1108 
1109 							if (send_buffer.data[i] > max_pulse) {
1110 								max_pulse = send_buffer.data[i];
1111 							}
1112 						}
1113 					}
1114 				}
1115 			}
1116 		} while (next);
1117 		c++;
1118 	}
1119 	if (first_sum) {
1120 		/* no timing data, so assume gap is the actual total
1121 		   length */
1122 		remote->min_total_signal_length = min_gap(remote);
1123 		remote->max_total_signal_length = max_gap(remote);
1124 		remote->min_gap_length = min_gap(remote);
1125 		remote->max_gap_length = max_gap(remote);
1126 	} else if (is_const(remote)) {
1127 		if (remote->min_total_signal_length > max_signal_length) {
1128 			remote->min_gap_length = remote->min_total_signal_length - max_signal_length;
1129 		} else {
1130 			logprintf(LOG_WARNING, "min_gap_length is 0 for '%s' remote", remote->name);
1131 			remote->min_gap_length = 0;
1132 		}
1133 		if (remote->max_total_signal_length > min_signal_length) {
1134 			remote->max_gap_length = remote->max_total_signal_length - min_signal_length;
1135 		} else {
1136 			logprintf(LOG_WARNING, "max_gap_length is 0 for '%s' remote", remote->name);
1137 			remote->max_gap_length = 0;
1138 		}
1139 	} else {
1140 		remote->min_total_signal_length = min_signal_length + remote->min_gap_length;
1141 		remote->max_total_signal_length = max_signal_length + remote->max_gap_length;
1142 	}
1143 	LOGPRINTF(1, "lengths: %lu %lu %lu %lu", remote->min_total_signal_length, remote->max_total_signal_length,
1144 		  remote->min_gap_length, remote->max_gap_length);
1145 }
1146 
free_config(struct ir_remote * remotes)1147 void free_config(struct ir_remote *remotes)
1148 {
1149 	struct ir_remote *next;
1150 	struct ir_ncode *codes;
1151 
1152 	while (remotes != NULL) {
1153 		next = remotes->next;
1154 
1155 #               ifdef DYNCODES
1156 		if (remotes->dyncodes_name != NULL)
1157 			free(remotes->dyncodes_name);
1158 #               endif
1159 		if (remotes->name != NULL)
1160 			free(remotes->name);
1161 		if (remotes->codes != NULL) {
1162 			codes = remotes->codes;
1163 			while (codes->name != NULL) {
1164 				struct ir_code_node *node, *next_node;
1165 
1166 				free(codes->name);
1167 				if (codes->signals != NULL)
1168 					free(codes->signals);
1169 				node = codes->next;
1170 				while (node) {
1171 					next_node = node->next;
1172 					free(node);
1173 					node = next_node;
1174 				}
1175 				codes++;
1176 			}
1177 			free(remotes->codes);
1178 		}
1179 		free(remotes);
1180 		remotes = next;
1181 	}
1182 }
1183