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