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