| LIRC libraries LinuxInfraredRemoteControl

lirc_client.c
Go to the documentation of this file.
1 /****************************************************************************
2 ** lirc_client.c ***********************************************************
3 ****************************************************************************
4 *
5 * lirc_client - common routines for lircd clients
6 *
7 * Copyright (C) 1998 Trent Piepho <xyzzy@u.washington.edu>
8 * Copyright (C) 1998 Christoph Bartelmus <lirc@bartelmus.de>
9 *
10 * System wide LIRCRC support by Michal Svec <rebel@atrey.karlin.mff.cuni.cz>
11 */
12
19 #ifdef HAVE_CONFIG_H
20 # include <config.h>
21 #endif
22
23 #include <errno.h>
24 #include <libgen.h>
25 #include <limits.h>
26 #include <netdb.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <stdarg.h>
30 #include <string.h>
31 #include <strings.h>
32 #include <sys/param.h>
33 #include <sys/socket.h>
34 #include <sys/stat.h>
35 #include <sys/types.h>
36 #include <sys/time.h>
37 #include <sys/wait.h>
38 #include <sys/un.h>
39 #include <unistd.h>
40
41 #include "lirc_client.h"
42
44 static const struct timeval CMD_TIMEOUT = { .tv_sec = 1, .tv_usec = 0 };
45
46
47 // Until we have working client logging...
48 #define logprintf(level, fmt, args ...) syslog(level, fmt, ## args)
49 #define LIRC_WARNING LOG_WARNING
50 #define LIRC_DEBUG LOG_DEBUG
51 #define LIRC_NOTICE LOG_NOTICE
52 #define LIRC_ERROR LOG_ERR
53
54 /* internal defines */
55 #define MAX_INCLUDES 10
56 #define LIRC_READ 255
57 #define LIRC_PACKET_SIZE 255
58 /* three seconds */
59 #define LIRC_TIMEOUT 3
60
61 /* internal data structures */
62 struct filestack_t {
63 FILE* file;
64 char* name;
65 int line;
66 struct filestack_t* parent;
67 };
68
69
71 enum packet_state {
72 P_BEGIN,
73 P_MESSAGE,
74 P_STATUS,
75 P_DATA,
76 P_N,
77 P_DATA_N,
78 P_END
79 };
80
81
82 /*
83 * lircrc_config relies on this function, hence don't make it static
84 * but it's not part of the official interface, so there's no guarantee
85 * that it will stay available in the future
86 */
87 unsigned int lirc_flags(char* string);
88
89 static int lirc_lircd;
90 static int lirc_verbose = 0;
91 static char* lirc_prog = NULL;
92 static char* lirc_buffer = NULL;
93
94 char* prog;
95
97 static inline void
98 chk_write(int fd, const void* buf, size_t count, const char* msg)
99 {
100 if (write(fd, buf, count) == -1)
101 perror(msg);
102 }
103
104
105 int lirc_command_init(lirc_cmd_ctx* ctx, const char* fmt, ...)
106 {
107 va_list ap;
108 int n;
109
110 memset(ctx, 0, sizeof(lirc_cmd_ctx));
111 va_start(ap, fmt);
112 n = vsnprintf(ctx->packet, PACKET_SIZE, fmt, ap);
113 va_end(ap);
114 if (n >= PACKET_SIZE) {
115 logprintf(LIRC_NOTICE, "Message too big: %s", ctx->packet);
116 return EMSGSIZE;
117 }
118 return 0;
119 }
120
121
122 void lirc_command_reply_to_stdout(lirc_cmd_ctx* ctx)
123 {
124 ctx->reply_to_stdout = 1;
125 }
126
127
129 static int fill_string(int fd, lirc_cmd_ctx* cmd)
130 {
131 ssize_t n;
132
133 setsockopt(fd,
134 SOL_SOCKET,
135 SO_RCVTIMEO,
136 (const void*)&CMD_TIMEOUT,
137 sizeof(CMD_TIMEOUT));
138 n = read(fd, cmd->buffer + cmd->head, PACKET_SIZE - cmd->head);
139 if (n == -1) {
140 if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
141 logprintf(LIRC_NOTICE, "fill_string: timeout\n");
142 return EAGAIN;
143 }
144 cmd->head = 0;
145 return errno;
146 }
147 cmd->head += n;
148 return 0;
149 }
150
151
153 static int read_string(lirc_cmd_ctx* cmd, int fd, const char** string)
154 {
155 int r;
156 int skip;
157
158 /* Move remaining data to start of buffer, overwriting previous line. */
159 if (cmd->next != NULL && cmd->next != cmd->buffer) {
160 skip = cmd->next - cmd->buffer;
161 memmove(cmd->buffer, cmd->next, cmd->head - skip);
162 cmd->head -= skip;
163 cmd->next = cmd->buffer;
164 cmd->buffer[cmd->head] = '\0';
165 }
166 /* If no complete line is available, load more bytes from fd. */
167 if (cmd->next == NULL || strchr(cmd->next, '\n') == NULL) {
168 r = fill_string(fd, cmd);
169 if (r > 0)
170 return r;
171 cmd->next = cmd->buffer;
172 }
173 /* cmd->next == cmd->buffer here in all cases. */
174 *string = cmd->next;
175 /* Separate current line from the remaining lines, if available. */
176 cmd->next = strchr(cmd->next, '\n');
177 if (cmd->next != NULL) {
178 *(cmd->next) = '\0';
179 cmd->next++;
180 }
181 return 0;
182 }
183
184
185 int lirc_command_run(lirc_cmd_ctx* ctx, int fd)
186 {
187 int done, todo;
188 const char* string = NULL;
189 const char* data;
190 char* endptr;
191 enum packet_state state;
192 int status, n, r;
193 __u32 data_n = 0;
194
195 todo = strlen(ctx->packet);
196 data = ctx->packet;
197 logprintf(LIRC_DEBUG, "lirc_command_run: Sending: %s", data);
198 while (todo > 0) {
199 done = write(fd, (void*)data, todo);
200 if (done < 0) {
201 logprintf(LIRC_WARNING,
202 "%s: could not send packet\n", prog);
203 perror(prog);
204 return done;
205 }
206 data += done;
207 todo -= done;
208 }
209
210 /* get response */
211 status = 0;
212 n = 0;
213 state = P_BEGIN;
214 while (1) {
215 do
216 r = read_string(ctx, fd, &string);
217 while (r == EAGAIN);
218 if (!string || strlen(string) == 0)
219 goto bad_packet;
220 logprintf(LIRC_DEBUG,
221 "lirc_command_run, state: %d, input: \"%s\"\n",
222 state, string ? string : "(Null)");
223 switch (state) {
224 case P_BEGIN:
225 if (strcasecmp(string, "BEGIN") != 0)
226 break;
227 state = P_MESSAGE;
228 continue;
229 case P_MESSAGE:
230 if (strncasecmp(string, ctx->packet,
231 strlen(string)) != 0
232 || strcspn(string, "\n")
233 != strcspn(ctx->packet, "\n")) {
234 state = P_BEGIN;
235 break;
236 }
237 state = P_STATUS;
238 continue;
239 case P_STATUS:
240 if (strcasecmp(string, "SUCCESS") == 0) {
241 status = 0;
242 } else if (strcasecmp(string, "END") == 0) {
243 logprintf(LIRC_NOTICE,
244 "lirc_command_run: status:END");
245 return 0;
246 } else if (strcasecmp(string, "ERROR") == 0) {
247 logprintf(LIRC_WARNING,
248 "%s: command failed: %s",
249 prog, ctx->packet);
250 status = EIO;
251 } else {
252 goto bad_packet;
253 }
254 state = P_DATA;
255 break;
256 case P_DATA:
257 if (strcasecmp(string, "END") == 0) {
258 logprintf(LIRC_NOTICE,
259 "lirc_command_run: data:END, status:%d",
260 status);
261 return status;
262 } else if (strcasecmp(string, "DATA") == 0) {
263 state = P_N;
264 break;
265 }
266 logprintf(LIRC_DEBUG,
267 "data: bad packet: %s\n",
268 string);
269 goto bad_packet;
270 case P_N:
271 errno = 0;
272 data_n = (__u32)strtoul(string, &endptr, 0);
273 if (!*string || *endptr)
274 goto bad_packet;
275 if (data_n == 0)
276 state = P_END;
277 else
278 state = P_DATA_N;
279 break;
280 case P_DATA_N:
281 if (n == 0) {
282 if (ctx->reply_to_stdout)
283 puts("");
284 else
285 strcpy(ctx->reply, "");
286 }
287 if (ctx->reply_to_stdout) {
288 chk_write(STDOUT_FILENO, string, strlen(string),
289 "reply (1)");
290 chk_write(STDOUT_FILENO, "\n", 1, "reply (2)");
291 } else {
292 strncpy(ctx->reply,
293 string,
294 PACKET_SIZE - strlen(ctx->reply));
295 }
296 n++;
297 if (n == data_n)
298 state = P_END;
299 break;
300 case P_END:
301 if (strcasecmp(string, "END") == 0) {
302 logprintf(LIRC_NOTICE,
303 "lirc_command_run: status:END, status:%d",
304 status);
305 return status;
306 }
307 goto bad_packet;
308 }
309 }
310 bad_packet:
311 logprintf(LIRC_WARNING, "%s: bad return packet\n", prog);
312 logprintf(LIRC_DEBUG, "State %d: bad packet: %s\n", status, string);
313 return EPROTO;
314 }
315
316
317 static void lirc_printf(const char* format_str, ...)
318 {
319 va_list ap;
320
321 if (!lirc_verbose)
322 return;
323
324 va_start(ap, format_str);
325 vfprintf(stderr, format_str, ap);
326 va_end(ap);
327 }
328
329
330 static void lirc_perror(const char* s)
331 {
332 if (!lirc_verbose)
333 return;
334
335 perror(s);
336 }
337
338
339 int lirc_init(const char* prog, int verbose)
340 {
341 if (prog == NULL || lirc_prog != NULL)
342 return -1;
343 lirc_lircd = lirc_get_local_socket(NULL, !verbose);
344 if (lirc_lircd >= 0) {
345 lirc_verbose = verbose;
346 lirc_prog = strdup(prog);
347 if (lirc_prog == NULL) {
348 lirc_printf("%s: out of memory\n", prog);
349 return -1;
350 }
351 return lirc_lircd;
352 }
353 lirc_printf("%s: could not open socket: %s\n",
354 lirc_prog,
355 strerror(-lirc_lircd));
356 return -1;
357 }
358
359
360 int lirc_deinit(void)
361 {
362 if (lirc_prog != NULL) {
363 free(lirc_prog);
364 lirc_prog = NULL;
365 }
366 if (lirc_buffer != NULL) {
367 free(lirc_buffer);
368 lirc_buffer = NULL;
369 }
370 return close(lirc_lircd);
371 }
372
373
374 static int lirc_readline(char** line, FILE* f)
375 {
376 char* newline;
377 char* ret;
378 char* enlargeline;
379 int len;
380
381 newline = (char*)malloc(LIRC_READ + 1);
382 if (newline == NULL) {
383 lirc_printf("%s: out of memory\n", lirc_prog);
384 return -1;
385 }
386 len = 0;
387 while (1) {
388 ret = fgets(newline + len, LIRC_READ + 1, f);
389 if (ret == NULL) {
390 if (feof(f) && len > 0) {
391 *line = newline;
392 } else {
393 free(newline);
394 *line = NULL;
395 }
396 return 0;
397 }
398 len = strlen(newline);
399 if (newline[len - 1] == '\n') {
400 newline[len - 1] = 0;
401 *line = newline;
402 return 0;
403 }
404
405 enlargeline = (char*)realloc(newline, len + 1 + LIRC_READ);
406 if (enlargeline == NULL) {
407 free(newline);
408 lirc_printf("%s: out of memory\n", lirc_prog);
409 return -1;
410 }
411 newline = enlargeline;
412 }
413 }
414
415
416 static char* lirc_trim(char* s)
417 {
418 int len;
419
420 while (s[0] == ' ' || s[0] == '\t')
421 s++;
422 len = strlen(s);
423 while (len > 0) {
424 len--;
425 if (s[len] == ' ' || s[len] == '\t')
426 s[len] = 0;
427 else
428 break;
429 }
430 return s;
431 }
432
433
434 /* parse standard C escape sequences + \@,\A-\Z is ^@,^A-^Z */
435 static char lirc_parse_escape(char** s, const char* name, int line)
436 {
437 char c;
438 unsigned int i, overflow, count;
439 int digits_found, digit;
440
441 c = **s;
442 (*s)++;
443 switch (c) {
444 case 'a':
445 return '\a';
446 case 'b':
447 return '\b';
448 case 'e':
449 #if 0
450 case 'E': /* this should become ^E */
451 #endif
452 return 033;
453 case 'f':
454 return '\f';
455 case 'n':
456 return '\n';
457 case 'r':
458 return '\r';
459 case 't':
460 return '\t';
461 case 'v':
462 return '\v';
463 case '\n':
464 return 0;
465 case 0:
466 (*s)--;
467 return 0;
468 case '0':
469 case '1':
470 case '2':
471 case '3':
472 case '4':
473 case '5':
474 case '6':
475 case '7':
476 i = c - '0';
477 count = 0;
478
479 while (++count < 3) {
480 c = *(*s)++;
481 if (c >= '0' && c <= '7') {
482 i = (i << 3) + c - '0';
483 } else {
484 (*s)--;
485 break;
486 }
487 }
488 if (i > (1 << CHAR_BIT) - 1) {
489 i &= (1 << CHAR_BIT) - 1;
490 lirc_printf(
491 "%s: octal escape sequence out of range in %s:%d\n",
492 lirc_prog, name, line);
493 }
494 return (char)i;
495 case 'x':
496 {
497 i = 0;
498 overflow = 0;
499 digits_found = 0;
500 for (;; ) {
501 c = *(*s)++;
502 if (c >= '0' && c <= '9') {
503 digit = c - '0';
504 } else if (c >= 'a' && c <= 'f') {
505 digit = c - 'a' + 10;
506 } else if (c >= 'A' && c <= 'F') {
507 digit = c - 'A' + 10;
508 } else {
509 (*s)--;
510 break;
511 }
512 overflow |= i ^ (i << 4 >> 4);
513 i = (i << 4) + digit;
514 digits_found = 1;
515 }
516 if (!digits_found)
517 lirc_printf("%s: \\x used with no "
518 "following hex digits in %s:%d\n",
519 lirc_prog, name, line);
520 if (overflow || i > (1 << CHAR_BIT) - 1) {
521 i &= (1 << CHAR_BIT) - 1;
522 lirc_printf("%s: hex escape sequence out "
523 "of range in %s:%d\n", lirc_prog, name,
524 line);
525 }
526 return (char)i;
527 }
528 default:
529 if (c >= '@' && c <= 'Z')
530 return c - '@';
531 return c;
532 }
533 }
534
535
536 static void lirc_parse_string(char* s, const char* name, int line)
537 {
538 char* t;
539
540 t = s;
541 while (*s != 0) {
542 if (*s == '\\') {
543 s++;
544 *t = lirc_parse_escape(&s, name, line);
545 t++;
546 } else {
547 *t = *s;
548 s++;
549 t++;
550 }
551 }
552 *t = 0;
553 }
554
555
556 static void lirc_parse_include(char* s, const char* name, int line)
557 {
558 char last;
559 size_t len;
560
561 len = strlen(s);
562 if (len < 2)
563 return;
564 last = s[len - 1];
565 if (*s != '"' && *s != '<')
566 return;
567 if (*s == '"' && last != '"')
568 return;
569 else if (*s == '<' && last != '>')
570 return;
571 s[len - 1] = 0;
572 memmove(s, s + 1, len - 2 + 1); /* terminating 0 is copied */
573 }
574
575
576 int lirc_mode(char* token, char* token2, char** mode,
577 struct lirc_config_entry** new_config,
578 struct lirc_config_entry** first_config,
579 struct lirc_config_entry** last_config,
580 int (check) (char* s),
581 const char* name,
582 int line)
583 {
584 struct lirc_config_entry* new_entry;
585
586 new_entry = *new_config;
587 if (strcasecmp(token, "begin") == 0) {
588 if (token2 == NULL) {
589 if (new_entry == NULL) {
590 new_entry = (struct lirc_config_entry*)
591 malloc(sizeof(struct lirc_config_entry));
592 if (new_entry == NULL) {
593 lirc_printf("%s: out of memory\n",
594 lirc_prog);
595 return -1;
596 }
597 new_entry->prog = NULL;
598 new_entry->code = NULL;
599 new_entry->rep_delay = 0;
600 new_entry->ign_first_events = 0;
601 new_entry->rep = 0;
602 new_entry->config = NULL;
603 new_entry->change_mode = NULL;
604 new_entry->flags = none;
605 new_entry->mode = NULL;
606 new_entry->next_config = NULL;
607 new_entry->next_code = NULL;
608 new_entry->next = NULL;
609 *new_config = new_entry;
610 } else {
611 lirc_printf("%s: bad file format, %s:%d\n",
612 lirc_prog, name, line);
613 return -1;
614 }
615 } else {
616 if (new_entry == NULL && *mode == NULL) {
617 *mode = strdup(token2);
618 if (*mode == NULL)
619 return -1;
620 } else {
621 lirc_printf("%s: bad file format, %s:%d\n",
622 lirc_prog, name, line);
623 return -1;
624 }
625 }
626 } else if (strcasecmp(token, "end") == 0) {
627 if (token2 == NULL) {
628 if (new_entry != NULL) {
629 #if 0
630 if (new_entry->prog == NULL) {
631 lirc_printf(
632 "%s: prog missing in config before line %d\n", lirc_prog,
633 line);
634 lirc_freeconfigentries(new_entry);
635 *new_config = NULL;
636 return -1;
637 }
638 if (strcasecmp(new_entry->prog,
639 lirc_prog) != 0) {
640 lirc_freeconfigentries(new_entry);
641 *new_config = NULL;
642 return 0;
643 }
644 #endif
645 new_entry->next_code = new_entry->code;
646 new_entry->next_config = new_entry->config;
647 if (*last_config == NULL) {
648 *first_config = new_entry;
649 *last_config = new_entry;
650 } else {
651 (*last_config)->next = new_entry;
652 *last_config = new_entry;
653 }
654 *new_config = NULL;
655
656 if (*mode != NULL) {
657 new_entry->mode = strdup(*mode);
658 if (new_entry->mode == NULL) {
659 lirc_printf(
660 "%s: out of memory\n",
661 lirc_prog);
662 return -1;
663 }
664 }
665
666 if (check != NULL &&
667 new_entry->prog != NULL &&
668 strcasecmp(new_entry->prog,
669 lirc_prog) == 0) {
670 struct lirc_list* list;
671
672 list = new_entry->config;
673 while (list != NULL) {
674 if (check(list->string) == -1)
675 return -1;
676 list = list->next;
677 }
678 }
679
680 if (new_entry->rep_delay == 0 &&
681 new_entry->rep > 0)
682 new_entry->rep_delay = new_entry->rep -
683 1;
684 } else {
685 lirc_printf(
686 "%s: %s:%d: 'end' without 'begin'\n",
687 lirc_prog, name, line);
688 return -1;
689 }
690 } else {
691 if (*mode != NULL) {
692 if (new_entry != NULL) {
693 lirc_printf(
694 "%s: %s:%d: missing 'end' token\n",
695 lirc_prog, name, line);
696 return -1;
697 }
698 if (strcasecmp(*mode, token2) == 0) {
699 free(*mode);
700 *mode = NULL;
701 } else {
702 lirc_printf("%s: \"%s\" doesn't "
703 "match mode \"%s\"\n",
704 lirc_prog, token2, *mode);
705 return -1;
706 }
707 } else {
708 lirc_printf(
709 "%s: %s:%d: 'end %s' without 'begin'\n",
710 lirc_prog, name, line, token2);
711 return -1;
712 }
713 }
714 } else {
715 lirc_printf("%s: unknown token \"%s\" in %s:%d ignored\n",
716 lirc_prog, token, name, line);
717 }
718 return 0;
719 }
720
721
722 unsigned int lirc_flags(char* string)
723 {
724 char* s;
725 unsigned int flags;
726
727 flags = none;
728 s = strtok(string, " \t|");
729 while (s) {
730 if (strcasecmp(s, "once") == 0)
731 flags |= once;
732 else if (strcasecmp(s, "quit") == 0)
733 flags |= quit;
734 else if (strcasecmp(s, "mode") == 0)
735 flags |= mode;
736 else if (strcasecmp(s, "startup_mode") == 0)
737 flags |= startup_mode;
738 else if (strcasecmp(s, "toggle_reset") == 0)
739 flags |= toggle_reset;
740 else
741 lirc_printf("%s: unknown flag \"%s\"\n", lirc_prog, s);
742 s = strtok(NULL, " \t");
743 }
744 return flags;
745 }
746
747
748
749
750
751
757 static char* get_homepath(void)
758 {
759 char* home;
760 char* filename;
761
762 filename = malloc(MAXPATHLEN);
763 if (filename == NULL) {
764 lirc_printf("%s: out of memory\n", lirc_prog);
765 return NULL;
766 }
767 home = getenv("HOME");
768 home = home == NULL ? "/" : home;
769 strncpy(filename, home, MAXPATHLEN);
770 if (filename[strlen(filename) - 1] == '/')
771 filename[strlen(filename) - 1] = '\0';
772 return filename;
773 }
774
775
781 static char* get_freedesktop_path(void)
782 {
783 char* path;
784
785 if (getenv("XDG_CONFIG_HOME") != NULL) {
786 path = malloc(MAXPATHLEN);
787 strncpy(path, getenv("XDG_CONFIG_HOME"), MAXPATHLEN);
788 strncat(path, "/", MAXPATHLEN - strlen(path));
789 strncat(path, CFG_LIRCRC, MAXPATHLEN - strlen(path));
790 } else {
791 path = get_homepath();
792 if (path == NULL)
793 return NULL;
794 strncat(path, "/.config/lircrc", MAXPATHLEN - strlen(path) - 1);
795 }
796 if (access(path, R_OK) != 0)
797 path[0] = '\0';
798 return path;
799 }
800
801
802 static char* lirc_getfilename(const char* file, const char* current_file)
803 {
804 char* filename;
805
806 if (file == NULL) {
807 filename = get_freedesktop_path();
808 if (filename == NULL) {
809 return NULL;
810 } else if (strlen(filename) == 0) {
811 free(filename);
812 filename = get_homepath();
813 if (filename == NULL)
814 return NULL;
815 strcat(filename, "/" LIRCRC_USER_FILE);
816 }
817 filename = realloc(filename, strlen(filename) + 1);
818 } else if (strncmp(file, "~/", 2) == 0) {
819 filename = get_homepath();
820 if (filename == NULL)
821 return NULL;
822 strcat(filename, file + 1);
823 filename = realloc(filename, strlen(filename) + 1);
824 } else if (file[0] == '/' || current_file == NULL) {
825 /* absolute path or root */
826 filename = strdup(file);
827 if (filename == NULL) {
828 lirc_printf("%s: out of memory\n", lirc_prog);
829 return NULL;
830 }
831 } else {
832 /* get path from parent filename */
833 int pathlen = strlen(current_file);
834
835 while (pathlen > 0 && current_file[pathlen - 1] != '/')
836 pathlen--;
837 filename = (char*)malloc(pathlen + strlen(file) + 1);
838 if (filename == NULL) {
839 lirc_printf("%s: out of memory\n", lirc_prog);
840 return NULL;
841 }
842 memcpy(filename, current_file, pathlen);
843 filename[pathlen] = 0;
844 strcat(filename, file);
845 }
846 return filename;
847 }
848
849
850 static FILE* lirc_open(const char* file,
851 const char* current_file,
852 char** full_name)
853 {
854 FILE* fin;
855 char* filename;
856
857 filename = lirc_getfilename(file, current_file);
858 if (filename == NULL)
859 return NULL;
860
861 fin = fopen(filename, "r");
862 if (fin == NULL && (file != NULL || errno != ENOENT)) {
863 lirc_printf("%s: could not open config file %s\n", lirc_prog,
864 filename);
865 lirc_perror(lirc_prog);
866 } else if (fin == NULL) {
867 const char* root_file = LIRCRC_ROOT_FILE;
868
869 fin = fopen(root_file, "r");
870 if (fin == NULL && errno == ENOENT) {
871 int save_errno = errno;
872
873 root_file = LIRCRC_OLD_ROOT_FILE;
874 fin = fopen(root_file, "r");
875 errno = save_errno;
876 }
877 if (fin == NULL && errno != ENOENT) {
878 lirc_printf("%s: could not open config file %s\n",
879 lirc_prog, LIRCRC_ROOT_FILE);
880 lirc_perror(lirc_prog);
881 } else if (fin == NULL) {
882 lirc_printf("%s: could not open config files "
883 "%s and %s\n", lirc_prog, filename,
884 LIRCRC_ROOT_FILE);
885 lirc_perror(lirc_prog);
886 } else {
887 free(filename);
888 filename = strdup(root_file);
889 if (filename == NULL) {
890 fclose(fin);
891 lirc_printf("%s: out of memory\n", lirc_prog);
892 return NULL;
893 }
894 }
895 }
896 if (full_name && fin != NULL)
897 *full_name = filename;
898 else
899 free(filename);
900 return fin;
901 }
902
903
904 static struct filestack_t* stack_push(struct filestack_t* parent)
905 {
906 struct filestack_t* entry;
907
908 entry = malloc(sizeof(struct filestack_t));
909 if (entry == NULL) {
910 lirc_printf("%s: out of memory\n", lirc_prog);
911 return NULL;
912 }
913 entry->file = NULL;
914 entry->name = NULL;
915 entry->line = 0;
916 entry->parent = parent;
917 return entry;
918 }
919
920
921 static struct filestack_t* stack_pop(struct filestack_t* entry)
922 {
923 struct filestack_t* parent = NULL;
924
925 if (entry) {
926 parent = entry->parent;
927 if (entry->name)
928 free(entry->name);
929 free(entry);
930 }
931 return parent;
932 }
933
934
935 static void stack_free(struct filestack_t* entry)
936 {
937 while (entry)
938 entry = stack_pop(entry);
939 }
940
941
942 static char* lirc_startupmode(struct lirc_config_entry* first)
943 {
944 struct lirc_config_entry* scan;
945 char* startupmode;
946
947 startupmode = NULL;
948 scan = first;
949 /* Set a startup mode based on flags=startup_mode */
950 while (scan != NULL) {
951 if (scan->flags & startup_mode) {
952 if (scan->change_mode != NULL) {
953 startupmode = scan->change_mode;
954 /* Remove the startup mode or it confuses lirc mode system */
955 scan->change_mode = NULL;
956 break;
957 }
958 lirc_printf("%s: startup_mode flags requires 'mode ='\n", lirc_prog);
959 }
960 scan = scan->next;
961 }
962
963 /* Set a default mode if we find a mode = client app name */
964 if (startupmode == NULL) {
965 scan = first;
966 while (scan != NULL) {
967 if (scan->mode != NULL
968 && strcasecmp(lirc_prog, scan->mode) == 0) {
969 startupmode = lirc_prog;
970 break;
971 }
972 scan = scan->next;
973 }
974 }
975
976 if (startupmode == NULL)
977 return NULL;
978 scan = first;
979 while (scan != NULL) {
980 if (scan->change_mode != NULL
981 && scan->flags & once
982 && strcasecmp(startupmode, scan->change_mode) == 0)
983 scan->flags |= ecno;
984 scan = scan->next;
985 }
986 return startupmode;
987 }
988
989
990 static void lirc_freeconfigentries(struct lirc_config_entry* first)
991 {
992 struct lirc_config_entry* c;
993 struct lirc_config_entry* config_temp;
994 struct lirc_list* list;
995 struct lirc_list* list_temp;
996 struct lirc_code* code;
997 struct lirc_code* code_temp;
998
999 c = first;
1000 while (c != NULL) {
1001 if (c->prog)
1002 free(c->prog);
1003 if (c->change_mode)
1004 free(c->change_mode);
1005 if (c->mode)
1006 free(c->mode);
1007
1008 code = c->code;
1009 while (code != NULL) {
1010 if (code->remote != NULL && code->remote != LIRC_ALL)
1011 free(code->remote);
1012 if (code->button != NULL && code->button != LIRC_ALL)
1013 free(code->button);
1014 code_temp = code->next;
1015 free(code);
1016 code = code_temp;
1017 }
1018
1019 list = c->config;
1020 while (list != NULL) {
1021 if (list->string)
1022 free(list->string);
1023 list_temp = list->next;
1024 free(list);
1025 list = list_temp;
1026 }
1027 config_temp = c->next;
1028 free(c);
1029 c = config_temp;
1030 }
1031 }
1032
1033
1034 static void
1035 parse_shebang(char* line, int depth, const char* path, char* buff, size_t size)
1036 {
1037 char* token;
1038 char my_path[128];
1039 const char* const SHEBANG_MSG =
1040 "Warning: Use of deprecated lircrc shebang."
1041 " Use lircrc_class instead.\n";
1042
1043 token = strtok(line, "#! ");
1044 buff[0] = '\0';
1045 if (depth > 1) {
1046 lirc_printf("Warning: ignoring shebang in included file.");
1047 return;
1048 }
1049 if (strcmp(token, "lircrc") == 0) {
1050 strncpy(my_path, path, sizeof(my_path) - 1);
1051 strncat(buff, basename(my_path), size - 1);
1052 lirc_printf(SHEBANG_MSG);
1053 } else {
1054 lirc_printf("Warning: bad shebang (ignored)");
1055 }
1056 }
1057
1058
1059 static int lirc_readconfig_only_internal(const char* file,
1060 struct lirc_config** config,
1061 int (check)(char* s),
1062 char** full_name)
1063 {
1064 const char* const INCLUDED_LIRCRC_CLASS =
1065 "Warning: lirc_class in included file (ignored)";
1066 char* string;
1067 char* eq;
1068 char* token;
1069 char* token2;
1070 char* token3;
1071 struct filestack_t* filestack;
1072 struct filestack_t* stack_tmp;
1073 int open_files;
1074 char lircrc_class[128] = { '\0' };
1075 struct lirc_config_entry* new_entry;
1076 struct lirc_config_entry* first;
1077 struct lirc_config_entry* last;
1078 char* mode;
1079 char* remote;
1080 int ret = 0;
1081 int firstline = 1;
1082 char* save_full_name = NULL;
1083
1084 filestack = stack_push(NULL);
1085 if (filestack == NULL)
1086 return -1;
1087 filestack->file = lirc_open(file, NULL, &(filestack->name));
1088 if (filestack->file == NULL) {
1089 stack_free(filestack);
1090 return -1;
1091 }
1092 filestack->line = 0;
1093 open_files = 1;
1094
1095 first = new_entry = last = NULL;
1096 mode = NULL;
1097 remote = LIRC_ALL;
1098 while (filestack) {
1099 ret = lirc_readline(&string, filestack->file);
1100 if (ret == -1 || string == NULL) {
1101 fclose(filestack->file);
1102 if (open_files == 1 && full_name != NULL) {
1103 save_full_name = filestack->name;
1104 filestack->name = NULL;
1105 }
1106 filestack = stack_pop(filestack);
1107 open_files--;
1108 continue;
1109 }
1110 /* check for sha-bang */
1111 if (firstline) {
1112 firstline = 0;
1113 if (strncmp(string, "#!", 2) == 0) {
1114 parse_shebang(string,
1115 open_files,
1116 file,
1117 lircrc_class,
1118 sizeof(lircrc_class));
1119 }
1120 }
1121 filestack->line++;
1122 eq = strchr(string, '=');
1123 if (eq == NULL) {
1124 token = strtok(string, " \t");
1125 if (token == NULL) {
1126 /* ignore empty line */
1127 } else if (token[0] == '#') {
1128 /* ignore comment */
1129 } else if (strcasecmp(token, "lircrc_class") == 0) {
1130 token2 = lirc_trim(strtok(NULL, ""));
1131 if (strlen(token2) == 0) {
1132 lirc_printf(
1133 "Warning: no lircrc_class");
1134 } else if (open_files == 1) {
1135 strncpy(lircrc_class,
1136 token2,
1137 sizeof(lircrc_class) - 1);
1138 } else {
1139 lirc_printf(INCLUDED_LIRCRC_CLASS);
1140 }
1141 } else if (strcasecmp(token, "include") == 0) {
1142 if (open_files >= MAX_INCLUDES) {
1143 lirc_printf("%s: too many files "
1144 "included at %s:%d\n",
1145 lirc_prog, filestack->name,
1146 filestack->line);
1147 ret = -1;
1148 } else {
1149 token2 = strtok(NULL, "");
1150 token2 = lirc_trim(token2);
1151 lirc_parse_include(token2,
1152 filestack->name,
1153 filestack->line);
1154 stack_tmp = stack_push(filestack);
1155 if (stack_tmp == NULL) {
1156 ret = -1;
1157 } else {
1158 stack_tmp->file =
1159 lirc_open(token2,
1160 filestack->name,
1161 &(stack_tmp->
1162 name));
1163 stack_tmp->line = 0;
1164 if (stack_tmp->file) {
1165 open_files++;
1166 filestack = stack_tmp;
1167 } else {
1168 stack_pop(stack_tmp);
1169 ret = -1;
1170 }
1171 }
1172 }
1173 } else {
1174 token2 = strtok(NULL, " \t");
1175 if (token2)
1176 token3 = strtok(NULL, " \t");
1177 if (token2 != NULL && token3 != NULL) {
1178 lirc_printf("%s: unexpected token in line %s:%d\n",
1179 lirc_prog, filestack->name, filestack->line);
1180 } else {
1181 ret = lirc_mode(token, token2, &mode,
1182 &new_entry, &first,
1183 &last,
1184 check, filestack->name,
1185 filestack->line);
1186 if (ret == 0) {
1187 if (remote != LIRC_ALL)
1188 free(remote);
1189 remote = LIRC_ALL;
1190 } else {
1191 if (mode != NULL) {
1192 free(mode);
1193 mode = NULL;
1194 }
1195 if (new_entry != NULL) {
1196 lirc_freeconfigentries(
1197 new_entry);
1198 new_entry = NULL;
1199 }
1200 }
1201 }
1202 }
1203 } else {
1204 eq[0] = 0;
1205 token = lirc_trim(string);
1206 token2 = lirc_trim(eq + 1);
1207 if (token[0] == '#') {
1208 /* ignore comment */
1209 } else if (new_entry == NULL) {
1210 lirc_printf("%s: bad file format, %s:%d\n",
1211 lirc_prog, filestack->name,
1212 filestack->line);
1213 ret = -1;
1214 } else {
1215 token2 = strdup(token2);
1216 if (token2 == NULL) {
1217 lirc_printf("%s: out of memory\n",
1218 lirc_prog);
1219 ret = -1;
1220 } else if (strcasecmp(token, "prog") == 0) {
1221 if (new_entry->prog != NULL)
1222 free(new_entry->prog);
1223 new_entry->prog = token2;
1224 } else if (strcasecmp(token, "remote") == 0) {
1225 if (remote != LIRC_ALL)
1226 free(remote);
1227
1228 if (strcasecmp("*", token2) == 0) {
1229 remote = LIRC_ALL;
1230 free(token2);
1231 } else {
1232 remote = token2;
1233 }
1234 } else if (strcasecmp(token, "button") == 0) {
1235 struct lirc_code* code;
1236
1237 code = (struct lirc_code*)
1238 malloc(sizeof(struct lirc_code));
1239 if (code == NULL) {
1240 free(token2);
1241 lirc_printf(
1242 "%s: out of memory\n",
1243 lirc_prog);
1244 ret = -1;
1245 } else {
1246 code->remote = remote;
1247 if (strcasecmp("*",
1248 token2) == 0) {
1249 code->button = LIRC_ALL;
1250 free(token2);
1251 } else {
1252 code->button = token2;
1253 }
1254 code->next = NULL;
1255
1256 if (new_entry->code == NULL)
1257 new_entry->code = code;
1258 else
1259 new_entry->next_code->
1260 next = code;
1261 new_entry->next_code = code;
1262 if (remote != LIRC_ALL) {
1263 remote = strdup(remote);
1264 if (remote == NULL) {
1265 lirc_printf(
1266 "%s: out of memory\n",
1267 lirc_prog);
1268 ret = -1;
1269 }
1270 }
1271 }
1272 } else if (strcasecmp(token, "delay") == 0) {
1273 char* end;
1274
1275 errno = ERANGE + 1;
1276 new_entry->rep_delay = strtoul(token2,
1277 &end, 0);
1278 if ((new_entry->rep_delay ==
1279 ULONG_MAX && errno == ERANGE)
1280 || end[0] != 0 || strlen(token2) ==
1281 0)
1282 lirc_printf("%s: \"%s\" not"
1283 " a valid number for delay\n", lirc_prog,
1284 token2);
1285 free(token2);
1286 } else if (strcasecmp(token, "ignore_first_events") == 0) {
1287 char* end;
1288
1289 errno = ERANGE + 1;
1290 new_entry->ign_first_events = strtoul(
1291 token2, &end, 0);
1292 if ((new_entry->ign_first_events ==
1293 ULONG_MAX && errno == ERANGE)
1294 || end[0] != 0 || strlen(token2) ==
1295 0)
1296 lirc_printf("%s: \"%s\" not"
1297 " a valid number for ignore_first_events\n",
1298 lirc_prog, token2);
1299 free(token2);
1300 } else if (strcasecmp(token, "repeat") == 0) {
1301 char* end;
1302
1303 errno = ERANGE + 1;
1304 new_entry->rep =
1305 strtoul(token2, &end, 0);
1306 if ((new_entry->rep == ULONG_MAX &&
1307 errno == ERANGE)
1308 || end[0] != 0 || strlen(token2) ==
1309 0)
1310 lirc_printf("%s: \"%s\" not"
1311 " a valid number for repeat\n", lirc_prog,
1312 token2);
1313 free(token2);
1314 } else if (strcasecmp(token, "config") == 0) {
1315 struct lirc_list* new_list;
1316
1317 new_list = (struct lirc_list*)
1318 malloc(sizeof(struct lirc_list));
1319 if (new_list == NULL) {
1320 free(token2);
1321 lirc_printf(
1322 "%s: out of memory\n",
1323 lirc_prog);
1324 ret = -1;
1325 } else {
1326 lirc_parse_string(token2,
1327 filestack->name,
1328 filestack->line);
1329 new_list->string = token2;
1330 new_list->next = NULL;
1331 if (new_entry->config == NULL)
1332 new_entry->config =
1333 new_list;
1334 else
1335 new_entry->next_config->
1336 next = new_list;
1337 new_entry->next_config =
1338 new_list;
1339 }
1340 } else if (strcasecmp(token, "mode") == 0) {
1341 if (new_entry->change_mode != NULL)
1342 free(new_entry->change_mode);
1343 new_entry->change_mode = token2;
1344 } else if (strcasecmp(token, "flags") == 0) {
1345 new_entry->flags = lirc_flags(token2);
1346 free(token2);
1347 } else {
1348 free(token2);
1349 lirc_printf(
1350 "%s: unknown token \"%s\" in %s:%d ignored\n",
1351 lirc_prog, token, filestack->name,
1352 filestack->line);
1353 }
1354 }
1355 }
1356 free(string);
1357 if (ret == -1)
1358 break;
1359 }
1360 if (remote != LIRC_ALL)
1361 free(remote);
1362 if (new_entry != NULL) {
1363 if (ret == 0) {
1364 ret = lirc_mode("end", NULL, &mode, &new_entry, &first,
1365 &last, check, "", 0);
1366 lirc_printf(
1367 "%s: warning: end token missing at end of file\n",
1368 lirc_prog);
1369 } else {
1370 lirc_freeconfigentries(new_entry);
1371 new_entry = NULL;
1372 }
1373 }
1374 if (mode != NULL) {
1375 if (ret == 0)
1376 lirc_printf(
1377 "%s: warning: no end token found for mode \"%s\"\n", lirc_prog,
1378 mode);
1379 free(mode);
1380 }
1381 if (ret == 0) {
1382 char* startupmode;
1383
1384 *config = (struct lirc_config*)
1385 malloc(sizeof(struct lirc_config));
1386 if (*config == NULL) {
1387 lirc_printf("%s: out of memory\n", lirc_prog);
1388 lirc_freeconfigentries(first);
1389 return -1;
1390 }
1391 (*config)->first = first;
1392 (*config)->next = first;
1393 startupmode = lirc_startupmode((*config)->first);
1394 (*config)->current_mode =
1395 startupmode ? strdup(startupmode) : NULL;
1396 if (lircrc_class[0] != '\0')
1397 (*config)->lircrc_class = strdup(lircrc_class);
1398 else
1399 (*config)->lircrc_class = NULL;
1400 (*config)->sockfd = -1;
1401 if (full_name != NULL) {
1402 *full_name = save_full_name;
1403 save_full_name = NULL;
1404 }
1405 } else {
1406 *config = NULL;
1407 lirc_freeconfigentries(first);
1408 }
1409 if (filestack)
1410 stack_free(filestack);
1411 if (save_full_name)
1412 free(save_full_name);
1413 return ret;
1414 }
1415
1416
1417 int lirc_identify(int sockfd)
1418 {
1419 lirc_cmd_ctx cmd;
1420 int ret;
1421
1422 ret = lirc_command_init(&cmd, "IDENT %s\n", lirc_prog);
1423 if (ret != 0)
1424 return ret;
1425 do
1426 ret = lirc_command_run(&cmd, sockfd);
1427 while (ret == EAGAIN || ret == EWOULDBLOCK);
1428 return ret == 0 ? LIRC_RET_SUCCESS : -1;
1429 }
1430
1431
1432
1433 int lirc_readconfig(const char* file,
1434 struct lirc_config** config,
1435 int (check)(char* s))
1436 {
1437 struct sockaddr_un addr;
1438 int sockfd = -1;
1439 char* filename;
1440 char command[128];
1441 int ret;
1442
1443 filename = NULL;
1444 if (lirc_readconfig_only_internal(file, config, check, &filename) == -1)
1445 return -1;
1446
1447 if ((*config)->lircrc_class == NULL)
1448 goto lirc_readconfig_compat;
1449
1450 /* connect to lircrcd */
1451
1452 addr.sun_family = AF_UNIX;
1453 if (lirc_getsocketname((*config)->lircrc_class,
1454 addr.sun_path,
1455 sizeof(addr.sun_path)) > sizeof(addr.sun_path)) {
1456 lirc_printf("%s: WARNING: file name too long\n", lirc_prog);
1457 goto lirc_readconfig_compat;
1458 }
1459 sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
1460 if (sockfd == -1) {
1461 lirc_printf("%s: WARNING: could not open socket\n", lirc_prog);
1462 lirc_perror(lirc_prog);
1463 goto lirc_readconfig_compat;
1464 }
1465 if (connect(sockfd, (struct sockaddr*)&addr, sizeof(addr)) != -1) {
1466 (*config)->sockfd = sockfd;
1467 free(filename);
1468
1469 /* tell daemon lirc_prog */
1470 if (lirc_identify(sockfd) == LIRC_RET_SUCCESS)
1471 /* we're connected */
1472 return 0;
1473 close(sockfd);
1474 lirc_freeconfig(*config);
1475 return -1;
1476 }
1477 close(sockfd);
1478 sockfd = -1;
1479
1480 /* launch lircrcd */
1481 snprintf(command, sizeof(command),
1482 "lircrcd %s", (*config)->lircrc_class);
1483 ret = system(command);
1484 if (ret == -1 || WEXITSTATUS(ret) != EXIT_SUCCESS)
1485 goto lirc_readconfig_compat;
1486 free(filename);
1487
1488 sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
1489 if (sockfd == -1) {
1490 lirc_printf("%s: WARNING: could not open socket\n", lirc_prog);
1491 lirc_perror(lirc_prog);
1492 goto lirc_readconfig_compat;
1493 }
1494 if (connect(sockfd, (struct sockaddr*)&addr, sizeof(addr)) != -1) {
1495 if (lirc_identify(sockfd) == LIRC_RET_SUCCESS) {
1496 (*config)->sockfd = sockfd;
1497 return 0;
1498 }
1499 }
1500 close(sockfd);
1501 lirc_freeconfig(*config);
1502 return -1;
1503
1504 lirc_readconfig_compat:
1505 /* compat fallback */
1506 if (sockfd != -1)
1507 close(sockfd);
1508 return 0;
1509 }
1510
1511
1512 int lirc_readconfig_only(const char* file,
1513 struct lirc_config** config,
1514 int (check) (char* s))
1515 {
1516 return lirc_readconfig_only_internal(file, config, check, NULL);
1517 }
1518
1519
1520 void lirc_freeconfig(struct lirc_config* config)
1521 {
1522 if (config != NULL) {
1523 if (config->sockfd != -1) {
1524 (void)close(config->sockfd);
1525 config->sockfd = -1;
1526 }
1527 if (config->lircrc_class != NULL)
1528 free(config->lircrc_class);
1529 lirc_freeconfigentries(config->first);
1530 free(config->current_mode);
1531 free(config);
1532 }
1533 }
1534
1535
1536 static void lirc_clearmode(struct lirc_config* config)
1537 {
1538 struct lirc_config_entry* scan;
1539
1540 if (config->current_mode == NULL)
1541 return;
1542 scan = config->first;
1543 while (scan != NULL) {
1544 if (scan->change_mode != NULL)
1545 if (strcasecmp(scan->change_mode,
1546 config->current_mode) == 0)
1547 scan->flags &= ~ecno;
1548 scan = scan->next;
1549 }
1550 free(config->current_mode);
1551 config->current_mode = NULL;
1552 }
1553
1554
1555 static char* lirc_execute(struct lirc_config* config,
1556 struct lirc_config_entry* scan)
1557 {
1558 char* s;
1559 int do_once = 1;
1560
1561 if (scan->flags & mode)
1562 lirc_clearmode(config);
1563 if (scan->change_mode != NULL) {
1564 free(config->current_mode);
1565 config->current_mode = strdup(scan->change_mode);
1566 if (scan->flags & once) {
1567 if (scan->flags & ecno)
1568 do_once = 0;
1569 else
1570 scan->flags |= ecno;
1571 }
1572 }
1573 if (scan->next_config != NULL
1574 && scan->prog != NULL
1575 && (lirc_prog == NULL || strcasecmp(scan->prog, lirc_prog) == 0)
1576 && do_once == 1) {
1577 s = scan->next_config->string;
1578 scan->next_config = scan->next_config->next;
1579 if (scan->next_config == NULL)
1580 scan->next_config = scan->config;
1581 return s;
1582 }
1583 return NULL;
1584 }
1585
1594 static int rep_filter(struct lirc_config_entry* scan, int rep)
1595 {
1596 int delay_start, rep_delay;
1597
1598 if (scan->ign_first_events) {
1599 if (scan->rep_delay && rep == 0) /* warn user only once */
1600 lirc_printf(
1601 "%s: ignoring \"delay\" because \"ignore_first_events\" is also set\n",
1602 lirc_prog);
1603 rep_delay = scan->ign_first_events;
1604 delay_start = 0;
1605 } else {
1606 rep_delay = scan->rep_delay;
1607 delay_start = 1;
1608 }
1609 /* handle event before delay_start */
1610 if (rep < delay_start)
1611 return 1;
1612 /* special case: 1 event after delay when repeat is not set */
1613 if (scan->rep == 0 && rep_delay > 0 && rep == rep_delay + delay_start)
1614 return 1;
1615 /* handle repeat */
1616 if (scan->rep > 0 && rep >= rep_delay + delay_start) {
1617 rep -= rep_delay + delay_start;
1618 return (rep % scan->rep) == 0;
1619 }
1620 return 0;
1621 }
1622
1623 static int lirc_iscode(struct lirc_config_entry* scan,
1624 char* remote,
1625 char* button,
1626 int rep)
1627 {
1628 struct lirc_code* codes;
1629
1630 /* no remote/button specified */
1631 if (scan->code == NULL)
1632 return rep_filter(scan, rep);
1633
1634 /* remote/button match? */
1635 if (scan->next_code->remote == LIRC_ALL
1636 || strcasecmp(scan->next_code->remote, remote) == 0) {
1637 if (scan->next_code->button == LIRC_ALL
1638 || strcasecmp(scan->next_code->button, button) == 0) {
1639 int iscode = 0;
1640 /* button sequence? */
1641 if (scan->code->next == NULL || rep == 0) {
1642 scan->next_code = scan->next_code->next;
1643 if (scan->code->next != NULL)
1644 iscode = 1;
1645 }
1646 /* sequence completed? */
1647 if (scan->next_code == NULL) {
1648 scan->next_code = scan->code;
1649 if (scan->code->next != NULL ||
1650 rep_filter(scan, rep))
1651 iscode = 2;
1652 }
1653 return iscode;
1654 }
1655 }
1656
1657 if (rep != 0)
1658 return 0;
1659
1660 /* handle toggle_reset */
1661 if (scan->flags & toggle_reset)
1662 scan->next_config = scan->config;
1663
1664 codes = scan->code;
1665 if (codes == scan->next_code)
1666 return 0;
1667 codes = codes->next;
1668 /* rebase code sequence */
1669 while (codes != scan->next_code->next) {
1670 struct lirc_code* prev;
1671 struct lirc_code* next;
1672 int flag = 1;
1673
1674 prev = scan->code;
1675 next = codes;
1676 while (next != scan->next_code) {
1677 if (prev->remote == LIRC_ALL
1678 || strcasecmp(prev->remote, next->remote) == 0) {
1679 if (prev->button == LIRC_ALL
1680 || strcasecmp(prev->button,
1681 next->button) == 0) {
1682 prev = prev->next;
1683 next = next->next;
1684 } else {
1685 flag = 0;
1686 break;
1687 }
1688 } else {
1689 flag = 0;
1690 break;
1691 }
1692 }
1693 if (flag == 1) {
1694 if (prev->remote == LIRC_ALL
1695 || strcasecmp(prev->remote, remote) == 0) {
1696 if (prev->button == LIRC_ALL
1697 || strcasecmp(prev->button, button) == 0) {
1698 if (rep == 0) {
1699 scan->next_code = prev->next;
1700 return 0;
1701 }
1702 }
1703 }
1704 }
1705 codes = codes->next;
1706 }
1707 scan->next_code = scan->code;
1708 return 0;
1709 }
1710
1711
1712 char* lirc_ir2char(struct lirc_config* config, char* code)
1713 {
1714 static int warning = 1;
1715 char* string;
1716
1717 if (warning) {
1718 fprintf(stderr, "%s: warning: lirc_ir2char() is obsolete\n",
1719 lirc_prog);
1720 warning = 0;
1721 }
1722 if (lirc_code2char(config, code, &string) == -1)
1723 return NULL;
1724 return string;
1725 }
1726
1727
1728 static int lirc_code2char_internal(struct lirc_config* config,
1729 char* code,
1730 char** string,
1731 char** prog)
1732 {
1733 int rep;
1734 char* backup;
1735 char* remote;
1736 char* button;
1737 char* s = NULL;
1738 struct lirc_config_entry* scan;
1739 int exec_level;
1740 int quit_happened;
1741
1742 *string = NULL;
1743 if (sscanf(code, "%*x %x %*s %*s\n", &rep) == 1) {
1744 backup = strdup(code);
1745 if (backup == NULL)
1746 return -1;
1747
1748 strtok(backup, " ");
1749 strtok(NULL, " ");
1750 button = strtok(NULL, " ");
1751 remote = strtok(NULL, "\n");
1752
1753 if (button == NULL || remote == NULL) {
1754 free(backup);
1755 return 0;
1756 }
1757
1758 scan = config->next;
1759 quit_happened = 0;
1760 while (scan != NULL) {
1761 exec_level = lirc_iscode(scan, remote, button, rep);
1762 if (exec_level > 0 &&
1763 (scan->mode == NULL ||
1764 (scan->mode != NULL &&
1765 config->current_mode != NULL &&
1766 strcasecmp(scan->mode,
1767 config->current_mode) == 0)) &&
1768 quit_happened == 0) {
1769 if (exec_level > 1) {
1770 s = lirc_execute(config, scan);
1771 if (s != NULL && prog != NULL)
1772 *prog = scan->prog;
1773 } else {
1774 s = NULL;
1775 }
1776 if (scan->flags & quit) {
1777 quit_happened = 1;
1778 config->next = NULL;
1779 scan = scan->next;
1780 continue;
1781 } else if (s != NULL) {
1782 config->next = scan->next;
1783 break;
1784 }
1785 }
1786 scan = scan->next;
1787 }
1788 free(backup);
1789 if (s != NULL) {
1790 *string = s;
1791 return 0;
1792 }
1793 }
1794 config->next = config->first;
1795 return 0;
1796 }
1797
1798
1799 int lirc_code2char(struct lirc_config* config, char* code, char** string)
1800 {
1801 lirc_cmd_ctx cmd;
1802 static char static_buff[PACKET_SIZE];
1803 int ret;
1804 char* my_code;
1805 char* pos;
1806
1807 my_code = strdup(code);
1808 pos = rindex(my_code, '\n');
1809 if (pos != NULL)
1810 *pos = '\0';
1811 ret = lirc_command_init(&cmd, "CODE %s\n", my_code);
1812 free(my_code);
1813 if (ret != 0)
1814 return -1;
1815 if (config->sockfd != -1) {
1816 do
1817 ret = lirc_command_run(&cmd, config->sockfd);
1818 while (ret == EAGAIN || ret == EWOULDBLOCK);
1819 if (ret == 0) {
1820 strncpy(static_buff, cmd.reply, PACKET_SIZE);
1821 *string = static_buff;
1822 }
1823 return ret == 0 ? 0 : -1;
1824 }
1825 return lirc_code2char_internal(config, code, string, NULL);
1826 }
1827
1828
1829 int lirc_code2charprog(struct lirc_config* config,
1830 char* code,
1831 char** string,
1832 char** prog)
1833 {
1834 char* backup;
1835 int ret;
1836
1837 backup = lirc_prog;
1838 lirc_prog = NULL;
1839
1840 ret = lirc_code2char_internal(config, code, string, prog);
1841
1842 lirc_prog = backup;
1843 return ret;
1844 }
1845
1846
1847 char* lirc_nextir(void)
1848 {
1849 static int warning = 1;
1850 char* code;
1851 int ret;
1852
1853 if (warning) {
1854 fprintf(stderr, "%s: warning: lirc_nextir() is obsolete\n",
1855 lirc_prog);
1856 warning = 0;
1857 }
1858 ret = lirc_nextcode(&code);
1859 if (ret == -1)
1860 return NULL;
1861 return code;
1862 }
1863
1864
1865 int lirc_nextcode(char** code)
1866 {
1867 static int packet_size = PACKET_SIZE;
1868 static int end_len = 0;
1869 ssize_t len = 0;
1870 char* end;
1871 char c;
1872
1873 *code = NULL;
1874 if (lirc_buffer == NULL) {
1875 lirc_buffer = (char*)malloc(packet_size + 1);
1876 if (lirc_buffer == NULL) {
1877 lirc_printf("%s: out of memory\n", lirc_prog);
1878 return -1;
1879 }
1880 lirc_buffer[0] = 0;
1881 }
1882 while ((end = strchr(lirc_buffer, '\n')) == NULL) {
1883 if (end_len >= packet_size) {
1884 char* new_buffer;
1885
1886 packet_size += PACKET_SIZE;
1887 new_buffer =
1888 (char*)realloc(lirc_buffer, packet_size + 1);
1889 if (new_buffer == NULL)
1890 return -1;
1891 lirc_buffer = new_buffer;
1892 }
1893 len = read(lirc_lircd, lirc_buffer + end_len,
1894 packet_size - end_len);
1895 if (len <= 0) {
1896 if (len == -1 && errno == EAGAIN)
1897 return 0;
1898 else
1899 return -1;
1900 }
1901 end_len += len;
1902 lirc_buffer[end_len] = 0;
1903 /* return if next code not yet available completely */
1904 end = strchr(lirc_buffer, '\n');
1905 if (end == NULL)
1906 return 0;
1907 }
1908 /* copy first line to buffer (code) and move remaining chars to
1909 * lirc_buffers start */
1910 end++;
1911 end_len = strlen(end);
1912 c = end[0];
1913 end[0] = 0;
1914 *code = strdup(lirc_buffer);
1915 end[0] = c;
1916 memmove(lirc_buffer, end, end_len + 1);
1917 if (*code == NULL)
1918 return -1;
1919 return 0;
1920 }
1921
1922
1923 size_t lirc_getsocketname(const char* id, char* buf, size_t size)
1924 {
1925 id = id != NULL ? id : "default";
1926 snprintf(buf, size, VARRUNDIR "/%d-%s-lircrcd.socket", getuid(), id);
1927 return strlen(buf);
1928 }
1929
1930
1931
1932 const char* lirc_getmode(struct lirc_config* config)
1933 {
1934 lirc_cmd_ctx cmd;
1935 static char static_buff[PACKET_SIZE];
1936 int ret;
1937
1938 if (config->sockfd != -1) {
1939 lirc_command_init(&cmd, "GETMODE\n");
1940 do
1941 ret = lirc_command_run(&cmd, config->sockfd);
1942 while (ret == EAGAIN || ret == EWOULDBLOCK);
1943 if (ret == 0) {
1944 strncpy(static_buff, cmd.reply, PACKET_SIZE);
1945 return static_buff;
1946 }
1947 return NULL;
1948 }
1949 return config->current_mode;
1950 }
1951
1952
1953 const char* lirc_setmode(struct lirc_config* config, const char* mode)
1954 {
1955 lirc_cmd_ctx cmd;
1956 int r;
1957 static char static_buff[PACKET_SIZE];
1958
1959 if (config->sockfd != -1) {
1960 if (mode != NULL)
1961 r = lirc_command_init(&cmd, "SETMODE %s\n", mode);
1962 else
1963 r = lirc_command_init(&cmd, "SETMODE\n");
1964 if (r != 0)
1965 return NULL;
1966 do
1967 r = lirc_command_run(&cmd, config->sockfd);
1968 while (r == EAGAIN || r == EWOULDBLOCK);
1969 if (r == 0) {
1970 strncpy(static_buff, cmd.reply, PACKET_SIZE);
1971 return static_buff;
1972 }
1973 return NULL;
1974 }
1975 free(config->current_mode);
1976 config->current_mode = mode ? strdup(mode) : NULL;
1977 return config->current_mode;
1978 }
1979
1980
1981 int lirc_send_one(int fd, const char* remote, const char* keysym)
1982 {
1983 int r;
1984 lirc_cmd_ctx command;
1985
1986 r = lirc_command_init(&command, "SEND_ONCE %s %s\n", remote, keysym);
1987 if (r != 0)
1988 return EMSGSIZE;
1989 do
1990 r = lirc_command_run(&command, fd);
1991 while (r == EAGAIN);
1992 return r;
1993 }
1994
1995
1996 int lirc_simulate(int fd,
1997 const char* remote,
1998 const char* keysym,
1999 int scancode,
2000 int repeat)
2001 {
2002 lirc_cmd_ctx cmd;
2003 int r;
2004
2005 r = lirc_command_init(&cmd, "SIMULATE %016x %02x %s %s\n",
2006 scancode, repeat, keysym, remote);
2007 if (r != 0)
2008 return EMSGSIZE;
2009 do
2010 r = lirc_command_run(&cmd, fd);
2011 while (r == EAGAIN);
2012 return r;
2013 }
2014
2015
2017 static int
2018 do_connect(int domain, struct sockaddr* addr, size_t size, int quiet)
2019 {
2020 int fd;
2021
2022 fd = socket(domain, SOCK_STREAM, 0);
2023 if (fd == -1) {
2024 if (!quiet) {
2025 fprintf(stderr, "do_connect: could not open socket\n");
2026 perror("open");
2027 }
2028 return -errno;
2029 }
2030 if (connect(fd, addr, size) == -1) {
2031 if (!quiet) {
2032 fprintf(stderr,
2033 "do_connect: could not connect to socket\n");
2034 perror("connect");
2035 }
2036 return -errno;
2037 }
2038 return fd;
2039 }
2040
2041
2042 int lirc_get_local_socket(const char* path, int quiet)
2043 {
2044 const char* socket_path;
2045 struct sockaddr_un addr_un;
2046
2047 socket_path = path ? path : getenv("LIRC_SOCKET_PATH");
2048 socket_path = socket_path ? socket_path : LIRCD;
2049 if (strlen(socket_path) + 1 > sizeof(addr_un.sun_path)) {
2050 /* path is longer than sockaddr_un.sun_path field (!) */
2051 if (!quiet)
2052 fprintf(stderr, "%s: socket name is too long\n", prog);
2053 return -ENAMETOOLONG;
2054 }
2055 addr_un.sun_family = AF_UNIX;
2056 strcpy(addr_un.sun_path, socket_path);
2057 return do_connect(AF_UNIX,
2058 (struct sockaddr*)&addr_un,
2059 sizeof(addr_un),
2060 quiet);
2061 }
2062
2063
2064 int lirc_get_remote_socket(const char* address, int port, int quiet)
2065 {
2066 struct addrinfo* addrinfos;
2067 struct addrinfo* a;
2068 char service[64];
2069 int r;
2070
2071 snprintf(service, sizeof(service),
2072 "%d", port > 0 ? port : LIRC_INET_PORT);
2073 r = getaddrinfo(address, service, NULL, &addrinfos);
2074 if (r < 0) {
2075 if (!quiet)
2076 fprintf(stderr, "get_remote_socket: host %s unknown\n",
2077 address);
2078 return -EADDRNOTAVAIL;
2079 }
2080 for (a = addrinfos; a != NULL; a = a->ai_next) {
2081 r = do_connect(a->ai_family, a->ai_addr, a->ai_addrlen, quiet);
2082 if (r >= 0)
2083 break;
2084 };
2085 freeaddrinfo(addrinfos);
2086 return r;
2087 }
LIRCRC_ROOT_FILE
#define LIRCRC_ROOT_FILE
Definition: lirc_config.h:68
chk_write
#define chk_write(fd, buf, count)
Definition: lirc_log.h:215
lirc_command_reply_to_stdout
void lirc_command_reply_to_stdout(lirc_cmd_ctx *ctx)
Definition: lirc_client.c:122
lirc_config_entry
Definition: lirc_client.h:169
lirc_init
int lirc_init(const char *prog, int verbose)
Definition: lirc_client.c:339
lirc_setmode
const char * lirc_setmode(struct lirc_config *config, const char *mode)
Definition: lirc_client.c:1953
lirc_cmd_ctx::reply
char reply[PACKET_SIZE+1]
Definition: lirc_client.h:195
lirc_get_local_socket
int lirc_get_local_socket(const char *path, int quiet)
Definition: lirc_client.c:2042
lirc_cmd_ctx::buffer
char buffer[PACKET_SIZE+1]
Definition: lirc_client.h:194
lirc_command_run
int lirc_command_run(lirc_cmd_ctx *ctx, int fd)
Definition: lirc_client.c:185
LIRCRC_OLD_ROOT_FILE
#define LIRCRC_OLD_ROOT_FILE
Definition: lirc_config.h:71
lirc_code
Definition: lirc_client.h:154
lirc_config::lircrc_class
char * lircrc_class
Definition: lirc_client.h:161
lirc_getmode
const char * lirc_getmode(struct lirc_config *config)
Definition: lirc_client.c:1932
PACKET_SIZE
#define PACKET_SIZE
Definition: lirc_config.h:98
lirc_simulate
int lirc_simulate(int fd, const char *remote, const char *keysym, int scancode, int repeat)
Definition: lirc_client.c:1996
lirc_getsocketname
size_t lirc_getsocketname(const char *id, char *buf, size_t size)
Definition: lirc_client.c:1923
lirc_command_init
int lirc_command_init(lirc_cmd_ctx *ctx, const char *fmt,...)
Definition: lirc_client.c:105
packet_state
packet_state
Definition: lirc_client.c:71
LIRC_INET_PORT
#define LIRC_INET_PORT
Definition: lirc_config.h:34
lirc_cmd_ctx::head
int head
Definition: lirc_client.h:196
lirc_nextcode
int lirc_nextcode(char **code)
Definition: lirc_client.c:1865
lirc_get_remote_socket
int lirc_get_remote_socket(const char *address, int port, int quiet)
Definition: lirc_client.c:2064
lirc_code2char
int lirc_code2char(struct lirc_config *config, char *code, char **string)
Definition: lirc_client.c:1799
lirc_cmd_ctx
Definition: lirc_client.h:192
lirc_readconfig_only
int lirc_readconfig_only(const char *file, struct lirc_config **config, int(check)(char *s))
Definition: lirc_client.c:1512
lirc_cmd_ctx::packet
char packet[PACKET_SIZE+1]
Definition: lirc_client.h:193
lirc_readconfig
int lirc_readconfig(const char *file, struct lirc_config **config, int(check)(char *s))
Definition: lirc_client.c:1433
lirc_cmd_ctx::next
char * next
Definition: lirc_client.h:198
lirc_send_one
int lirc_send_one(int fd, const char *remote, const char *keysym)
Definition: lirc_client.c:1981
lirc_cmd_ctx::reply_to_stdout
int reply_to_stdout
Definition: lirc_client.h:197
lirc_freeconfig
void lirc_freeconfig(struct lirc_config *config)
Definition: lirc_client.c:1520
LIRCRC_USER_FILE
#define LIRCRC_USER_FILE
Definition: lirc_config.h:65
CFG_LIRCRC
#define CFG_LIRCRC
Definition: lirc_config.h:28
lirc_client.h
3-rd party application interface.
LIRCD
#define LIRCD
Definition: lirc_config.h:48
lirc_config
Definition: lirc_client.h:160
lirc_list
Definition: lirc_client.h:149
lirc_nextir
char * lirc_nextir(void)
Definition: lirc_client.c:1847
lirc_deinit
int lirc_deinit(void)
Definition: lirc_client.c:360
lirc_ir2char
char * lirc_ir2char(struct lirc_config *config, char *code)
Definition: lirc_client.c:1712