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