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