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