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