1 /*      $Id: lirc_client.c,v 5.29 2009/07/08 19:38:22 lirc Exp $      */
2 
3 /****************************************************************************
4  ** lirc_client.c ***********************************************************
5  ****************************************************************************
6  *
7  * lirc_client - common routines for lircd clients
8  *
9  * Copyright (C) 1998 Trent Piepho <xyzzy@u.washington.edu>
10  * Copyright (C) 1998 Christoph Bartelmus <lirc@bartelmus.de>
11  *
12  * System wide LIRCRC support by Michal Svec <rebel@atrey.karlin.mff.cuni.cz>
13  */
14 
15 #ifdef HAVE_CONFIG_H
16 # include <config.h>
17 #endif
18 
19 #include <errno.h>
20 #include <unistd.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <stdarg.h>
24 #include <string.h>
25 #include <limits.h>
26 #include <sys/socket.h>
27 #include <sys/un.h>
28 #include <sys/stat.h>
29 #include <sys/types.h>
30 #include <sys/wait.h>
31 
32 #include "lirc_client.h"
33 
34 /* internal defines */
35 #define MAX_INCLUDES 10
36 #define LIRC_READ 255
37 #define LIRC_PACKET_SIZE 255
38 /* three seconds */
39 #define LIRC_TIMEOUT 3
40 
41 /* internal data structures */
42 struct filestack_t {
43 	FILE *file;
44 	char *name;
45 	int line;
46 	struct filestack_t *parent;
47 };
48 
49 enum packet_state {
50 	P_BEGIN,
51 	P_MESSAGE,
52 	P_STATUS,
53 	P_DATA,
54 	P_N,
55 	P_DATA_N,
56 	P_END
57 };
58 
59 /* internal functions */
60 static void lirc_printf(char *format_str, ...);
61 static void lirc_perror(const char *s);
62 static int lirc_readline(char **line, FILE * f);
63 static char *lirc_trim(char *s);
64 static char lirc_parse_escape(char **s, const char *name, int line);
65 static void lirc_parse_string(char *s, const char *name, int line);
66 static void lirc_parse_include(char *s, const char *name, int line);
67 static int lirc_mode(char *token, char *token2, char **mode,
68 		     struct lirc_config_entry **new_config,
69 		     struct lirc_config_entry **first_config,
70 		     struct lirc_config_entry **last_config, int (check) (char *s), const char *name, int line);
71 /*
72   lircrc_config relies on this function, hence don't make it static
73   but it's not part of the official interface, so there's no guarantee
74   that it will stay available in the future
75 */
76 unsigned int lirc_flags(char *string);
77 static char *lirc_getfilename(const char *file, const char *current_file);
78 static FILE *lirc_open(const char *file, const char *current_file, char **full_name);
79 static struct filestack_t *stack_push(struct filestack_t *parent);
80 static struct filestack_t *stack_pop(struct filestack_t *entry);
81 static void stack_free(struct filestack_t *entry);
82 static int lirc_readconfig_only_internal(char *file,
83 					 struct lirc_config **config,
84 					 int (check) (char *s), char **full_name, char **sha_bang);
85 static char *lirc_startupmode(struct lirc_config_entry *first);
86 static void lirc_freeconfigentries(struct lirc_config_entry *first);
87 static void lirc_clearmode(struct lirc_config *config);
88 static char *lirc_execute(struct lirc_config *config, struct lirc_config_entry *scan);
89 static int lirc_iscode(struct lirc_config_entry *scan, char *remote, char *button, int rep);
90 static int lirc_code2char_internal(struct lirc_config *config, char *code, char **string, char **prog);
91 static const char *lirc_read_string(int fd);
92 static int lirc_identify(int sockfd);
93 
94 static int lirc_send_command(int sockfd, const char *command, char *buf, size_t * buf_len, int *ret_status);
95 
96 static int lirc_lircd;
97 static int lirc_verbose = 0;
98 static char *lirc_prog = NULL;
99 static char *lirc_buffer = NULL;
100 
lirc_printf(char * format_str,...)101 static void lirc_printf(char *format_str, ...)
102 {
103 	va_list ap;
104 
105 	if (!lirc_verbose)
106 		return;
107 
108 	va_start(ap, format_str);
109 	vfprintf(stderr, format_str, ap);
110 	va_end(ap);
111 }
112 
lirc_perror(const char * s)113 static void lirc_perror(const char *s)
114 {
115 	if (!lirc_verbose)
116 		return;
117 
118 	perror(s);
119 }
120 
lirc_init(char * prog,int verbose)121 int lirc_init(char *prog, int verbose)
122 {
123 	struct sockaddr_un addr;
124 
125 	/* connect to lircd */
126 
127 	if (prog == NULL || lirc_prog != NULL)
128 		return (-1);
129 	lirc_prog = strdup(prog);
130 	lirc_verbose = verbose;
131 	if (lirc_prog == NULL) {
132 		lirc_printf("%s: out of memory\n", prog);
133 		return (-1);
134 	}
135 
136 	addr.sun_family = AF_UNIX;
137 	strcpy(addr.sun_path, LIRCD);
138 	lirc_lircd = socket(AF_UNIX, SOCK_STREAM, 0);
139 	if (lirc_lircd == -1) {
140 		lirc_printf("%s: could not open socket\n", lirc_prog);
141 		lirc_perror(lirc_prog);
142 		free(lirc_prog);
143 		lirc_prog = NULL;
144 		return (-1);
145 	}
146 	if (connect(lirc_lircd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
147 		close(lirc_lircd);
148 		lirc_printf("%s: could not connect to socket\n", lirc_prog);
149 		lirc_perror(lirc_prog);
150 		free(lirc_prog);
151 		lirc_prog = NULL;
152 		return (-1);
153 	}
154 	return (lirc_lircd);
155 }
156 
lirc_deinit(void)157 int lirc_deinit(void)
158 {
159 	if (lirc_prog != NULL) {
160 		free(lirc_prog);
161 		lirc_prog = NULL;
162 	}
163 	if (lirc_buffer != NULL) {
164 		free(lirc_buffer);
165 		lirc_buffer = NULL;
166 	}
167 	return (close(lirc_lircd));
168 }
169 
lirc_readline(char ** line,FILE * f)170 static int lirc_readline(char **line, FILE * f)
171 {
172 	char *newline, *ret, *enlargeline;
173 	int len;
174 
175 	newline = (char *)malloc(LIRC_READ + 1);
176 	if (newline == NULL) {
177 		lirc_printf("%s: out of memory\n", lirc_prog);
178 		return (-1);
179 	}
180 	len = 0;
181 	while (1) {
182 		ret = fgets(newline + len, LIRC_READ + 1, f);
183 		if (ret == NULL) {
184 			if (feof(f) && len > 0) {
185 				*line = newline;
186 			} else {
187 				free(newline);
188 				*line = NULL;
189 			}
190 			return (0);
191 		}
192 		len = strlen(newline);
193 		if (newline[len - 1] == '\n') {
194 			newline[len - 1] = 0;
195 			*line = newline;
196 			return (0);
197 		}
198 
199 		enlargeline = (char *)realloc(newline, len + 1 + LIRC_READ);
200 		if (enlargeline == NULL) {
201 			free(newline);
202 			lirc_printf("%s: out of memory\n", lirc_prog);
203 			return (-1);
204 		}
205 		newline = enlargeline;
206 	}
207 }
208 
lirc_trim(char * s)209 static char *lirc_trim(char *s)
210 {
211 	int len;
212 
213 	while (s[0] == ' ' || s[0] == '\t')
214 		s++;
215 	len = strlen(s);
216 	while (len > 0) {
217 		len--;
218 		if (s[len] == ' ' || s[len] == '\t')
219 			s[len] = 0;
220 		else
221 			break;
222 	}
223 	return (s);
224 }
225 
226 /* parse standard C escape sequences + \@,\A-\Z is ^@,^A-^Z */
227 
lirc_parse_escape(char ** s,const char * name,int line)228 static char lirc_parse_escape(char **s, const char *name, int line)
229 {
230 
231 	char c;
232 	unsigned int i, overflow, count;
233 	int digits_found, digit;
234 
235 	c = **s;
236 	(*s)++;
237 	switch (c) {
238 	case 'a':
239 		return ('\a');
240 	case 'b':
241 		return ('\b');
242 	case 'e':
243 #if 0
244 	case 'E':		/* this should become ^E */
245 #endif
246 		return (033);
247 	case 'f':
248 		return ('\f');
249 	case 'n':
250 		return ('\n');
251 	case 'r':
252 		return ('\r');
253 	case 't':
254 		return ('\t');
255 	case 'v':
256 		return ('\v');
257 	case '\n':
258 		return (0);
259 	case 0:
260 		(*s)--;
261 		return 0;
262 	case '0':
263 	case '1':
264 	case '2':
265 	case '3':
266 	case '4':
267 	case '5':
268 	case '6':
269 	case '7':
270 		i = c - '0';
271 		count = 0;
272 
273 		while (++count < 3) {
274 			c = *(*s)++;
275 			if (c >= '0' && c <= '7') {
276 				i = (i << 3) + c - '0';
277 			} else {
278 				(*s)--;
279 				break;
280 			}
281 		}
282 		if (i > (1 << CHAR_BIT) - 1) {
283 			i &= (1 << CHAR_BIT) - 1;
284 			lirc_printf("%s: octal escape sequence out of range in %s:%d\n", lirc_prog, name, line);
285 		}
286 		return ((char)i);
287 	case 'x':
288 		{
289 			i = 0;
290 			overflow = 0;
291 			digits_found = 0;
292 			for (;;) {
293 				c = *(*s)++;
294 				if (c >= '0' && c <= '9')
295 					digit = c - '0';
296 				else if (c >= 'a' && c <= 'f')
297 					digit = c - 'a' + 10;
298 				else if (c >= 'A' && c <= 'F')
299 					digit = c - 'A' + 10;
300 				else {
301 					(*s)--;
302 					break;
303 				}
304 				overflow |= i ^ (i << 4 >> 4);
305 				i = (i << 4) + digit;
306 				digits_found = 1;
307 			}
308 			if (!digits_found) {
309 				lirc_printf("%s: \\x used with no "
310 					    "following hex digits in %s:%d\n", lirc_prog, name, line);
311 			}
312 			if (overflow || i > (1 << CHAR_BIT) - 1) {
313 				i &= (1 << CHAR_BIT) - 1;
314 				lirc_printf("%s: hex escape sequence out "
315 					    "of range in %s:%d\n", lirc_prog, name, line);
316 			}
317 			return ((char)i);
318 		}
319 	default:
320 		if (c >= '@' && c <= 'Z')
321 			return (c - '@');
322 		return (c);
323 	}
324 }
325 
lirc_parse_string(char * s,const char * name,int line)326 static void lirc_parse_string(char *s, const char *name, int line)
327 {
328 	char *t;
329 
330 	t = s;
331 	while (*s != 0) {
332 		if (*s == '\\') {
333 			s++;
334 			*t = lirc_parse_escape(&s, name, line);
335 			t++;
336 		} else {
337 			*t = *s;
338 			s++;
339 			t++;
340 		}
341 	}
342 	*t = 0;
343 }
344 
lirc_parse_include(char * s,const char * name,int line)345 static void lirc_parse_include(char *s, const char *name, int line)
346 {
347 	char last;
348 	size_t len;
349 
350 	len = strlen(s);
351 	if (len < 2) {
352 		return;
353 	}
354 	last = s[len - 1];
355 	if (*s != '"' && *s != '<') {
356 		return;
357 	}
358 	if (*s == '"' && last != '"') {
359 		return;
360 	} else if (*s == '<' && last != '>') {
361 		return;
362 	}
363 	s[len - 1] = 0;
364 	memmove(s, s + 1, len - 2 + 1);	/* terminating 0 is copied */
365 }
366 
lirc_mode(char * token,char * token2,char ** mode,struct lirc_config_entry ** new_config,struct lirc_config_entry ** first_config,struct lirc_config_entry ** last_config,int (check)(char * s),const char * name,int line)367 int lirc_mode(char *token, char *token2, char **mode,
368 	      struct lirc_config_entry **new_config,
369 	      struct lirc_config_entry **first_config,
370 	      struct lirc_config_entry **last_config, int (check) (char *s), const char *name, int line)
371 {
372 	struct lirc_config_entry *new_entry;
373 
374 	new_entry = *new_config;
375 	if (strcasecmp(token, "begin") == 0) {
376 		if (token2 == NULL) {
377 			if (new_entry == NULL) {
378 				new_entry = (struct lirc_config_entry *)
379 				    malloc(sizeof(struct lirc_config_entry));
380 				if (new_entry == NULL) {
381 					lirc_printf("%s: out of memory\n", lirc_prog);
382 					return (-1);
383 				} else {
384 					new_entry->prog = NULL;
385 					new_entry->code = NULL;
386 					new_entry->rep_delay = 0;
387 					new_entry->rep = 0;
388 					new_entry->config = NULL;
389 					new_entry->change_mode = NULL;
390 					new_entry->flags = none;
391 					new_entry->mode = NULL;
392 					new_entry->next_config = NULL;
393 					new_entry->next_code = NULL;
394 					new_entry->next = NULL;
395 
396 					*new_config = new_entry;
397 				}
398 			} else {
399 				lirc_printf("%s: bad file format, %s:%d\n", lirc_prog, name, line);
400 				return (-1);
401 			}
402 		} else {
403 			if (new_entry == NULL && *mode == NULL) {
404 				*mode = strdup(token2);
405 				if (*mode == NULL) {
406 					return (-1);
407 				}
408 			} else {
409 				lirc_printf("%s: bad file format, %s:%d\n", lirc_prog, name, line);
410 				return (-1);
411 			}
412 		}
413 	} else if (strcasecmp(token, "end") == 0) {
414 		if (token2 == NULL) {
415 			if (new_entry != NULL) {
416 #if 0
417 				if (new_entry->prog == NULL) {
418 					lirc_printf("%s: prog missing in config before line %d\n", lirc_prog, line);
419 					lirc_freeconfigentries(new_entry);
420 					*new_config = NULL;
421 					return (-1);
422 				}
423 				if (strcasecmp(new_entry->prog, lirc_prog) != 0) {
424 					lirc_freeconfigentries(new_entry);
425 					*new_config = NULL;
426 					return (0);
427 				}
428 #endif
429 				new_entry->next_code = new_entry->code;
430 				new_entry->next_config = new_entry->config;
431 				if (*last_config == NULL) {
432 					*first_config = new_entry;
433 					*last_config = new_entry;
434 				} else {
435 					(*last_config)->next = new_entry;
436 					*last_config = new_entry;
437 				}
438 				*new_config = NULL;
439 
440 				if (*mode != NULL) {
441 					new_entry->mode = strdup(*mode);
442 					if (new_entry->mode == NULL) {
443 						lirc_printf("%s: out of memory\n", lirc_prog);
444 						return (-1);
445 					}
446 				}
447 
448 				if (check != NULL &&
449 				    new_entry->prog != NULL && strcasecmp(new_entry->prog, lirc_prog) == 0) {
450 					struct lirc_list *list;
451 
452 					list = new_entry->config;
453 					while (list != NULL) {
454 						if (check(list->string) == -1) {
455 							return (-1);
456 						}
457 						list = list->next;
458 					}
459 				}
460 
461 				if (new_entry->rep_delay == 0 && new_entry->rep > 0) {
462 					new_entry->rep_delay = new_entry->rep - 1;
463 				}
464 			} else {
465 				lirc_printf("%s: %s:%d: 'end' without 'begin'\n", lirc_prog, name, line);
466 				return (-1);
467 			}
468 		} else {
469 			if (*mode != NULL) {
470 				if (new_entry != NULL) {
471 					lirc_printf("%s: %s:%d: missing 'end' token\n", lirc_prog, name, line);
472 					return (-1);
473 				}
474 				if (strcasecmp(*mode, token2) == 0) {
475 					free(*mode);
476 					*mode = NULL;
477 				} else {
478 					lirc_printf("%s: \"%s\" doesn't "
479 						    "match mode \"%s\"\n", lirc_prog, token2, *mode);
480 					return (-1);
481 				}
482 			} else {
483 				lirc_printf("%s: %s:%d: 'end %s' without 'begin'\n", lirc_prog, name, line, token2);
484 				return (-1);
485 			}
486 		}
487 	} else {
488 		lirc_printf("%s: unknown token \"%s\" in %s:%d ignored\n", lirc_prog, token, name, line);
489 	}
490 	return (0);
491 }
492 
lirc_flags(char * string)493 unsigned int lirc_flags(char *string)
494 {
495 	char *s;
496 	unsigned int flags;
497 
498 	flags = none;
499 	s = strtok(string, " \t|");
500 	while (s) {
501 		if (strcasecmp(s, "once") == 0) {
502 			flags |= once;
503 		} else if (strcasecmp(s, "quit") == 0) {
504 			flags |= quit;
505 		} else if (strcasecmp(s, "mode") == 0) {
506 			flags |= mode;
507 		} else if (strcasecmp(s, "startup_mode") == 0) {
508 			flags |= startup_mode;
509 		} else if (strcasecmp(s, "toggle_reset") == 0) {
510 			flags |= toggle_reset;
511 		} else {
512 			lirc_printf("%s: unknown flag \"%s\"\n", lirc_prog, s);
513 		}
514 		s = strtok(NULL, " \t");
515 	}
516 	return (flags);
517 }
518 
lirc_getfilename(const char * file,const char * current_file)519 static char *lirc_getfilename(const char *file, const char *current_file)
520 {
521 	char *home, *filename;
522 
523 	if (file == NULL) {
524 		home = getenv("HOME");
525 		if (home == NULL) {
526 			home = "/";
527 		}
528 		filename = (char *)malloc(strlen(home) + 1 + strlen(LIRCRC_USER_FILE) + 1);
529 		if (filename == NULL) {
530 			lirc_printf("%s: out of memory\n", lirc_prog);
531 			return NULL;
532 		}
533 		strcpy(filename, home);
534 		if (strlen(home) > 0 && filename[strlen(filename) - 1] != '/') {
535 			strcat(filename, "/");
536 		}
537 		strcat(filename, LIRCRC_USER_FILE);
538 	} else if (strncmp(file, "~/", 2) == 0) {
539 		home = getenv("HOME");
540 		if (home == NULL) {
541 			home = "/";
542 		}
543 		filename = (char *)malloc(strlen(home) + strlen(file) + 1);
544 		if (filename == NULL) {
545 			lirc_printf("%s: out of memory\n", lirc_prog);
546 			return NULL;
547 		}
548 		strcpy(filename, home);
549 		strcat(filename, file + 1);
550 	} else if (file[0] == '/' || current_file == NULL) {
551 		/* absulute path or root */
552 		filename = strdup(file);
553 		if (filename == NULL) {
554 			lirc_printf("%s: out of memory\n", lirc_prog);
555 			return NULL;
556 		}
557 	} else {
558 		/* get path from parent filename */
559 		int pathlen = strlen(current_file);
560 		while (pathlen > 0 && current_file[pathlen - 1] != '/')
561 			pathlen--;
562 		filename = (char *)malloc(pathlen + strlen(file) + 1);
563 		if (filename == NULL) {
564 			lirc_printf("%s: out of memory\n", lirc_prog);
565 			return NULL;
566 		}
567 		memcpy(filename, current_file, pathlen);
568 		filename[pathlen] = 0;
569 		strcat(filename, file);
570 	}
571 	return filename;
572 }
573 
lirc_open(const char * file,const char * current_file,char ** full_name)574 static FILE *lirc_open(const char *file, const char *current_file, char **full_name)
575 {
576 	FILE *fin;
577 	char *filename;
578 
579 	filename = lirc_getfilename(file, current_file);
580 	if (filename == NULL) {
581 		return NULL;
582 	}
583 
584 	fin = fopen(filename, "r");
585 	if (fin == NULL && (file != NULL || errno != ENOENT)) {
586 		lirc_printf("%s: could not open config file %s\n", lirc_prog, filename);
587 		lirc_perror(lirc_prog);
588 	} else if (fin == NULL) {
589 		const char *root_file = LIRCRC_ROOT_FILE;
590 		fin = fopen(root_file, "r");
591 		if (fin == NULL && errno == ENOENT) {
592 			int save_errno = errno;
593 			root_file = LIRCRC_OLD_ROOT_FILE;
594 			fin = fopen(root_file, "r");
595 			errno = save_errno;
596 		}
597 		if (fin == NULL && errno != ENOENT) {
598 			lirc_printf("%s: could not open config file %s\n", lirc_prog, LIRCRC_ROOT_FILE);
599 			lirc_perror(lirc_prog);
600 		} else if (fin == NULL) {
601 			lirc_printf("%s: could not open config files "
602 				    "%s and %s\n", lirc_prog, filename, LIRCRC_ROOT_FILE);
603 			lirc_perror(lirc_prog);
604 		} else {
605 			free(filename);
606 			filename = strdup(root_file);
607 			if (filename == NULL) {
608 				fclose(fin);
609 				lirc_printf("%s: out of memory\n", lirc_prog);
610 				return NULL;
611 			}
612 		}
613 	}
614 	if (full_name && fin != NULL) {
615 		*full_name = filename;
616 	} else {
617 		free(filename);
618 	}
619 	return fin;
620 }
621 
stack_push(struct filestack_t * parent)622 static struct filestack_t *stack_push(struct filestack_t *parent)
623 {
624 	struct filestack_t *entry;
625 	entry = malloc(sizeof(struct filestack_t));
626 	if (entry == NULL) {
627 		lirc_printf("%s: out of memory\n", lirc_prog);
628 		return NULL;
629 	}
630 	entry->file = NULL;
631 	entry->name = NULL;
632 	entry->line = 0;
633 	entry->parent = parent;
634 	return entry;
635 }
636 
stack_pop(struct filestack_t * entry)637 static struct filestack_t *stack_pop(struct filestack_t *entry)
638 {
639 	struct filestack_t *parent = NULL;
640 	if (entry) {
641 		parent = entry->parent;
642 		if (entry->name)
643 			free(entry->name);
644 		free(entry);
645 	}
646 	return parent;
647 }
648 
stack_free(struct filestack_t * entry)649 static void stack_free(struct filestack_t *entry)
650 {
651 	while (entry) {
652 		entry = stack_pop(entry);
653 	}
654 }
655 
lirc_readconfig(char * file,struct lirc_config ** config,int (check)(char * s))656 int lirc_readconfig(char *file, struct lirc_config **config, int (check) (char *s))
657 {
658 	struct sockaddr_un addr;
659 	int sockfd = -1;
660 	char *sha_bang, *sha_bang2, *filename;
661 	char *command;
662 	int ret;
663 
664 	filename = NULL;
665 	sha_bang = NULL;
666 	if (lirc_readconfig_only_internal(file, config, check, &filename, &sha_bang) == -1) {
667 		return -1;
668 	}
669 
670 	if (sha_bang == NULL) {
671 		goto lirc_readconfig_compat;
672 	}
673 
674 	/* connect to lircrcd */
675 
676 	addr.sun_family = AF_UNIX;
677 	if (lirc_getsocketname(filename, addr.sun_path, sizeof(addr.sun_path)) > sizeof(addr.sun_path)) {
678 		lirc_printf("%s: WARNING: file name too long\n", lirc_prog);
679 		goto lirc_readconfig_compat;
680 	}
681 	sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
682 	if (sockfd == -1) {
683 		lirc_printf("%s: WARNING: could not open socket\n", lirc_prog);
684 		lirc_perror(lirc_prog);
685 		goto lirc_readconfig_compat;
686 	}
687 	if (connect(sockfd, (struct sockaddr *)&addr, sizeof(addr)) != -1) {
688 		if (sha_bang != NULL)
689 			free(sha_bang);
690 		(*config)->sockfd = sockfd;
691 		free(filename);
692 
693 		/* tell daemon lirc_prog */
694 		if (lirc_identify(sockfd) == LIRC_RET_SUCCESS) {
695 			/* we're connected */
696 			return 0;
697 		}
698 		close(sockfd);
699 		lirc_freeconfig(*config);
700 		return -1;
701 	}
702 	close(sockfd);
703 	sockfd = -1;
704 
705 	/* launch lircrcd */
706 	sha_bang2 = sha_bang != NULL ? sha_bang : "lircrcd";
707 
708 	command = malloc(strlen(sha_bang2) + 1 + strlen(filename) + 1);
709 	if (command == NULL) {
710 		goto lirc_readconfig_compat;
711 	}
712 	strcpy(command, sha_bang2);
713 	strcat(command, " ");
714 	strcat(command, filename);
715 
716 	ret = system(command);
717 
718 	if (ret == -1 || WEXITSTATUS(ret) != EXIT_SUCCESS) {
719 		goto lirc_readconfig_compat;
720 	}
721 
722 	if (sha_bang != NULL)
723 		free(sha_bang);
724 	free(filename);
725 
726 	sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
727 	if (sockfd == -1) {
728 		lirc_printf("%s: WARNING: could not open socket\n", lirc_prog);
729 		lirc_perror(lirc_prog);
730 		goto lirc_readconfig_compat;
731 	}
732 	if (connect(sockfd, (struct sockaddr *)&addr, sizeof(addr)) != -1) {
733 		if (lirc_identify(sockfd) == LIRC_RET_SUCCESS) {
734 			(*config)->sockfd = sockfd;
735 			return 0;
736 		}
737 	}
738 	close(sockfd);
739 	lirc_freeconfig(*config);
740 	return -1;
741 
742 lirc_readconfig_compat:
743 	/* compat fallback */
744 	if (sockfd != -1)
745 		close(sockfd);
746 	if (sha_bang != NULL)
747 		free(sha_bang);
748 	free(filename);
749 	return 0;
750 }
751 
lirc_readconfig_only(char * file,struct lirc_config ** config,int (check)(char * s))752 int lirc_readconfig_only(char *file, struct lirc_config **config, int (check) (char *s))
753 {
754 	return lirc_readconfig_only_internal(file, config, check, NULL, NULL);
755 }
756 
lirc_readconfig_only_internal(char * file,struct lirc_config ** config,int (check)(char * s),char ** full_name,char ** sha_bang)757 static int lirc_readconfig_only_internal(char *file,
758 					 struct lirc_config **config,
759 					 int (check) (char *s), char **full_name, char **sha_bang)
760 {
761 	char *string, *eq, *token, *token2, *token3;
762 	struct filestack_t *filestack, *stack_tmp;
763 	int open_files;
764 	struct lirc_config_entry *new_entry, *first, *last;
765 	char *mode, *remote;
766 	int ret = 0;
767 	int firstline = 1;
768 	char *save_full_name = NULL;
769 
770 	filestack = stack_push(NULL);
771 	if (filestack == NULL) {
772 		return -1;
773 	}
774 	filestack->file = lirc_open(file, NULL, &(filestack->name));
775 	if (filestack->file == NULL) {
776 		stack_free(filestack);
777 		return -1;
778 	}
779 	filestack->line = 0;
780 	open_files = 1;
781 
782 	first = new_entry = last = NULL;
783 	mode = NULL;
784 	remote = LIRC_ALL;
785 	while (filestack) {
786 		if ((ret = lirc_readline(&string, filestack->file)) == -1 || string == NULL) {
787 			fclose(filestack->file);
788 			if (open_files == 1 && full_name != NULL) {
789 				save_full_name = filestack->name;
790 				filestack->name = NULL;
791 			}
792 			filestack = stack_pop(filestack);
793 			open_files--;
794 			continue;
795 		}
796 		/* check for sha-bang */
797 		if (firstline && sha_bang) {
798 			firstline = 0;
799 			if (strncmp(string, "#!", 2) == 0) {
800 				*sha_bang = strdup(string + 2);
801 				if (*sha_bang == NULL) {
802 					lirc_printf("%s: out of memory\n", lirc_prog);
803 					ret = -1;
804 					free(string);
805 					break;
806 				}
807 			}
808 		}
809 		filestack->line++;
810 		eq = strchr(string, '=');
811 		if (eq == NULL) {
812 			token = strtok(string, " \t");
813 			if (token == NULL) {
814 				/* ignore empty line */
815 			} else if (token[0] == '#') {
816 				/* ignore comment */
817 			} else if (strcasecmp(token, "include") == 0) {
818 				if (open_files >= MAX_INCLUDES) {
819 					lirc_printf("%s: too many files "
820 						    "included at %s:%d\n", lirc_prog, filestack->name, filestack->line);
821 					ret = -1;
822 				} else {
823 					token2 = strtok(NULL, "");
824 					token2 = lirc_trim(token2);
825 					lirc_parse_include(token2, filestack->name, filestack->line);
826 					stack_tmp = stack_push(filestack);
827 					if (stack_tmp == NULL) {
828 						ret = -1;
829 					} else {
830 						stack_tmp->file =
831 						    lirc_open(token2, filestack->name, &(stack_tmp->name));
832 						stack_tmp->line = 0;
833 						if (stack_tmp->file) {
834 							open_files++;
835 							filestack = stack_tmp;
836 						} else {
837 							stack_pop(stack_tmp);
838 							ret = -1;
839 						}
840 					}
841 				}
842 			} else {
843 				token2 = strtok(NULL, " \t");
844 				if (token2 != NULL && (token3 = strtok(NULL, " \t")) != NULL) {
845 					lirc_printf("%s: unexpected token in line %s:%d\n",
846 						    lirc_prog, filestack->name, filestack->line);
847 				} else {
848 					ret = lirc_mode(token, token2, &mode,
849 							&new_entry, &first, &last,
850 							check, filestack->name, filestack->line);
851 					if (ret == 0) {
852 						if (remote != LIRC_ALL)
853 							free(remote);
854 						remote = LIRC_ALL;
855 					} else {
856 						if (mode != NULL) {
857 							free(mode);
858 							mode = NULL;
859 						}
860 						if (new_entry != NULL) {
861 							lirc_freeconfigentries(new_entry);
862 							new_entry = NULL;
863 						}
864 					}
865 				}
866 			}
867 		} else {
868 			eq[0] = 0;
869 			token = lirc_trim(string);
870 			token2 = lirc_trim(eq + 1);
871 			if (token[0] == '#') {
872 				/* ignore comment */
873 			} else if (new_entry == NULL) {
874 				lirc_printf("%s: bad file format, %s:%d\n",
875 					    lirc_prog, filestack->name, filestack->line);
876 				ret = -1;
877 			} else {
878 				token2 = strdup(token2);
879 				if (token2 == NULL) {
880 					lirc_printf("%s: out of memory\n", lirc_prog);
881 					ret = -1;
882 				} else if (strcasecmp(token, "prog") == 0) {
883 					if (new_entry->prog != NULL)
884 						free(new_entry->prog);
885 					new_entry->prog = token2;
886 				} else if (strcasecmp(token, "remote") == 0) {
887 					if (remote != LIRC_ALL)
888 						free(remote);
889 
890 					if (strcasecmp("*", token2) == 0) {
891 						remote = LIRC_ALL;
892 						free(token2);
893 					} else {
894 						remote = token2;
895 					}
896 				} else if (strcasecmp(token, "button") == 0) {
897 					struct lirc_code *code;
898 
899 					code = (struct lirc_code *)
900 					    malloc(sizeof(struct lirc_code));
901 					if (code == NULL) {
902 						free(token2);
903 						lirc_printf("%s: out of memory\n", lirc_prog);
904 						ret = -1;
905 					} else {
906 						code->remote = remote;
907 						if (strcasecmp("*", token2) == 0) {
908 							code->button = LIRC_ALL;
909 							free(token2);
910 						} else {
911 							code->button = token2;
912 						}
913 						code->next = NULL;
914 
915 						if (new_entry->code == NULL) {
916 							new_entry->code = code;
917 						} else {
918 							new_entry->next_code->next = code;
919 						}
920 						new_entry->next_code = code;
921 						if (remote != LIRC_ALL) {
922 							remote = strdup(remote);
923 							if (remote == NULL) {
924 								lirc_printf("%s: out of memory\n", lirc_prog);
925 								ret = -1;
926 							}
927 						}
928 					}
929 				} else if (strcasecmp(token, "delay") == 0) {
930 					char *end;
931 
932 					errno = ERANGE + 1;
933 					new_entry->rep_delay = strtoul(token2, &end, 0);
934 					if ((new_entry->rep_delay == ULONG_MAX && errno == ERANGE)
935 					    || end[0] != 0 || strlen(token2) == 0) {
936 						lirc_printf("%s: \"%s\" not"
937 							    " a  valid number for delay\n", lirc_prog, token2);
938 					}
939 					free(token2);
940 				} else if (strcasecmp(token, "repeat") == 0) {
941 					char *end;
942 
943 					errno = ERANGE + 1;
944 					new_entry->rep = strtoul(token2, &end, 0);
945 					if ((new_entry->rep == ULONG_MAX && errno == ERANGE)
946 					    || end[0] != 0 || strlen(token2) == 0) {
947 						lirc_printf("%s: \"%s\" not"
948 							    " a  valid number for repeat\n", lirc_prog, token2);
949 					}
950 					free(token2);
951 				} else if (strcasecmp(token, "config") == 0) {
952 					struct lirc_list *new_list;
953 
954 					new_list = (struct lirc_list *)
955 					    malloc(sizeof(struct lirc_list));
956 					if (new_list == NULL) {
957 						free(token2);
958 						lirc_printf("%s: out of memory\n", lirc_prog);
959 						ret = -1;
960 					} else {
961 						lirc_parse_string(token2, filestack->name, filestack->line);
962 						new_list->string = token2;
963 						new_list->next = NULL;
964 						if (new_entry->config == NULL) {
965 							new_entry->config = new_list;
966 						} else {
967 							new_entry->next_config->next = new_list;
968 						}
969 						new_entry->next_config = new_list;
970 					}
971 				} else if (strcasecmp(token, "mode") == 0) {
972 					if (new_entry->change_mode != NULL)
973 						free(new_entry->change_mode);
974 					new_entry->change_mode = token2;
975 				} else if (strcasecmp(token, "flags") == 0) {
976 					new_entry->flags = lirc_flags(token2);
977 					free(token2);
978 				} else {
979 					free(token2);
980 					lirc_printf("%s: unknown token \"%s\" in %s:%d ignored\n",
981 						    lirc_prog, token, filestack->name, filestack->line);
982 				}
983 			}
984 		}
985 		free(string);
986 		if (ret == -1)
987 			break;
988 	}
989 	if (remote != LIRC_ALL)
990 		free(remote);
991 	if (new_entry != NULL) {
992 		if (ret == 0) {
993 			ret = lirc_mode("end", NULL, &mode, &new_entry, &first, &last, check, "", 0);
994 			lirc_printf("%s: warning: end token missing at end of file\n", lirc_prog);
995 		} else {
996 			lirc_freeconfigentries(new_entry);
997 			new_entry = NULL;
998 		}
999 	}
1000 	if (mode != NULL) {
1001 		if (ret == 0) {
1002 			lirc_printf("%s: warning: no end token found for mode \"%s\"\n", lirc_prog, mode);
1003 		}
1004 		free(mode);
1005 	}
1006 	if (ret == 0) {
1007 		char *startupmode;
1008 
1009 		*config = (struct lirc_config *)
1010 		    malloc(sizeof(struct lirc_config));
1011 		if (*config == NULL) {
1012 			lirc_printf("%s: out of memory\n", lirc_prog);
1013 			lirc_freeconfigentries(first);
1014 			return (-1);
1015 		}
1016 		(*config)->first = first;
1017 		(*config)->next = first;
1018 		startupmode = lirc_startupmode((*config)->first);
1019 		(*config)->current_mode = startupmode ? strdup(startupmode) : NULL;
1020 		(*config)->sockfd = -1;
1021 		if (full_name != NULL) {
1022 			*full_name = save_full_name;
1023 			save_full_name = NULL;
1024 		}
1025 	} else {
1026 		*config = NULL;
1027 		lirc_freeconfigentries(first);
1028 		if (*sha_bang != NULL) {
1029 			free(*sha_bang);
1030 			*sha_bang = NULL;
1031 		}
1032 	}
1033 	if (filestack) {
1034 		stack_free(filestack);
1035 	}
1036 	if (save_full_name) {
1037 		free(save_full_name);
1038 	}
1039 	return (ret);
1040 }
1041 
lirc_startupmode(struct lirc_config_entry * first)1042 static char *lirc_startupmode(struct lirc_config_entry *first)
1043 {
1044 	struct lirc_config_entry *scan;
1045 	char *startupmode;
1046 
1047 	startupmode = NULL;
1048 	scan = first;
1049 	/* Set a startup mode based on flags=startup_mode */
1050 	while (scan != NULL) {
1051 		if (scan->flags & startup_mode) {
1052 			if (scan->change_mode != NULL) {
1053 				startupmode = scan->change_mode;
1054 				/* Remove the startup mode or it confuses lirc mode system */
1055 				scan->change_mode = NULL;
1056 				break;
1057 			} else {
1058 				lirc_printf("%s: startup_mode flags requires 'mode ='\n", lirc_prog);
1059 			}
1060 		}
1061 		scan = scan->next;
1062 	}
1063 
1064 	/* Set a default mode if we find a mode = client app name */
1065 	if (startupmode == NULL) {
1066 		scan = first;
1067 		while (scan != NULL) {
1068 			if (scan->mode != NULL && strcasecmp(lirc_prog, scan->mode) == 0) {
1069 				startupmode = lirc_prog;
1070 				break;
1071 			}
1072 			scan = scan->next;
1073 		}
1074 	}
1075 
1076 	if (startupmode == NULL)
1077 		return (NULL);
1078 	scan = first;
1079 	while (scan != NULL) {
1080 		if (scan->change_mode != NULL && scan->flags & once && strcasecmp(startupmode, scan->change_mode) == 0) {
1081 			scan->flags |= ecno;
1082 		}
1083 		scan = scan->next;
1084 	}
1085 	return (startupmode);
1086 }
1087 
lirc_freeconfig(struct lirc_config * config)1088 void lirc_freeconfig(struct lirc_config *config)
1089 {
1090 	if (config != NULL) {
1091 		if (config->sockfd != -1) {
1092 			(void)close(config->sockfd);
1093 			config->sockfd = -1;
1094 		}
1095 		lirc_freeconfigentries(config->first);
1096 		free(config->current_mode);
1097 		free(config);
1098 	}
1099 }
1100 
lirc_freeconfigentries(struct lirc_config_entry * first)1101 static void lirc_freeconfigentries(struct lirc_config_entry *first)
1102 {
1103 	struct lirc_config_entry *c, *config_temp;
1104 	struct lirc_list *list, *list_temp;
1105 	struct lirc_code *code, *code_temp;
1106 
1107 	c = first;
1108 	while (c != NULL) {
1109 		if (c->prog)
1110 			free(c->prog);
1111 		if (c->change_mode)
1112 			free(c->change_mode);
1113 		if (c->mode)
1114 			free(c->mode);
1115 
1116 		code = c->code;
1117 		while (code != NULL) {
1118 			if (code->remote != NULL && code->remote != LIRC_ALL)
1119 				free(code->remote);
1120 			if (code->button != NULL && code->button != LIRC_ALL)
1121 				free(code->button);
1122 			code_temp = code->next;
1123 			free(code);
1124 			code = code_temp;
1125 		}
1126 
1127 		list = c->config;
1128 		while (list != NULL) {
1129 			if (list->string)
1130 				free(list->string);
1131 			list_temp = list->next;
1132 			free(list);
1133 			list = list_temp;
1134 		}
1135 		config_temp = c->next;
1136 		free(c);
1137 		c = config_temp;
1138 	}
1139 }
1140 
lirc_clearmode(struct lirc_config * config)1141 static void lirc_clearmode(struct lirc_config *config)
1142 {
1143 	struct lirc_config_entry *scan;
1144 
1145 	if (config->current_mode == NULL) {
1146 		return;
1147 	}
1148 	scan = config->first;
1149 	while (scan != NULL) {
1150 		if (scan->change_mode != NULL) {
1151 			if (strcasecmp(scan->change_mode, config->current_mode) == 0) {
1152 				scan->flags &= ~ecno;
1153 			}
1154 		}
1155 		scan = scan->next;
1156 	}
1157 	free(config->current_mode);
1158 	config->current_mode = NULL;
1159 }
1160 
lirc_execute(struct lirc_config * config,struct lirc_config_entry * scan)1161 static char *lirc_execute(struct lirc_config *config, struct lirc_config_entry *scan)
1162 {
1163 	char *s;
1164 	int do_once = 1;
1165 
1166 	if (scan->flags & mode) {
1167 		lirc_clearmode(config);
1168 	}
1169 	if (scan->change_mode != NULL) {
1170 		free(config->current_mode);
1171 		config->current_mode = strdup(scan->change_mode);
1172 		if (scan->flags & once) {
1173 			if (scan->flags & ecno) {
1174 				do_once = 0;
1175 			} else {
1176 				scan->flags |= ecno;
1177 			}
1178 		}
1179 	}
1180 	if (scan->next_config != NULL &&
1181 	    scan->prog != NULL && (lirc_prog == NULL || strcasecmp(scan->prog, lirc_prog) == 0) && do_once == 1) {
1182 		s = scan->next_config->string;
1183 		scan->next_config = scan->next_config->next;
1184 		if (scan->next_config == NULL)
1185 			scan->next_config = scan->config;
1186 		return (s);
1187 	}
1188 	return (NULL);
1189 }
1190 
lirc_iscode(struct lirc_config_entry * scan,char * remote,char * button,int rep)1191 static int lirc_iscode(struct lirc_config_entry *scan, char *remote, char *button, int rep)
1192 {
1193 	struct lirc_code *codes;
1194 
1195 	/* no remote/button specified */
1196 	if (scan->code == NULL) {
1197 		return rep == 0 ||
1198 		    (scan->rep > 0 && rep > scan->rep_delay && ((rep - scan->rep_delay - 1) % scan->rep) == 0);
1199 	}
1200 
1201 	/* remote/button match? */
1202 	if (scan->next_code->remote == LIRC_ALL || strcasecmp(scan->next_code->remote, remote) == 0) {
1203 		if (scan->next_code->button == LIRC_ALL || strcasecmp(scan->next_code->button, button) == 0) {
1204 			int iscode = 0;
1205 			/* button sequence? */
1206 			if (scan->code->next == NULL || rep == 0) {
1207 				scan->next_code = scan->next_code->next;
1208 				if (scan->code->next != NULL) {
1209 					iscode = 1;
1210 				}
1211 			}
1212 			/* sequence completed? */
1213 			if (scan->next_code == NULL) {
1214 				scan->next_code = scan->code;
1215 				if (scan->code->next != NULL || rep == 0 ||
1216 				    (scan->rep > 0 && rep > scan->rep_delay &&
1217 				     ((rep - scan->rep_delay - 1) % scan->rep) == 0))
1218 					iscode = 2;
1219 			}
1220 			return iscode;
1221 		}
1222 	}
1223 
1224 	if (rep != 0)
1225 		return (0);
1226 
1227 	/* handle toggle_reset */
1228 	if (scan->flags & toggle_reset) {
1229 		scan->next_config = scan->config;
1230 	}
1231 
1232 	codes = scan->code;
1233 	if (codes == scan->next_code)
1234 		return (0);
1235 	codes = codes->next;
1236 	/* rebase code sequence */
1237 	while (codes != scan->next_code->next) {
1238 		struct lirc_code *prev, *next;
1239 		int flag = 1;
1240 
1241 		prev = scan->code;
1242 		next = codes;
1243 		while (next != scan->next_code) {
1244 			if (prev->remote == LIRC_ALL || strcasecmp(prev->remote, next->remote) == 0) {
1245 				if (prev->button == LIRC_ALL || strcasecmp(prev->button, next->button) == 0) {
1246 					prev = prev->next;
1247 					next = next->next;
1248 				} else {
1249 					flag = 0;
1250 					break;
1251 				}
1252 			} else {
1253 				flag = 0;
1254 				break;
1255 			}
1256 		}
1257 		if (flag == 1) {
1258 			if (prev->remote == LIRC_ALL || strcasecmp(prev->remote, remote) == 0) {
1259 				if (prev->button == LIRC_ALL || strcasecmp(prev->button, button) == 0) {
1260 					if (rep == 0) {
1261 						scan->next_code = prev->next;
1262 						return (0);
1263 					}
1264 				}
1265 			}
1266 		}
1267 		codes = codes->next;
1268 	}
1269 	scan->next_code = scan->code;
1270 	return (0);
1271 }
1272 
lirc_ir2char(struct lirc_config * config,char * code)1273 char *lirc_ir2char(struct lirc_config *config, char *code)
1274 {
1275 	static int warning = 1;
1276 	char *string;
1277 
1278 	if (warning) {
1279 		fprintf(stderr, "%s: warning: lirc_ir2char() is obsolete\n", lirc_prog);
1280 		warning = 0;
1281 	}
1282 	if (lirc_code2char(config, code, &string) == -1)
1283 		return (NULL);
1284 	return (string);
1285 }
1286 
lirc_code2char(struct lirc_config * config,char * code,char ** string)1287 int lirc_code2char(struct lirc_config *config, char *code, char **string)
1288 {
1289 	if (config->sockfd != -1) {
1290 		char command[10 + strlen(code) + 1 + 1];
1291 		static char buf[LIRC_PACKET_SIZE];
1292 		size_t buf_len = LIRC_PACKET_SIZE;
1293 		int success;
1294 		int ret;
1295 
1296 		sprintf(command, "CODE %s", code);
1297 
1298 		ret = lirc_send_command(config->sockfd, command, buf, &buf_len, &success);
1299 		if (success == LIRC_RET_SUCCESS) {
1300 			if (ret > 0) {
1301 				*string = buf;
1302 			} else {
1303 				*string = NULL;
1304 			}
1305 			return LIRC_RET_SUCCESS;
1306 		}
1307 		return LIRC_RET_ERROR;
1308 	}
1309 	return lirc_code2char_internal(config, code, string, NULL);
1310 }
1311 
lirc_code2charprog(struct lirc_config * config,char * code,char ** string,char ** prog)1312 int lirc_code2charprog(struct lirc_config *config, char *code, char **string, char **prog)
1313 {
1314 	char *backup;
1315 	int ret;
1316 
1317 	backup = lirc_prog;
1318 	lirc_prog = NULL;
1319 
1320 	ret = lirc_code2char_internal(config, code, string, prog);
1321 
1322 	lirc_prog = backup;
1323 	return ret;
1324 }
1325 
lirc_code2char_internal(struct lirc_config * config,char * code,char ** string,char ** prog)1326 static int lirc_code2char_internal(struct lirc_config *config, char *code, char **string, char **prog)
1327 {
1328 	int rep;
1329 	char *backup;
1330 	char *remote, *button;
1331 	char *s = NULL;
1332 	struct lirc_config_entry *scan;
1333 	int exec_level;
1334 	int quit_happened;
1335 
1336 	*string = NULL;
1337 	if (sscanf(code, "%*x %x %*s %*s\n", &rep) == 1) {
1338 		backup = strdup(code);
1339 		if (backup == NULL)
1340 			return (-1);
1341 
1342 		strtok(backup, " ");
1343 		strtok(NULL, " ");
1344 		button = strtok(NULL, " ");
1345 		remote = strtok(NULL, "\n");
1346 
1347 		if (button == NULL || remote == NULL) {
1348 			free(backup);
1349 			return (0);
1350 		}
1351 
1352 		scan = config->next;
1353 		quit_happened = 0;
1354 		while (scan != NULL) {
1355 			exec_level = lirc_iscode(scan, remote, button, rep);
1356 			if (exec_level > 0 &&
1357 			    (scan->mode == NULL ||
1358 			     (scan->mode != NULL &&
1359 			      config->current_mode != NULL &&
1360 			      strcasecmp(scan->mode, config->current_mode) == 0)) && quit_happened == 0) {
1361 				if (exec_level > 1) {
1362 					s = lirc_execute(config, scan);
1363 					if (s != NULL && prog != NULL) {
1364 						*prog = scan->prog;
1365 					}
1366 				} else {
1367 					s = NULL;
1368 				}
1369 				if (scan->flags & quit) {
1370 					quit_happened = 1;
1371 					config->next = NULL;
1372 					scan = scan->next;
1373 					continue;
1374 				} else if (s != NULL) {
1375 					config->next = scan->next;
1376 					break;
1377 				}
1378 			}
1379 			scan = scan->next;
1380 		}
1381 		free(backup);
1382 		if (s != NULL) {
1383 			*string = s;
1384 			return (0);
1385 		}
1386 	}
1387 	config->next = config->first;
1388 	return (0);
1389 }
1390 
1391 #define PACKET_SIZE 100
1392 
lirc_nextir(void)1393 char *lirc_nextir(void)
1394 {
1395 	static int warning = 1;
1396 	char *code;
1397 	int ret;
1398 
1399 	if (warning) {
1400 		fprintf(stderr, "%s: warning: lirc_nextir() is obsolete\n", lirc_prog);
1401 		warning = 0;
1402 	}
1403 	ret = lirc_nextcode(&code);
1404 	if (ret == -1)
1405 		return (NULL);
1406 	return (code);
1407 }
1408 
lirc_nextcode(char ** code)1409 int lirc_nextcode(char **code)
1410 {
1411 	static int packet_size = PACKET_SIZE;
1412 	static int end_len = 0;
1413 	ssize_t len = 0;
1414 	char *end, c;
1415 
1416 	*code = NULL;
1417 	if (lirc_buffer == NULL) {
1418 		lirc_buffer = (char *)malloc(packet_size + 1);
1419 		if (lirc_buffer == NULL) {
1420 			lirc_printf("%s: out of memory\n", lirc_prog);
1421 			return (-1);
1422 		}
1423 		lirc_buffer[0] = 0;
1424 	}
1425 	while ((end = strchr(lirc_buffer, '\n')) == NULL) {
1426 		if (end_len >= packet_size) {
1427 			char *new_buffer;
1428 
1429 			packet_size += PACKET_SIZE;
1430 			new_buffer = (char *)realloc(lirc_buffer, packet_size + 1);
1431 			if (new_buffer == NULL) {
1432 				return (-1);
1433 			}
1434 			lirc_buffer = new_buffer;
1435 		}
1436 		len = read(lirc_lircd, lirc_buffer + end_len, packet_size - end_len);
1437 		if (len <= 0) {
1438 			if (len == -1 && errno == EAGAIN)
1439 				return (0);
1440 			else
1441 				return (-1);
1442 		}
1443 		end_len += len;
1444 		lirc_buffer[end_len] = 0;
1445 		/* return if next code not yet available completely */
1446 		if ((end = strchr(lirc_buffer, '\n')) == NULL) {
1447 			return (0);
1448 		}
1449 	}
1450 	/* copy first line to buffer (code) and move remaining chars to
1451 	   lirc_buffers start */
1452 	end++;
1453 	end_len = strlen(end);
1454 	c = end[0];
1455 	end[0] = 0;
1456 	*code = strdup(lirc_buffer);
1457 	end[0] = c;
1458 	memmove(lirc_buffer, end, end_len + 1);
1459 	if (*code == NULL)
1460 		return (-1);
1461 	return (0);
1462 }
1463 
lirc_getsocketname(const char * filename,char * buf,size_t size)1464 size_t lirc_getsocketname(const char *filename, char *buf, size_t size)
1465 {
1466 	if (strlen(filename) + 2 <= size) {
1467 		strcpy(buf, filename);
1468 		strcat(buf, "d");
1469 	}
1470 	return strlen(filename) + 2;
1471 }
1472 
lirc_getmode(struct lirc_config * config)1473 const char *lirc_getmode(struct lirc_config *config)
1474 {
1475 	if (config->sockfd != -1) {
1476 		static char buf[LIRC_PACKET_SIZE];
1477 		size_t buf_len = LIRC_PACKET_SIZE;
1478 		int success;
1479 		int ret;
1480 
1481 		ret = lirc_send_command(config->sockfd, "GETMODE\n", buf, &buf_len, &success);
1482 		if (success == LIRC_RET_SUCCESS) {
1483 			if (ret > 0) {
1484 				return buf;
1485 			} else {
1486 				return NULL;
1487 			}
1488 		}
1489 		return NULL;
1490 	}
1491 	return config->current_mode;
1492 }
1493 
lirc_setmode(struct lirc_config * config,const char * mode)1494 const char *lirc_setmode(struct lirc_config *config, const char *mode)
1495 {
1496 	if (config->sockfd != -1) {
1497 		static char buf[LIRC_PACKET_SIZE];
1498 		size_t buf_len = LIRC_PACKET_SIZE;
1499 		int success;
1500 		int ret;
1501 		char cmd[LIRC_PACKET_SIZE];
1502 		if (snprintf(cmd, LIRC_PACKET_SIZE, "SETMODE%s%s\n", mode ? " " : "", mode ? mode : "")
1503 		    >= LIRC_PACKET_SIZE) {
1504 			return NULL;
1505 		}
1506 
1507 		ret = lirc_send_command(config->sockfd, cmd, buf, &buf_len, &success);
1508 		if (success == LIRC_RET_SUCCESS) {
1509 			if (ret > 0) {
1510 				return buf;
1511 			} else {
1512 				return NULL;
1513 			}
1514 		}
1515 		return NULL;
1516 	}
1517 
1518 	free(config->current_mode);
1519 	config->current_mode = mode ? strdup(mode) : NULL;
1520 	return config->current_mode;
1521 }
1522 
lirc_read_string(int fd)1523 static const char *lirc_read_string(int fd)
1524 {
1525 	static char buffer[LIRC_PACKET_SIZE + 1] = "";
1526 	char *end;
1527 	static int head = 0, tail = 0;
1528 	int ret;
1529 	ssize_t n;
1530 	fd_set fds;
1531 	struct timeval tv;
1532 
1533 	if (head > 0) {
1534 		memmove(buffer, buffer + head, tail - head + 1);
1535 		tail -= head;
1536 		head = 0;
1537 		end = strchr(buffer, '\n');
1538 	} else {
1539 		end = NULL;
1540 	}
1541 	if (strlen(buffer) != tail) {
1542 		lirc_printf("%s: protocol error\n", lirc_prog);
1543 		goto lirc_read_string_error;
1544 	}
1545 
1546 	while (end == NULL) {
1547 		if (LIRC_PACKET_SIZE <= tail) {
1548 			lirc_printf("%s: bad packet\n", lirc_prog);
1549 			goto lirc_read_string_error;
1550 		}
1551 
1552 		FD_ZERO(&fds);
1553 		FD_SET(fd, &fds);
1554 		tv.tv_sec = LIRC_TIMEOUT;
1555 		tv.tv_usec = 0;
1556 		do {
1557 			ret = select(fd + 1, &fds, NULL, NULL, &tv);
1558 		}
1559 		while (ret == -1 && errno == EINTR);
1560 		if (ret == -1) {
1561 			lirc_printf("%s: select() failed\n", lirc_prog);
1562 			lirc_perror(lirc_prog);
1563 			goto lirc_read_string_error;
1564 		} else if (ret == 0) {
1565 			lirc_printf("%s: timeout\n", lirc_prog);
1566 			goto lirc_read_string_error;
1567 		}
1568 
1569 		n = read(fd, buffer + tail, LIRC_PACKET_SIZE - tail);
1570 		if (n <= 0) {
1571 			lirc_printf("%s: read() failed\n", lirc_prog);
1572 			lirc_perror(lirc_prog);
1573 			goto lirc_read_string_error;
1574 		}
1575 		buffer[tail + n] = 0;
1576 		tail += n;
1577 		end = strchr(buffer, '\n');
1578 	}
1579 
1580 	end[0] = 0;
1581 	head = strlen(buffer) + 1;
1582 	return (buffer);
1583 
1584 lirc_read_string_error:
1585 	head = tail = 0;
1586 	buffer[0] = 0;
1587 	return (NULL);
1588 }
1589 
lirc_send_command(int sockfd,const char * command,char * buf,size_t * buf_len,int * ret_status)1590 int lirc_send_command(int sockfd, const char *command, char *buf, size_t * buf_len, int *ret_status)
1591 {
1592 	int done, todo;
1593 	const char *string, *data;
1594 	char *endptr;
1595 	enum packet_state state;
1596 	int status, n;
1597 	__u32 data_n = 0;
1598 	size_t written = 0, max = 0, len;
1599 
1600 	if (buf_len != NULL) {
1601 		max = *buf_len;
1602 	}
1603 	todo = strlen(command);
1604 	data = command;
1605 	while (todo > 0) {
1606 		done = write(sockfd, (void *)data, todo);
1607 		if (done < 0) {
1608 			lirc_printf("%s: could not send packet\n", lirc_prog);
1609 			lirc_perror(lirc_prog);
1610 			return (-1);
1611 		}
1612 		data += done;
1613 		todo -= done;
1614 	}
1615 
1616 	/* get response */
1617 	status = LIRC_RET_SUCCESS;
1618 	state = P_BEGIN;
1619 	n = 0;
1620 	while (1) {
1621 		string = lirc_read_string(sockfd);
1622 		if (string == NULL)
1623 			return (-1);
1624 		switch (state) {
1625 		case P_BEGIN:
1626 			if (strcasecmp(string, "BEGIN") != 0) {
1627 				continue;
1628 			}
1629 			state = P_MESSAGE;
1630 			break;
1631 		case P_MESSAGE:
1632 			if (strncasecmp(string, command, strlen(string)) != 0 || strlen(string) + 1 != strlen(command)) {
1633 				state = P_BEGIN;
1634 				continue;
1635 			}
1636 			state = P_STATUS;
1637 			break;
1638 		case P_STATUS:
1639 			if (strcasecmp(string, "SUCCESS") == 0) {
1640 				status = LIRC_RET_SUCCESS;
1641 			} else if (strcasecmp(string, "END") == 0) {
1642 				status = LIRC_RET_SUCCESS;
1643 				goto good_packet;
1644 			} else if (strcasecmp(string, "ERROR") == 0) {
1645 				lirc_printf("%s: command failed: %s", lirc_prog, command);
1646 				status = LIRC_RET_ERROR;
1647 			} else {
1648 				goto bad_packet;
1649 			}
1650 			state = P_DATA;
1651 			break;
1652 		case P_DATA:
1653 			if (strcasecmp(string, "END") == 0) {
1654 				goto good_packet;
1655 			} else if (strcasecmp(string, "DATA") == 0) {
1656 				state = P_N;
1657 				break;
1658 			}
1659 			goto bad_packet;
1660 		case P_N:
1661 			errno = 0;
1662 			data_n = (__u32) strtoul(string, &endptr, 0);
1663 			if (!*string || *endptr) {
1664 				goto bad_packet;
1665 			}
1666 			if (data_n == 0) {
1667 				state = P_END;
1668 			} else {
1669 				state = P_DATA_N;
1670 			}
1671 			break;
1672 		case P_DATA_N:
1673 			len = strlen(string);
1674 			if (buf != NULL && written + len + 1 < max) {
1675 				memcpy(buf + written, string, len + 1);
1676 			}
1677 			written += len + 1;
1678 			n++;
1679 			if (n == data_n)
1680 				state = P_END;
1681 			break;
1682 		case P_END:
1683 			if (strcasecmp(string, "END") == 0) {
1684 				goto good_packet;
1685 			}
1686 			goto bad_packet;
1687 			break;
1688 		}
1689 	}
1690 
1691 	/* never reached */
1692 
1693 bad_packet:
1694 	lirc_printf("%s: bad return packet\n", lirc_prog);
1695 	return (-1);
1696 
1697 good_packet:
1698 	if (ret_status != NULL) {
1699 		*ret_status = status;
1700 	}
1701 	if (buf_len != NULL) {
1702 		*buf_len = written;
1703 	}
1704 	return (int)data_n;
1705 }
1706 
lirc_identify(int sockfd)1707 int lirc_identify(int sockfd)
1708 {
1709 	char command[10 + strlen(lirc_prog) + 1 + 1];
1710 	int success;
1711 
1712 	sprintf(command, "IDENT %s\n", lirc_prog);
1713 
1714 	(void)lirc_send_command(sockfd, command, NULL, NULL, &success);
1715 	return success;
1716 }
1717