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