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