LIRC libraries LinuxInfraredRemoteControl

- Main Page
- Related Pages
- Modules
- Data Structures
- Files
- Examples

- File List
- Globals

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