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