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
384
385static int lirc_readline(char** line, FILE* f)
386{
387 char* newline;
388 char* ret;
389 char* enlargeline;
390 int len;
391
392 newline = (char*)malloc(LIRC_READ + 1);
393 if (newline == NULL) {
394 lirc_printf("%s: out of memory\n", lirc_prog);
395 return -1;
396 }
397 len = 0;
398 while (1) {
399 ret = fgets(newline + len, LIRC_READ + 1, f);
400 if (ret == NULL) {
401 if (feof(f) && len > 0) {
402 *line = newline;
403 } else {
404 free(newline);
405 *line = NULL;
406 }
407 return 0;
408 }
409 len = strlen(newline);
410 if (newline[len - 1] == '\n') {
411 newline[len - 1] = 0;
412 *line = newline;
413 return 0;
414 }
415
416 enlargeline = (char*)realloc(newline, len + 1 + LIRC_READ);
417 if (enlargeline == NULL) {
418 free(newline);
419 lirc_printf("%s: out of memory\n", lirc_prog);
420 return -1;
421 }
422 newline = enlargeline;
423 }
424}
425
426
427static char* lirc_trim(char* s)
428{
429 int len;
430
431 while (s[0] == ' ' || s[0] == '\t')
432 s++;
433 len = strlen(s);
434 while (len > 0) {
435 len--;
436 if (s[len] == ' ' || s[len] == '\t')
437 s[len] = 0;
438 else
439 break;
440 }
441 return s;
442}
443
444
445/* parse standard C escape sequences + \@,\A-\Z is ^@,^A-^Z */
446static char lirc_parse_escape(char** s, const char* name, int line)
447{
448 char c;
449 unsigned int i, overflow, count;
450 int digits_found, digit;
451
452 c = **s;
453 (*s)++;
454 switch (c) {
455 case 'a':
456 return '\a';
457 case 'b':
458 return '\b';
459 case 'e':
460#if 0
461 case 'E': /* this should become ^E */
462#endif
463 return 033;
464 case 'f':
465 return '\f';
466 case 'n':
467 return '\n';
468 case 'r':
469 return '\r';
470 case 't':
471 return '\t';
472 case 'v':
473 return '\v';
474 case '\n':
475 return 0;
476 case 0:
477 (*s)--;
478 return 0;
479 case '0':
480 case '1':
481 case '2':
482 case '3':
483 case '4':
484 case '5':
485 case '6':
486 case '7':
487 i = c - '0';
488 count = 0;
489
490 while (++count < 3) {
491 c = *(*s)++;
492 if (c >= '0' && c <= '7') {
493 i = (i << 3) + c - '0';
494 } else {
495 (*s)--;
496 break;
497 }
498 }
499 if (i > (1 << CHAR_BIT) - 1) {
500 i &= (1 << CHAR_BIT) - 1;
501 lirc_printf(
502 "%s: octal escape sequence out of range in %s:%d\n",
503 lirc_prog, name, line);
504 }
505 return (char)i;
506 case 'x':
507 {
508 i = 0;
509 overflow = 0;
510 digits_found = 0;
511 for (;; ) {
512 c = *(*s)++;
513 if (c >= '0' && c <= '9') {
514 digit = c - '0';
515 } else if (c >= 'a' && c <= 'f') {
516 digit = c - 'a' + 10;
517 } else if (c >= 'A' && c <= 'F') {
518 digit = c - 'A' + 10;
519 } else {
520 (*s)--;
521 break;
522 }
523 overflow |= i ^ (i << 4 >> 4);
524 i = (i << 4) + digit;
525 digits_found = 1;
526 }
527 if (!digits_found)
528 lirc_printf("%s: \\x used with no "
529 "following hex digits in %s:%d\n",
530 lirc_prog, name, line);
531 if (overflow || i > (1 << CHAR_BIT) - 1) {
532 i &= (1 << CHAR_BIT) - 1;
533 lirc_printf("%s: hex escape sequence out "
534 "of range in %s:%d\n", lirc_prog, name,
535 line);
536 }
537 return (char)i;
538 }
539 default:
540 if (c >= '@' && c <= 'Z')
541 return c - '@';
542 return c;
543 }
544}
545
546
547static void lirc_parse_string(char* s, const char* name, int line)
548{
549 char* t;
550
551 t = s;
552 while (*s != 0) {
553 if (*s == '\\') {
554 s++;
555 *t = lirc_parse_escape(&s, name, line);
556 t++;
557 } else {
558 *t = *s;
559 s++;
560 t++;
561 }
562 }
563 *t = 0;
564}
565
566
567static void lirc_parse_include(char* s, const char* name, int line)
568{
569 char last;
570 size_t len;
571
572 len = strlen(s);
573 if (len < 2)
574 return;
575 last = s[len - 1];
576 if (*s != '"' && *s != '<')
577 return;
578 if (*s == '"' && last != '"')
579 return;
580 else if (*s == '<' && last != '>')
581 return;
582 s[len - 1] = 0;
583 memmove(s, s + 1, len - 2 + 1); /* terminating 0 is copied */
584}
585
586
587int lirc_mode(char* token, char* token2, char** mode,
588 struct lirc_config_entry** new_config,
589 struct lirc_config_entry** first_config,
590 struct lirc_config_entry** last_config,
591 int (check) (char* s),
592 const char* name,
593 int line)
594{
595 struct lirc_config_entry* new_entry;
596
597 new_entry = *new_config;
598 if (strcasecmp(token, "begin") == 0) {
599 if (token2 == NULL) {
600 if (new_entry == NULL) {
601 new_entry = (struct lirc_config_entry*)
602 malloc(sizeof(struct lirc_config_entry));
603 if (new_entry == NULL) {
604 lirc_printf("%s: out of memory\n",
605 lirc_prog);
606 return -1;
607 }
608 new_entry->prog = NULL;
609 new_entry->code = NULL;
610 new_entry->rep_delay = 0;
611 new_entry->ign_first_events = 0;
612 new_entry->rep = 0;
613 new_entry->config = NULL;
614 new_entry->change_mode = NULL;
615 new_entry->flags = none;
616 new_entry->mode = NULL;
617 new_entry->next_config = NULL;
618 new_entry->next_code = NULL;
619 new_entry->next = NULL;
620 *new_config = new_entry;
621 } else {
622 lirc_printf("%s: bad file format, %s:%d\n",
623 lirc_prog, name, line);
624 return -1;
625 }
626 } else {
627 if (new_entry == NULL && *mode == NULL) {
628 *mode = strdup(token2);
629 if (*mode == NULL)
630 return -1;
631 } else {
632 lirc_printf("%s: bad file format, %s:%d\n",
633 lirc_prog, name, line);
634 return -1;
635 }
636 }
637 } else if (strcasecmp(token, "end") == 0) {
638 if (token2 == NULL) {
639 if (new_entry != NULL) {
640#if 0
641 if (new_entry->prog == NULL) {
642 lirc_printf(
643 "%s: prog missing in config before line %d\n", lirc_prog,
644 line);
645 lirc_freeconfigentries(new_entry);
646 *new_config = NULL;
647 return -1;
648 }
649 if (strcasecmp(new_entry->prog,
650 lirc_prog) != 0) {
651 lirc_freeconfigentries(new_entry);
652 *new_config = NULL;
653 return 0;
654 }
655#endif
656 new_entry->next_code = new_entry->code;
657 new_entry->next_config = new_entry->config;
658 if (*last_config == NULL) {
659 *first_config = new_entry;
660 *last_config = new_entry;
661 } else {
662 (*last_config)->next = new_entry;
663 *last_config = new_entry;
664 }
665 *new_config = NULL;
666
667 if (*mode != NULL) {
668 new_entry->mode = strdup(*mode);
669 if (new_entry->mode == NULL) {
670 lirc_printf(
671 "%s: out of memory\n",
672 lirc_prog);
673 return -1;
674 }
675 }
676
677 if (check != NULL &&
678 new_entry->prog != NULL &&
679 strcasecmp(new_entry->prog,
680 lirc_prog) == 0) {
681 struct lirc_list* list;
682
683 list = new_entry->config;
684 while (list != NULL) {
685 if (check(list->string) == -1)
686 return -1;
687 list = list->next;
688 }
689 }
690
691 if (new_entry->rep_delay == 0 &&
692 new_entry->rep > 0)
693 new_entry->rep_delay = new_entry->rep -
694 1;
695 } else {
696 lirc_printf(
697 "%s: %s:%d: 'end' without 'begin'\n",
698 lirc_prog, name, line);
699 return -1;
700 }
701 } else {
702 if (*mode != NULL) {
703 if (new_entry != NULL) {
704 lirc_printf(
705 "%s: %s:%d: missing 'end' token\n",
706 lirc_prog, name, line);
707 return -1;
708 }
709 if (strcasecmp(*mode, token2) == 0) {
710 free(*mode);
711 *mode = NULL;
712 } else {
713 lirc_printf("%s: \"%s\" doesn't "
714 "match mode \"%s\"\n",
715 lirc_prog, token2, *mode);
716 return -1;
717 }
718 } else {
719 lirc_printf(
720 "%s: %s:%d: 'end %s' without 'begin'\n",
721 lirc_prog, name, line, token2);
722 return -1;
723 }
724 }
725 } else {
726 lirc_printf("%s: unknown token \"%s\" in %s:%d ignored\n",
727 lirc_prog, token, name, line);
728 }
729 return 0;
730}
731
732
733unsigned int lirc_flags(char* string)
734{
735 char* s;
736 unsigned int flags;
737
738 flags = none;
739 s = strtok(string, " \t|");
740 while (s) {
741 if (strcasecmp(s, "once") == 0)
742 flags |= once;
743 else if (strcasecmp(s, "quit") == 0)
744 flags |= quit;
745 else if (strcasecmp(s, "mode") == 0)
746 flags |= mode;
747 else if (strcasecmp(s, "startup_mode") == 0)
748 flags |= startup_mode;
749 else if (strcasecmp(s, "toggle_reset") == 0)
750 flags |= toggle_reset;
751 else
752 lirc_printf("%s: unknown flag \"%s\"\n", lirc_prog, s);
753 s = strtok(NULL, " \t");
754 }
755 return flags;
756}
757
758
759
760
761
762
768static char* get_homepath(void)
769{
770 char* home;
771 char* filename;
772
773 filename = malloc(MAXPATHLEN);
774 if (filename == NULL) {
775 lirc_printf("%s: out of memory\n", lirc_prog);
776 return NULL;
777 }
778 home = getenv("HOME");
779 home = home == NULL ? "/" : home;
780 strncpy(filename, home, MAXPATHLEN);
781 if (filename[strlen(filename) - 1] == '/')
782 filename[strlen(filename) - 1] = '\0';
783 return filename;
784}
785
786
792static char* get_freedesktop_path(void)
793{
794 char* path;
795
796 if (getenv("XDG_CONFIG_HOME") != NULL) {
797 path = malloc(MAXPATHLEN);
798 strncpy(path, getenv("XDG_CONFIG_HOME"), MAXPATHLEN);
799 strncat(path, "/", MAXPATHLEN - strlen(path));
800 strncat(path, CFG_LIRCRC, MAXPATHLEN - strlen(path));
801 } else {
802 path = get_homepath();
803 if (path == NULL)
804 return NULL;
805 strncat(path, "/.config/lircrc", MAXPATHLEN - strlen(path) - 1);
806 }
807 if (access(path, R_OK) != 0)
808 path[0] = '\0';
809 return path;
810}
811
812
813static char* lirc_getfilename(const char* file, const char* current_file)
814{
815 char* filename;
816
817 if (file == NULL) {
818 filename = get_freedesktop_path();
819 if (filename == NULL) {
820 return NULL;
821 } else if (strlen(filename) == 0) {
822 free(filename);
823 filename = get_homepath();
824 if (filename == NULL)
825 return NULL;
826 strcat(filename, "/" LIRCRC_USER_FILE);
827 }
828 filename = realloc(filename, strlen(filename) + 1);
829 } else if (strncmp(file, "~/", 2) == 0) {
830 filename = get_homepath();
831 if (filename == NULL)
832 return NULL;
833 strcat(filename, file + 1);
834 filename = realloc(filename, strlen(filename) + 1);
835 } else if (file[0] == '/' || current_file == NULL) {
836 /* absolute path or root */
837 filename = strdup(file);
838 if (filename == NULL) {
839 lirc_printf("%s: out of memory\n", lirc_prog);
840 return NULL;
841 }
842 } else {
843 /* get path from parent filename */
844 int pathlen = strlen(current_file);
845
846 while (pathlen > 0 && current_file[pathlen - 1] != '/')
847 pathlen--;
848 filename = (char*)malloc(pathlen + strlen(file) + 1);
849 if (filename == NULL) {
850 lirc_printf("%s: out of memory\n", lirc_prog);
851 return NULL;
852 }
853 memcpy(filename, current_file, pathlen);
854 filename[pathlen] = 0;
855 strcat(filename, file);
856 }
857 return filename;
858}
859
860
861static FILE* lirc_open(const char* file,
862 const char* current_file,
863 char** full_name)
864{
865 FILE* fin;
866 char* filename;
867
868 filename = lirc_getfilename(file, current_file);
869 if (filename == NULL)
870 return NULL;
871
872 fin = fopen(filename, "r");
873 if (fin == NULL && (file != NULL || errno != ENOENT)) {
874 lirc_printf("%s: could not open config file %s\n", lirc_prog,
875 filename);
876 lirc_perror(lirc_prog);
877 } else if (fin == NULL) {
878 const char* root_file = LIRCRC_ROOT_FILE;
879
880 fin = fopen(root_file, "r");
881 if (fin == NULL && errno == ENOENT) {
882 int save_errno = errno;
883
884 root_file = LIRCRC_OLD_ROOT_FILE;
885 fin = fopen(root_file, "r");
886 errno = save_errno;
887 }
888 if (fin == NULL && errno != ENOENT) {
889 lirc_printf("%s: could not open config file %s\n",
890 lirc_prog, LIRCRC_ROOT_FILE);
891 lirc_perror(lirc_prog);
892 } else if (fin == NULL) {
893 lirc_printf("%s: could not open config files "
894 "%s and %s\n", lirc_prog, filename,
896 lirc_perror(lirc_prog);
897 } else {
898 free(filename);
899 filename = strdup(root_file);
900 if (filename == NULL) {
901 fclose(fin);
902 lirc_printf("%s: out of memory\n", lirc_prog);
903 return NULL;
904 }
905 }
906 }
907 if (full_name && fin != NULL)
908 *full_name = filename;
909 else
910 free(filename);
911 return fin;
912}
913
914
915static struct filestack_t* stack_push(struct filestack_t* parent)
916{
917 struct filestack_t* entry;
918
919 entry = malloc(sizeof(struct filestack_t));
920 if (entry == NULL) {
921 lirc_printf("%s: out of memory\n", lirc_prog);
922 return NULL;
923 }
924 entry->file = NULL;
925 entry->name = NULL;
926 entry->line = 0;
927 entry->parent = parent;
928 return entry;
929}
930
931
932static struct filestack_t* stack_pop(struct filestack_t* entry)
933{
934 struct filestack_t* parent = NULL;
935
936 if (entry) {
937 parent = entry->parent;
938 if (entry->name)
939 free(entry->name);
940 free(entry);
941 }
942 return parent;
943}
944
945
946static void stack_free(struct filestack_t* entry)
947{
948 while (entry)
949 entry = stack_pop(entry);
950}
951
952
953static char* lirc_startupmode(struct lirc_config_entry* first)
954{
955 struct lirc_config_entry* scan;
956 char* startupmode;
957
958 startupmode = NULL;
959 scan = first;
960 /* Set a startup mode based on flags=startup_mode */
961 while (scan != NULL) {
962 if (scan->flags & startup_mode) {
963 if (scan->change_mode != NULL) {
964 startupmode = scan->change_mode;
965 /* Remove the startup mode or it confuses lirc mode system */
966 scan->change_mode = NULL;
967 break;
968 }
969 lirc_printf("%s: startup_mode flags requires 'mode ='\n", lirc_prog);
970 }
971 scan = scan->next;
972 }
973
974 /* Set a default mode if we find a mode = client app name */
975 if (startupmode == NULL) {
976 scan = first;
977 while (scan != NULL) {
978 if (scan->mode != NULL
979 && lirc_prog != NULL
980 && strcasecmp(lirc_prog, scan->mode) == 0) {
981 startupmode = lirc_prog;
982 break;
983 }
984 scan = scan->next;
985 }
986 }
987
988 if (startupmode == NULL)
989 return NULL;
990 scan = first;
991 while (scan != NULL) {
992 if (scan->change_mode != NULL
993 && scan->flags & once
994 && strcasecmp(startupmode, scan->change_mode) == 0)
995 scan->flags |= ecno;
996 scan = scan->next;
997 }
998 return startupmode;
999}
1000
1001
1002static void lirc_freeconfigentries(struct lirc_config_entry* first)
1003{
1004 struct lirc_config_entry* c;
1005 struct lirc_config_entry* config_temp;
1006 struct lirc_list* list;
1007 struct lirc_list* list_temp;
1008 struct lirc_code* code;
1009 struct lirc_code* code_temp;
1010
1011 c = first;
1012 while (c != NULL) {
1013 if (c->prog)
1014 free(c->prog);
1015 if (c->change_mode)
1016 free(c->change_mode);
1017 if (c->mode)
1018 free(c->mode);
1019
1020 code = c->code;
1021 while (code != NULL) {
1022 if (code->remote != NULL && code->remote != LIRC_ALL)
1023 free(code->remote);
1024 if (code->button != NULL && code->button != LIRC_ALL)
1025 free(code->button);
1026 code_temp = code->next;
1027 free(code);
1028 code = code_temp;
1029 }
1030
1031 list = c->config;
1032 while (list != NULL) {
1033 if (list->string)
1034 free(list->string);
1035 list_temp = list->next;
1036 free(list);
1037 list = list_temp;
1038 }
1039 config_temp = c->next;
1040 free(c);
1041 c = config_temp;
1042 }
1043}
1044
1045
1046static void
1047parse_shebang(char* line, int depth, const char* path, char* buff, size_t size)
1048{
1049 char* token;
1050 char my_path[128];
1051 const char* const SHEBANG_MSG =
1052 "Warning: Use of deprecated lircrc shebang."
1053 " Use lircrc_class instead.\n";
1054
1055 token = strtok(line, "#! ");
1056 buff[0] = '\0';
1057 if (depth > 1) {
1058 lirc_printf("Warning: ignoring shebang in included file.");
1059 return;
1060 }
1061 if (strcmp(token, "lircrc") == 0) {
1062 strncpy(my_path, path, sizeof(my_path) - 1);
1063 strncat(buff, basename(my_path), size - 1);
1064 lirc_printf(SHEBANG_MSG);
1065 } else {
1066 lirc_printf("Warning: bad shebang (ignored)");
1067 }
1068}
1069
1070
1071static int lirc_readconfig_only_internal(const char* file,
1072 struct lirc_config** config,
1073 int (check)(char* s),
1074 char** full_name)
1075{
1076 const char* const INCLUDED_LIRCRC_CLASS =
1077 "Warning: lirc_class in included file (ignored)";
1078 char* string;
1079 char* eq;
1080 char* token;
1081 char* token2;
1082 char* token3;
1083 struct filestack_t* filestack;
1084 struct filestack_t* stack_tmp;
1085 int open_files;
1086 char lircrc_class[128] = { '\0' };
1087 struct lirc_config_entry* new_entry;
1088 struct lirc_config_entry* first;
1089 struct lirc_config_entry* last;
1090 char* mode;
1091 char* remote;
1092 int ret = 0;
1093 int firstline = 1;
1094 char* save_full_name = NULL;
1095
1096 filestack = stack_push(NULL);
1097 if (filestack == NULL)
1098 return -1;
1099 filestack->file = lirc_open(file, NULL, &(filestack->name));
1100 if (filestack->file == NULL) {
1101 stack_free(filestack);
1102 return -1;
1103 }
1104 filestack->line = 0;
1105 open_files = 1;
1106
1107 first = new_entry = last = NULL;
1108 mode = NULL;
1109 remote = LIRC_ALL;
1110 while (filestack) {
1111 ret = lirc_readline(&string, filestack->file);
1112 if (ret == -1 || string == NULL) {
1113 fclose(filestack->file);
1114 if (open_files == 1 && full_name != NULL) {
1115 save_full_name = filestack->name;
1116 filestack->name = NULL;
1117 }
1118 filestack = stack_pop(filestack);
1119 open_files--;
1120 continue;
1121 }
1122 /* check for sha-bang */
1123 if (firstline) {
1124 firstline = 0;
1125 if (strncmp(string, "#!", 2) == 0) {
1126 parse_shebang(string,
1127 open_files,
1128 file,
1129 lircrc_class,
1130 sizeof(lircrc_class));
1131 }
1132 }
1133 filestack->line++;
1134 eq = strchr(string, '=');
1135 if (eq == NULL) {
1136 token = strtok(string, " \t");
1137 if (token == NULL) {
1138 /* ignore empty line */
1139 } else if (token[0] == '#') {
1140 /* ignore comment */
1141 } else if (strcasecmp(token, "lircrc_class") == 0) {
1142 token2 = lirc_trim(strtok(NULL, ""));
1143 if (strlen(token2) == 0) {
1144 lirc_printf(
1145 "Warning: no lircrc_class");
1146 } else if (open_files == 1) {
1147 strncpy(lircrc_class,
1148 token2,
1149 sizeof(lircrc_class) - 1);
1150 } else {
1151 lirc_printf(INCLUDED_LIRCRC_CLASS);
1152 }
1153 } else if (strcasecmp(token, "include") == 0) {
1154 if (open_files >= MAX_INCLUDES) {
1155 lirc_printf("%s: too many files "
1156 "included at %s:%d\n",
1157 lirc_prog, filestack->name,
1158 filestack->line);
1159 ret = -1;
1160 } else {
1161 token2 = strtok(NULL, "");
1162 token2 = lirc_trim(token2);
1163 lirc_parse_include(token2,
1164 filestack->name,
1165 filestack->line);
1166 stack_tmp = stack_push(filestack);
1167 if (stack_tmp == NULL) {
1168 ret = -1;
1169 } else {
1170 stack_tmp->file =
1171 lirc_open(token2,
1172 filestack->name,
1173 &(stack_tmp->
1174 name));
1175 stack_tmp->line = 0;
1176 if (stack_tmp->file) {
1177 open_files++;
1178 filestack = stack_tmp;
1179 } else {
1180 stack_pop(stack_tmp);
1181 ret = -1;
1182 }
1183 }
1184 }
1185 } else {
1186 token2 = strtok(NULL, " \t");
1187 if (token2)
1188 token3 = strtok(NULL, " \t");
1189 if (token2 != NULL && token3 != NULL) {
1190 lirc_printf("%s: unexpected token in line %s:%d\n",
1191 lirc_prog, filestack->name, filestack->line);
1192 } else {
1193 ret = lirc_mode(token, token2, &mode,
1194 &new_entry, &first,
1195 &last,
1196 check, filestack->name,
1197 filestack->line);
1198 if (ret == 0) {
1199 if (remote != LIRC_ALL)
1200 free(remote);
1201 remote = LIRC_ALL;
1202 } else {
1203 if (mode != NULL) {
1204 free(mode);
1205 mode = NULL;
1206 }
1207 if (new_entry != NULL) {
1208 lirc_freeconfigentries(
1209 new_entry);
1210 new_entry = NULL;
1211 }
1212 }
1213 }
1214 }
1215 } else {
1216 eq[0] = 0;
1217 token = lirc_trim(string);
1218 token2 = lirc_trim(eq + 1);
1219 if (token[0] == '#') {
1220 /* ignore comment */
1221 } else if (new_entry == NULL) {
1222 lirc_printf("%s: bad file format, %s:%d\n",
1223 lirc_prog, filestack->name,
1224 filestack->line);
1225 ret = -1;
1226 } else {
1227 token2 = strdup(token2);
1228 if (token2 == NULL) {
1229 lirc_printf("%s: out of memory\n",
1230 lirc_prog);
1231 ret = -1;
1232 } else if (strcasecmp(token, "prog") == 0) {
1233 if (new_entry->prog != NULL)
1234 free(new_entry->prog);
1235 new_entry->prog = token2;
1236 } else if (strcasecmp(token, "remote") == 0) {
1237 if (remote != LIRC_ALL)
1238 free(remote);
1239
1240 if (strcasecmp("*", token2) == 0) {
1241 remote = LIRC_ALL;
1242 free(token2);
1243 } else {
1244 remote = token2;
1245 }
1246 } else if (strcasecmp(token, "button") == 0) {
1247 struct lirc_code* code;
1248
1249 code = (struct lirc_code*)
1250 malloc(sizeof(struct lirc_code));
1251 if (code == NULL) {
1252 free(token2);
1253 lirc_printf(
1254 "%s: out of memory\n",
1255 lirc_prog);
1256 ret = -1;
1257 } else {
1258 code->remote = remote;
1259 if (strcasecmp("*",
1260 token2) == 0) {
1261 code->button = LIRC_ALL;
1262 free(token2);
1263 } else {
1264 code->button = token2;
1265 }
1266 code->next = NULL;
1267
1268 if (new_entry->code == NULL)
1269 new_entry->code = code;
1270 else
1271 new_entry->next_code->
1272 next = code;
1273 new_entry->next_code = code;
1274 if (remote != LIRC_ALL) {
1275 remote = strdup(remote);
1276 if (remote == NULL) {
1277 lirc_printf(
1278 "%s: out of memory\n",
1279 lirc_prog);
1280 ret = -1;
1281 }
1282 }
1283 }
1284 } else if (strcasecmp(token, "delay") == 0) {
1285 char* end;
1286
1287 errno = ERANGE + 1;
1288 new_entry->rep_delay = strtoul(token2,
1289 &end, 0);
1290 if ((new_entry->rep_delay ==
1291 ULONG_MAX && errno == ERANGE)
1292 || end[0] != 0 || strlen(token2) ==
1293 0)
1294 lirc_printf("%s: \"%s\" not"
1295 " a valid number for delay\n", lirc_prog,
1296 token2);
1297 free(token2);
1298 } else if (strcasecmp(token, "ignore_first_events") == 0) {
1299 char* end;
1300
1301 errno = ERANGE + 1;
1302 new_entry->ign_first_events = strtoul(
1303 token2, &end, 0);
1304 if ((new_entry->ign_first_events ==
1305 ULONG_MAX && errno == ERANGE)
1306 || end[0] != 0 || strlen(token2) ==
1307 0)
1308 lirc_printf("%s: \"%s\" not"
1309 " a valid number for ignore_first_events\n",
1310 lirc_prog, token2);
1311 free(token2);
1312 } else if (strcasecmp(token, "repeat") == 0) {
1313 char* end;
1314
1315 errno = ERANGE + 1;
1316 new_entry->rep =
1317 strtoul(token2, &end, 0);
1318 if ((new_entry->rep == ULONG_MAX &&
1319 errno == ERANGE)
1320 || end[0] != 0 || strlen(token2) ==
1321 0)
1322 lirc_printf("%s: \"%s\" not"
1323 " a valid number for repeat\n", lirc_prog,
1324 token2);
1325 free(token2);
1326 } else if (strcasecmp(token, "config") == 0) {
1327 struct lirc_list* new_list;
1328
1329 new_list = (struct lirc_list*)
1330 malloc(sizeof(struct lirc_list));
1331 if (new_list == NULL) {
1332 free(token2);
1333 lirc_printf(
1334 "%s: out of memory\n",
1335 lirc_prog);
1336 ret = -1;
1337 } else {
1338 lirc_parse_string(token2,
1339 filestack->name,
1340 filestack->line);
1341 new_list->string = token2;
1342 new_list->next = NULL;
1343 if (new_entry->config == NULL)
1344 new_entry->config =
1345 new_list;
1346 else
1347 new_entry->next_config->
1348 next = new_list;
1349 new_entry->next_config =
1350 new_list;
1351 }
1352 } else if (strcasecmp(token, "mode") == 0) {
1353 if (new_entry->change_mode != NULL)
1354 free(new_entry->change_mode);
1355 new_entry->change_mode = token2;
1356 } else if (strcasecmp(token, "flags") == 0) {
1357 new_entry->flags = lirc_flags(token2);
1358 free(token2);
1359 } else {
1360 free(token2);
1361 lirc_printf(
1362 "%s: unknown token \"%s\" in %s:%d ignored\n",
1363 lirc_prog, token, filestack->name,
1364 filestack->line);
1365 }
1366 }
1367 }
1368 free(string);
1369 if (ret == -1)
1370 break;
1371 }
1372 if (remote != LIRC_ALL)
1373 free(remote);
1374 if (new_entry != NULL) {
1375 if (ret == 0) {
1376 ret = lirc_mode("end", NULL, &mode, &new_entry, &first,
1377 &last, check, "", 0);
1378 lirc_printf(
1379 "%s: warning: end token missing at end of file\n",
1380 lirc_prog);
1381 } else {
1382 lirc_freeconfigentries(new_entry);
1383 new_entry = NULL;
1384 }
1385 }
1386 if (mode != NULL) {
1387 if (ret == 0)
1388 lirc_printf(
1389 "%s: warning: no end token found for mode \"%s\"\n", lirc_prog,
1390 mode);
1391 free(mode);
1392 }
1393 if (ret == 0) {
1394 char* startupmode;
1395
1396 *config = (struct lirc_config*)
1397 malloc(sizeof(struct lirc_config));
1398 if (*config == NULL) {
1399 lirc_printf("%s: out of memory\n", lirc_prog);
1400 lirc_freeconfigentries(first);
1401 return -1;
1402 }
1403 (*config)->first = first;
1404 (*config)->next = first;
1405 startupmode = lirc_startupmode((*config)->first);
1406 (*config)->current_mode =
1407 startupmode ? strdup(startupmode) : NULL;
1408 if (lircrc_class[0] != '\0')
1409 (*config)->lircrc_class = strdup(lircrc_class);
1410 else
1411 (*config)->lircrc_class = NULL;
1412 (*config)->sockfd = -1;
1413 if (full_name != NULL) {
1414 *full_name = save_full_name;
1415 save_full_name = NULL;
1416 }
1417 } else {
1418 *config = NULL;
1419 lirc_freeconfigentries(first);
1420 }
1421 if (filestack)
1422 stack_free(filestack);
1423 if (save_full_name)
1424 free(save_full_name);
1425 return ret;
1426}
1427
1428
1429int lirc_identify(int sockfd)
1430{
1431 lirc_cmd_ctx cmd;
1432 int ret;
1433
1434 ret = lirc_command_init(&cmd, "IDENT %s\n", lirc_prog);
1435 if (ret != 0)
1436 return ret;
1437 do
1438 ret = lirc_command_run(&cmd, sockfd);
1439 while (ret == EAGAIN || ret == EWOULDBLOCK);
1440 return ret == 0 ? LIRC_RET_SUCCESS : -1;
1441}
1442
1443
1444
1445int lirc_readconfig(const char* file,
1446 struct lirc_config** config,
1447 int (check)(char* s))
1448{
1449 struct sockaddr_un addr;
1450 int sockfd = -1;
1451 char* filename;
1452 char command[128];
1453 int ret;
1454
1455 filename = NULL;
1456 if (lirc_readconfig_only_internal(file, config, check, &filename) == -1)
1457 return -1;
1458
1459 if ((*config)->lircrc_class == NULL)
1460 goto lirc_readconfig_compat;
1461
1462 /* connect to lircrcd */
1463
1464 addr.sun_family = AF_UNIX;
1465 if (lirc_getsocketname((*config)->lircrc_class,
1466 addr.sun_path,
1467 sizeof(addr.sun_path)) > sizeof(addr.sun_path)) {
1468 lirc_printf("%s: WARNING: file name too long\n", lirc_prog);
1469 goto lirc_readconfig_compat;
1470 }
1471 sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
1472 if (sockfd == -1) {
1473 lirc_printf("%s: WARNING: could not open socket\n", lirc_prog);
1474 lirc_perror(lirc_prog);
1475 goto lirc_readconfig_compat;
1476 }
1477 if (connect(sockfd, (struct sockaddr*)&addr, sizeof(addr)) != -1) {
1478 (*config)->sockfd = sockfd;
1479 free(filename);
1480
1481 /* tell daemon lirc_prog */
1482 if (lirc_identify(sockfd) == LIRC_RET_SUCCESS)
1483 /* we're connected */
1484 return 0;
1485 close(sockfd);
1486 lirc_freeconfig(*config);
1487 return -1;
1488 }
1489 close(sockfd);
1490 sockfd = -1;
1491
1492 /* launch lircrcd */
1493 snprintf(command, sizeof(command),
1494 "lircrcd %s", (*config)->lircrc_class);
1495 ret = system(command);
1496 if (ret == -1 || WEXITSTATUS(ret) != EXIT_SUCCESS)
1497 goto lirc_readconfig_compat;
1498 free(filename);
1499
1500 sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
1501 if (sockfd == -1) {
1502 lirc_printf("%s: WARNING: could not open socket\n", lirc_prog);
1503 lirc_perror(lirc_prog);
1504 goto lirc_readconfig_compat;
1505 }
1506 if (connect(sockfd, (struct sockaddr*)&addr, sizeof(addr)) != -1) {
1507 if (lirc_identify(sockfd) == LIRC_RET_SUCCESS) {
1508 (*config)->sockfd = sockfd;
1509 return 0;
1510 }
1511 }
1512 close(sockfd);
1513 lirc_freeconfig(*config);
1514 return -1;
1515
1516lirc_readconfig_compat:
1517 /* compat fallback */
1518 if (sockfd != -1)
1519 close(sockfd);
1520 return 0;
1521}
1522
1523
1524int lirc_readconfig_only(const char* file,
1525 struct lirc_config** config,
1526 int (check) (char* s))
1527{
1528 return lirc_readconfig_only_internal(file, config, check, NULL);
1529}
1530
1531
1532void lirc_freeconfig(struct lirc_config* config)
1533{
1534 if (config != NULL) {
1535 if (config->sockfd != -1) {
1536 (void)close(config->sockfd);
1537 config->sockfd = -1;
1538 }
1539 if (config->lircrc_class != NULL)
1540 free(config->lircrc_class);
1541 lirc_freeconfigentries(config->first);
1542 free(config->current_mode);
1543 free(config);
1544 }
1545}
1546
1547
1548static void lirc_clearmode(struct lirc_config* config)
1549{
1550 struct lirc_config_entry* scan;
1551
1552 if (config->current_mode == NULL)
1553 return;
1554 scan = config->first;
1555 while (scan != NULL) {
1556 if (scan->change_mode != NULL)
1557 if (strcasecmp(scan->change_mode,
1558 config->current_mode) == 0)
1559 scan->flags &= ~ecno;
1560 scan = scan->next;
1561 }
1562 free(config->current_mode);
1563 config->current_mode = NULL;
1564}
1565
1566
1567static char* lirc_execute(struct lirc_config* config,
1568 struct lirc_config_entry* scan)
1569{
1570 char* s;
1571 int do_once = 1;
1572
1573 if (scan->flags & mode)
1574 lirc_clearmode(config);
1575 if (scan->change_mode != NULL) {
1576 free(config->current_mode);
1577 config->current_mode = strdup(scan->change_mode);
1578 if (scan->flags & once) {
1579 if (scan->flags & ecno)
1580 do_once = 0;
1581 else
1582 scan->flags |= ecno;
1583 }
1584 }
1585 if (scan->next_config != NULL
1586 && scan->prog != NULL
1587 && (lirc_prog == NULL || strcasecmp(scan->prog, lirc_prog) == 0)
1588 && do_once == 1) {
1589 s = scan->next_config->string;
1590 scan->next_config = scan->next_config->next;
1591 if (scan->next_config == NULL)
1592 scan->next_config = scan->config;
1593 return s;
1594 }
1595 return NULL;
1596}
1597
1606static int rep_filter(struct lirc_config_entry* scan, int rep)
1607{
1608 int delay_start, rep_delay;
1609
1610 if (scan->ign_first_events) {
1611 if (scan->rep_delay && rep == 0) /* warn user only once */
1612 lirc_printf(
1613 "%s: ignoring \"delay\" because \"ignore_first_events\" is also set\n",
1614 lirc_prog);
1615 rep_delay = scan->ign_first_events;
1616 delay_start = 0;
1617 } else {
1618 rep_delay = scan->rep_delay;
1619 delay_start = 1;
1620 }
1621 /* handle event before delay_start */
1622 if (rep < delay_start)
1623 return 1;
1624 /* special case: 1 event after delay when repeat is not set */
1625 if (scan->rep == 0 && rep_delay > 0 && rep == rep_delay + delay_start)
1626 return 1;
1627 /* handle repeat */
1628 if (scan->rep > 0 && rep >= rep_delay + delay_start) {
1629 rep -= rep_delay + delay_start;
1630 return (rep % scan->rep) == 0;
1631 }
1632 return 0;
1633}
1634
1635static int lirc_iscode(struct lirc_config_entry* scan,
1636 char* remote,
1637 char* button,
1638 int rep)
1639{
1640 struct lirc_code* codes;
1641
1642 /* no remote/button specified */
1643 if (scan->code == NULL)
1644 return rep_filter(scan, rep);
1645
1646 /* remote/button match? */
1647 if (scan->next_code->remote == LIRC_ALL
1648 || strcasecmp(scan->next_code->remote, remote) == 0) {
1649 if (scan->next_code->button == LIRC_ALL
1650 || strcasecmp(scan->next_code->button, button) == 0) {
1651 int iscode = 0;
1652 /* button sequence? */
1653 if (scan->code->next == NULL || rep == 0) {
1654 scan->next_code = scan->next_code->next;
1655 if (scan->code->next != NULL)
1656 iscode = 1;
1657 }
1658 /* sequence completed? */
1659 if (scan->next_code == NULL) {
1660 scan->next_code = scan->code;
1661 if (scan->code->next != NULL ||
1662 rep_filter(scan, rep))
1663 iscode = 2;
1664 }
1665 return iscode;
1666 }
1667 }
1668
1669 if (rep != 0)
1670 return 0;
1671
1672 /* handle toggle_reset */
1673 if (scan->flags & toggle_reset)
1674 scan->next_config = scan->config;
1675
1676 codes = scan->code;
1677 if (codes == scan->next_code)
1678 return 0;
1679 codes = codes->next;
1680 /* rebase code sequence */
1681 while (codes != scan->next_code->next) {
1682 struct lirc_code* prev;
1683 struct lirc_code* next;
1684 int flag = 1;
1685
1686 prev = scan->code;
1687 next = codes;
1688 while (next != scan->next_code) {
1689 if (prev->remote == LIRC_ALL
1690 || strcasecmp(prev->remote, next->remote) == 0) {
1691 if (prev->button == LIRC_ALL
1692 || strcasecmp(prev->button,
1693 next->button) == 0) {
1694 prev = prev->next;
1695 next = next->next;
1696 } else {
1697 flag = 0;
1698 break;
1699 }
1700 } else {
1701 flag = 0;
1702 break;
1703 }
1704 }
1705 if (flag == 1) {
1706 if (prev->remote == LIRC_ALL
1707 || strcasecmp(prev->remote, remote) == 0) {
1708 if (prev->button == LIRC_ALL
1709 || strcasecmp(prev->button, button) == 0) {
1710 if (rep == 0) {
1711 scan->next_code = prev->next;
1712 return 0;
1713 }
1714 }
1715 }
1716 }
1717 codes = codes->next;
1718 }
1719 scan->next_code = scan->code;
1720 return 0;
1721}
1722
1723
1724char* lirc_ir2char(struct lirc_config* config, char* code)
1725{
1726 static int warning = 1;
1727 char* string;
1728
1729 if (warning) {
1730 fprintf(stderr, "%s: warning: lirc_ir2char() is obsolete\n",
1731 lirc_prog);
1732 warning = 0;
1733 }
1734 if (lirc_code2char(config, code, &string) == -1)
1735 return NULL;
1736 return string;
1737}
1738
1739
1740static int lirc_code2char_internal(struct lirc_config* config,
1741 char* code,
1742 char** string,
1743 char** prog)
1744{
1745 int rep;
1746 char* backup;
1747 char* remote;
1748 char* button;
1749 char* s = NULL;
1750 struct lirc_config_entry* scan;
1751 int exec_level;
1752 int quit_happened;
1753
1754 *string = NULL;
1755 if (sscanf(code, "%*x %x %*s %*s\n", &rep) == 1) {
1756 backup = strdup(code);
1757 if (backup == NULL)
1758 return -1;
1759
1760 strtok(backup, " ");
1761 strtok(NULL, " ");
1762 button = strtok(NULL, " ");
1763 remote = strtok(NULL, "\n");
1764
1765 if (button == NULL || remote == NULL) {
1766 free(backup);
1767 return 0;
1768 }
1769
1770 scan = config->next;
1771 quit_happened = 0;
1772 while (scan != NULL) {
1773 exec_level = lirc_iscode(scan, remote, button, rep);
1774 if (exec_level > 0 &&
1775 (scan->mode == NULL ||
1776 (scan->mode != NULL &&
1777 config->current_mode != NULL &&
1778 strcasecmp(scan->mode,
1779 config->current_mode) == 0)) &&
1780 quit_happened == 0) {
1781 if (exec_level > 1) {
1782 s = lirc_execute(config, scan);
1783 if (s != NULL && prog != NULL)
1784 *prog = scan->prog;
1785 } else {
1786 s = NULL;
1787 }
1788 if (scan->flags & quit) {
1789 quit_happened = 1;
1790 config->next = NULL;
1791 scan = scan->next;
1792 continue;
1793 } else if (s != NULL) {
1794 config->next = scan->next;
1795 break;
1796 }
1797 }
1798 scan = scan->next;
1799 }
1800 free(backup);
1801 if (s != NULL) {
1802 *string = s;
1803 return 0;
1804 }
1805 }
1806 config->next = config->first;
1807 return 0;
1808}
1809
1810
1811int lirc_code2char(struct lirc_config* config, char* code, char** string)
1812{
1813 lirc_cmd_ctx cmd;
1814 static char static_buff[PACKET_SIZE];
1815 int ret;
1816 char* my_code;
1817 char* pos;
1818
1819 my_code = strdup(code);
1820 pos = rindex(my_code, '\n');
1821 if (pos != NULL)
1822 *pos = '\0';
1823 ret = lirc_command_init(&cmd, "CODE %s\n", my_code);
1824 free(my_code);
1825 if (ret != 0)
1826 return -1;
1827 if (config->sockfd != -1) {
1828 do
1829 ret = lirc_command_run(&cmd, config->sockfd);
1830 while (ret == EAGAIN || ret == EWOULDBLOCK);
1831 if (ret == 0) {
1832 strncpy(static_buff, cmd.reply, PACKET_SIZE);
1833 *string = static_buff;
1834 }
1835 return ret == 0 ? 0 : -1;
1836 }
1837 return lirc_code2char_internal(config, code, string, NULL);
1838}
1839
1840
1841int lirc_code2charprog(struct lirc_config* config,
1842 char* code,
1843 char** string,
1844 char** prog)
1845{
1846 char* backup;
1847 int ret;
1848
1849 backup = lirc_prog;
1850 lirc_prog = NULL;
1851
1852 ret = lirc_code2char_internal(config, code, string, prog);
1853
1854 lirc_prog = backup;
1855 return ret;
1856}
1857
1858
1859char* lirc_nextir(void)
1860{
1861 static int warning = 1;
1862 char* code;
1863 int ret;
1864
1865 if (warning) {
1866 fprintf(stderr, "%s: warning: lirc_nextir() is obsolete\n",
1867 lirc_prog);
1868 warning = 0;
1869 }
1870 ret = lirc_nextcode(&code);
1871 if (ret == -1)
1872 return NULL;
1873 return code;
1874}
1875
1876
1877int lirc_nextcode(char** code)
1878{
1879 static int packet_size = PACKET_SIZE;
1880 static int end_len = 0;
1881 ssize_t len = 0;
1882 char* end;
1883 char c;
1884
1885 *code = NULL;
1886 if (lirc_buffer == NULL) {
1887 lirc_buffer = (char*)malloc(packet_size + 1);
1888 if (lirc_buffer == NULL) {
1889 lirc_printf("%s: out of memory\n", lirc_prog);
1890 return -1;
1891 }
1892 lirc_buffer[0] = 0;
1893 }
1894 while ((end = strchr(lirc_buffer, '\n')) == NULL) {
1895 if (end_len >= packet_size) {
1896 char* new_buffer;
1897
1898 packet_size += PACKET_SIZE;
1899 new_buffer =
1900 (char*)realloc(lirc_buffer, packet_size + 1);
1901 if (new_buffer == NULL)
1902 return -1;
1903 lirc_buffer = new_buffer;
1904 }
1905 len = read(lirc_lircd, lirc_buffer + end_len,
1906 packet_size - end_len);
1907 if (len <= 0) {
1908 if (len == -1 && errno == EAGAIN)
1909 return 0;
1910 else
1911 return -1;
1912 }
1913 end_len += len;
1914 lirc_buffer[end_len] = 0;
1915 /* return if next code not yet available completely */
1916 end = strchr(lirc_buffer, '\n');
1917 if (end == NULL)
1918 return 0;
1919 }
1920 /* copy first line to buffer (code) and move remaining chars to
1921 * lirc_buffers start */
1922 end++;
1923 end_len = strlen(end);
1924 c = end[0];
1925 end[0] = 0;
1926 *code = strdup(lirc_buffer);
1927 end[0] = c;
1928 memmove(lirc_buffer, end, end_len + 1);
1929 if (*code == NULL)
1930 return -1;
1931 return 0;
1932}
1933
1934
1935size_t lirc_getsocketname(const char* id, char* buf, size_t size)
1936{
1937 id = id != NULL ? id : "default";
1938 snprintf(buf, size, VARRUNDIR "/%d-%s-lircrcd.socket", getuid(), id);
1939 return strlen(buf);
1940}
1941
1942
1943
1944const char* lirc_getmode(struct lirc_config* config)
1945{
1946 lirc_cmd_ctx cmd;
1947 static char static_buff[PACKET_SIZE];
1948 int ret;
1949
1950 if (config->sockfd != -1) {
1951 lirc_command_init(&cmd, "GETMODE\n");
1952 do
1953 ret = lirc_command_run(&cmd, config->sockfd);
1954 while (ret == EAGAIN || ret == EWOULDBLOCK);
1955 if (ret == 0) {
1956 strncpy(static_buff, cmd.reply, PACKET_SIZE);
1957 return static_buff;
1958 }
1959 return NULL;
1960 }
1961 return config->current_mode;
1962}
1963
1964
1965const char* lirc_setmode(struct lirc_config* config, const char* mode)
1966{
1967 lirc_cmd_ctx cmd;
1968 int r;
1969 static char static_buff[PACKET_SIZE];
1970
1971 if (config->sockfd != -1) {
1972 if (mode != NULL)
1973 r = lirc_command_init(&cmd, "SETMODE %s\n", mode);
1974 else
1975 r = lirc_command_init(&cmd, "SETMODE\n");
1976 if (r != 0)
1977 return NULL;
1978 do
1979 r = lirc_command_run(&cmd, config->sockfd);
1980 while (r == EAGAIN || r == EWOULDBLOCK);
1981 if (r == 0) {
1982 strncpy(static_buff, cmd.reply, PACKET_SIZE);
1983 return static_buff;
1984 }
1985 return NULL;
1986 }
1987 free(config->current_mode);
1988 config->current_mode = mode ? strdup(mode) : NULL;
1989 return config->current_mode;
1990}
1991
1992
1993int lirc_send_one(int fd, const char* remote, const char* keysym)
1994{
1995 int r;
1996 lirc_cmd_ctx command;
1997
1998 r = lirc_command_init(&command, "SEND_ONCE %s %s\n", remote, keysym);
1999 if (r != 0)
2000 return EMSGSIZE;
2001 do
2002 r = lirc_command_run(&command, fd);
2003 while (r == EAGAIN);
2004 return r;
2005}
2006
2007
2008int lirc_simulate(int fd,
2009 const char* remote,
2010 const char* keysym,
2011 int scancode,
2012 int repeat)
2013{
2014 lirc_cmd_ctx cmd;
2015 int r;
2016
2017 r = lirc_command_init(&cmd, "SIMULATE %016x %02x %s %s\n",
2018 scancode, repeat, keysym, remote);
2019 if (r != 0)
2020 return EMSGSIZE;
2021 do
2022 r = lirc_command_run(&cmd, fd);
2023 while (r == EAGAIN);
2024 return r;
2025}
2026
2027
2029static int
2030do_connect(int domain, struct sockaddr* addr, size_t size, int quiet)
2031{
2032 int fd;
2033
2034 fd = socket(domain, SOCK_STREAM, 0);
2035 if (fd == -1) {
2036 if (!quiet) {
2037 fprintf(stderr, "do_connect: could not open socket\n");
2038 perror("open");
2039 }
2040 return -errno;
2041 }
2042 if (connect(fd, addr, size) == -1) {
2043 if (!quiet) {
2044 fprintf(stderr,
2045 "do_connect: could not connect to socket\n");
2046 perror("connect");
2047 }
2048 return -errno;
2049 }
2050 return fd;
2051}
2052
2053
2054int lirc_get_local_socket(const char* path, int quiet)
2055{
2056 const char* socket_path;
2057 struct sockaddr_un addr_un;
2058
2059 socket_path = path ? path : getenv("LIRC_SOCKET_PATH");
2060 socket_path = socket_path ? socket_path : LIRCD;
2061 if (strlen(socket_path) + 1 > sizeof(addr_un.sun_path)) {
2062 /* path is longer than sockaddr_un.sun_path field (!) */
2063 if (!quiet)
2064 fprintf(stderr, "%s: socket name is too long\n", prog);
2065 return -ENAMETOOLONG;
2066 }
2067 addr_un.sun_family = AF_UNIX;
2068 strcpy(addr_un.sun_path, socket_path);
2069 return do_connect(AF_UNIX,
2070 (struct sockaddr*)&addr_un,
2071 sizeof(addr_un),
2072 quiet);
2073}
2074
2075
2076int lirc_get_remote_socket(const char* address, int port, int quiet)
2077{
2078 struct addrinfo* addrinfos;
2079 struct addrinfo* a;
2080 char service[64];
2081 int r;
2082
2083 snprintf(service, sizeof(service),
2084 "%d", port > 0 ? port : LIRC_INET_PORT);
2085 r = getaddrinfo(address, service, NULL, &addrinfos);
2086 if (r < 0) {
2087 if (!quiet)
2088 fprintf(stderr, "get_remote_socket: host %s unknown\n",
2089 address);
2090 return -EADDRNOTAVAIL;
2091 }
2092 for (a = addrinfos; a != NULL; a = a->ai_next) {
2093 r = do_connect(a->ai_family, a->ai_addr, a->ai_addrlen, quiet);
2094 if (r >= 0)
2095 break;
2096 };
2097 freeaddrinfo(addrinfos);
2098 return r;
2099}
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.
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.