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 <memory>
24 #include <string>
25 #include <sys/socket.h>
26 #include <sys/stat.h>
27 #include <sys/types.h>
28 #include <sys/un.h>
29 #include <sys/wait.h>
30 #include <unistd.h>
31 
32 #include "lirc_client.h"
33 
34 // clazy:excludeall=raw-environment-function
35 // NOLINTBEGIN(performance-no-int-to-ptr)
36 // This code uses -1 throughout as the equivalent of nullptr.
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 
53 enum packet_state : std::uint8_t
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  std::string& full_name,
100  std::string& 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  unsigned int ret = 0;
847 
848  std::string filename;
849  std::string sha_bang;
850  if(lirc_readconfig_only_internal(state,file,config,check,filename,sha_bang)==-1)
851  {
852  return -1;
853  }
854 
855  if(sha_bang.empty())
856  return 0;
857 
858  /* connect to lircrcd */
859 
860  addr.sun_family=AF_UNIX;
861  if(lirc_getsocketname(filename.data(), 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  return 0;
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  return 0;
872  }
873  if(connect(sockfd, (struct sockaddr *)&addr, sizeof(addr))!=-1)
874  {
875  (*config)->sockfd=sockfd;
876 
877  /* tell daemon state->lirc_prog */
878  if(lirc_identify(state, sockfd) == LIRC_RET_SUCCESS)
879  {
880  /* we're connected */
881  return 0;
882  }
883  close(sockfd);
884  lirc_freeconfig(*config);
885  return -1;
886  }
887  close(sockfd);
888 
889  /* launch lircrcd */
890  std::string command = sha_bang + " " + filename;
891  ret = system(command.data());
892 
893  if(ret!=EXIT_SUCCESS)
894  return 0;
895 
896  sockfd=socket(AF_UNIX,SOCK_STREAM,0);
897  if(sockfd==-1)
898  {
899  lirc_printf(state, "%s: WARNING: could not open socket\n",state->lirc_prog);
900  lirc_perror(state, state->lirc_prog);
901  return 0;
902  }
903  if(connect(sockfd, (struct sockaddr *)&addr, sizeof(addr))!=-1)
904  {
905  if(lirc_identify(state, sockfd) == LIRC_RET_SUCCESS)
906  {
907  (*config)->sockfd=sockfd;
908  return 0;
909  }
910  }
911  close(sockfd);
912  lirc_freeconfig(*config);
913  return -1;
914 }
915 
916 int lirc_readconfig_only(const struct lirc_state *state,
917  const char *file,
918  struct lirc_config **config,
919  int (check)(char *s))
920 {
921  std::string filename;
922  std::string sha_bang;
923  return lirc_readconfig_only_internal(state, file, config, check, filename, sha_bang);
924 }
925 
926 static int lirc_readconfig_only_internal(const struct lirc_state *state,
927  const char *file,
928  struct lirc_config **config,
929  int (check)(char *s),
930  std::string& full_name,
931  std::string& sha_bang)
932 {
933  int ret=0;
934  int firstline=1;
935 
936  struct filestack_t *filestack = stack_push(state, nullptr);
937  if (filestack == nullptr)
938  {
939  return -1;
940  }
941  filestack->m_file = lirc_open(state, file, nullptr, &(filestack->m_name));
942  if (filestack->m_file == nullptr)
943  {
944  stack_free(filestack);
945  return -1;
946  }
947  filestack->m_line = 0;
948  int open_files = 1;
949 
950  struct lirc_config_entry *new_entry = nullptr;
951  struct lirc_config_entry *first = nullptr;
952  struct lirc_config_entry *last = nullptr;
953  char *mode=nullptr;
954  char *remote=LIRC_ALL;
955  while (filestack)
956  {
957  char *string = nullptr;
958  ret=lirc_readline(state,&string,filestack->m_file);
959  if(ret==-1 || string==nullptr)
960  {
961  fclose(filestack->m_file);
962  if(open_files == 1)
963  {
964  full_name = filestack->m_name;
965  }
966  filestack = stack_pop(filestack);
967  open_files--;
968  continue;
969  }
970  /* check for sha-bang */
971  if(firstline)
972  {
973  firstline = 0;
974  if(strncmp(string, "#!", 2)==0)
975  {
976  sha_bang=string+2;
977  }
978  }
979  filestack->m_line++;
980  char *eq=strchr(string,'=');
981  if(eq==nullptr)
982  {
983  char *strtok_state = nullptr;
984  char *token=strtok_r(string," \t",&strtok_state);
985  if ((token==nullptr) || (token[0]=='#'))
986  {
987  /* ignore empty line or comment */
988  }
989  else if(strcasecmp(token, "include") == 0)
990  {
991  if (open_files >= MAX_INCLUDES)
992  {
993  lirc_printf(state, "%s: too many files "
994  "included at %s:%d\n",
995  state->lirc_prog,
996  filestack->m_name,
997  filestack->m_line);
998  ret=-1;
999  }
1000  else
1001  {
1002  char *token2 = strtok_r(nullptr, "", &strtok_state);
1003  token2 = lirc_trim(token2);
1005  (token2, filestack->m_name,
1006  filestack->m_line);
1007  struct filestack_t *stack_tmp =
1008  stack_push(state, filestack);
1009  if (stack_tmp == nullptr)
1010  {
1011  ret=-1;
1012  }
1013  else
1014  {
1015  stack_tmp->m_file = lirc_open(state, token2, filestack->m_name, &(stack_tmp->m_name));
1016  stack_tmp->m_line = 0;
1017  if (stack_tmp->m_file)
1018  {
1019  open_files++;
1020  filestack = stack_tmp;
1021  }
1022  else
1023  {
1024  stack_pop(stack_tmp);
1025  ret=-1;
1026  }
1027  }
1028  }
1029  }
1030  else
1031  {
1032  char *token2=strtok_r(nullptr," \t",&strtok_state);
1033  if(token2!=nullptr &&
1034  strtok_r(nullptr," \t",&strtok_state)!=nullptr)
1035  {
1036  lirc_printf(state, "%s: unexpected token in line %s:%d\n",
1037  state->lirc_prog,filestack->m_name,filestack->m_line);
1038  }
1039  else
1040  {
1041  ret=lirc_mode(state, token,token2,&mode,
1042  &new_entry,&first,&last,
1043  check,
1044  filestack->m_name,
1045  filestack->m_line);
1046  if(ret==0)
1047  {
1048  if(remote!=LIRC_ALL)
1049  free(remote);
1050  remote=LIRC_ALL;
1051  }
1052  else
1053  {
1054  if(mode!=nullptr)
1055  {
1056  free(mode);
1057  mode=nullptr;
1058  }
1059  if(new_entry!=nullptr)
1060  {
1062  (new_entry);
1063  new_entry=nullptr;
1064  }
1065  }
1066  }
1067  }
1068  }
1069  else
1070  {
1071  eq[0]=0;
1072  char *token=lirc_trim(string);
1073  char *token2=lirc_trim(eq+1);
1074  if(token[0]=='#')
1075  {
1076  /* ignore comment */
1077  }
1078  else if(new_entry==nullptr)
1079  {
1080  lirc_printf(state, "%s: bad file format, %s:%d\n",
1081  state->lirc_prog,filestack->m_name,filestack->m_line);
1082  ret=-1;
1083  }
1084  else
1085  {
1086  token2=strdup(token2);
1087  if(token2==nullptr)
1088  {
1089  lirc_printf(state, "%s: out of memory\n",
1090  state->lirc_prog);
1091  ret=-1;
1092  }
1093  else if(strcasecmp(token,"prog")==0)
1094  {
1095  if(new_entry->prog!=nullptr) free(new_entry->prog);
1096  new_entry->prog=token2;
1097  }
1098  else if(strcasecmp(token,"remote")==0)
1099  {
1100  if(remote!=LIRC_ALL)
1101  free(remote);
1102 
1103  if(strcasecmp("*",token2)==0)
1104  {
1105  remote=LIRC_ALL;
1106  free(token2);
1107  }
1108  else
1109  {
1110  remote=token2;
1111  }
1112  }
1113  else if(strcasecmp(token,"button")==0)
1114  {
1115  auto *code=
1116  (struct lirc_code *)malloc(sizeof(struct lirc_code));
1117  if(code==nullptr)
1118  {
1119  free(token2);
1120  lirc_printf(state, "%s: out of "
1121  "memory\n",
1122  state->lirc_prog);
1123  ret=-1;
1124  }
1125  else
1126  {
1127  code->remote=remote;
1128  if(strcasecmp("*",token2)==0)
1129  {
1130  code->button=LIRC_ALL;
1131  free(token2);
1132  }
1133  else
1134  {
1135  code->button=token2;
1136  }
1137  code->next=nullptr;
1138 
1139  if(new_entry->code==nullptr)
1140  {
1141  new_entry->code=code;
1142  }
1143  else
1144  {
1145  new_entry->next_code->next
1146  =code;
1147  }
1148  new_entry->next_code=code;
1149  if(remote!=LIRC_ALL)
1150  {
1151  remote=strdup(remote);
1152  if(remote==nullptr)
1153  {
1154  lirc_printf(state, "%s: out of memory\n",state->lirc_prog);
1155  ret=-1;
1156  }
1157  }
1158  }
1159  }
1160  else if(strcasecmp(token,"delay")==0)
1161  {
1162  char *end = nullptr;
1163 
1164  errno=ERANGE+1;
1165  new_entry->rep_delay=strtoul(token2,&end,0);
1166  if((new_entry->rep_delay==UINT_MAX
1167  && errno==ERANGE)
1168  || end[0]!=0
1169  || strlen(token2)==0)
1170  {
1171  lirc_printf(state, "%s: \"%s\" not"
1172  " a valid number for "
1173  "delay\n",state->lirc_prog,
1174  token2);
1175  }
1176  free(token2);
1177  }
1178  else if(strcasecmp(token,"repeat")==0)
1179  {
1180  char *end = nullptr;
1181 
1182  errno=ERANGE+1;
1183  new_entry->rep=strtoul(token2,&end,0);
1184  if((new_entry->rep==UINT_MAX
1185  && errno==ERANGE)
1186  || end[0]!=0
1187  || strlen(token2)==0)
1188  {
1189  lirc_printf(state, "%s: \"%s\" not"
1190  " a valid number for "
1191  "repeat\n",state->lirc_prog,
1192  token2);
1193  }
1194  free(token2);
1195  }
1196  else if(strcasecmp(token,"config")==0)
1197  {
1198  auto *new_list =
1199  (struct lirc_list *)malloc(sizeof(struct lirc_list));
1200  if(new_list==nullptr)
1201  {
1202  free(token2);
1203  lirc_printf(state, "%s: out of "
1204  "memory\n",
1205  state->lirc_prog);
1206  ret=-1;
1207  }
1208  else
1209  {
1210  lirc_parse_string(state,token2,filestack->m_name,filestack->m_line);
1211  new_list->string=token2;
1212  new_list->next=nullptr;
1213  if(new_entry->config==nullptr)
1214  {
1215  new_entry->config=new_list;
1216  }
1217  else
1218  {
1219  new_entry->next_config->next
1220  =new_list;
1221  }
1222  new_entry->next_config=new_list;
1223  }
1224  }
1225  else if(strcasecmp(token,"mode")==0)
1226  {
1227  if(new_entry->change_mode!=nullptr) free(new_entry->change_mode);
1228  new_entry->change_mode=token2;
1229  }
1230  else if(strcasecmp(token,"flags")==0)
1231  {
1232  new_entry->flags=lirc_flags(state, token2);
1233  free(token2);
1234  }
1235  else
1236  {
1237  free(token2);
1238  lirc_printf(state, "%s: unknown token \"%s\" in %s:%d ignored\n",
1239  state->lirc_prog,token,filestack->m_name,filestack->m_line);
1240  }
1241  }
1242  }
1243  free(string);
1244  if(ret==-1) break;
1245  }
1246  if(remote!=LIRC_ALL)
1247  free(remote);
1248  if(new_entry!=nullptr)
1249  {
1250  if(ret==0)
1251  {
1252  ret=lirc_mode(state, "end",nullptr,&mode,&new_entry,
1253  &first,&last,check,"",0);
1254  lirc_printf(state, "%s: warning: end token missing at end "
1255  "of file\n",state->lirc_prog);
1256  }
1257  else
1258  {
1259  lirc_freeconfigentries(new_entry);
1260  new_entry=nullptr;
1261  }
1262  }
1263  if(mode!=nullptr)
1264  {
1265  if(ret==0)
1266  {
1267  lirc_printf(state, "%s: warning: no end token found for mode "
1268  "\"%s\"\n",state->lirc_prog,mode);
1269  }
1270  free(mode);
1271  }
1272  if(ret==0)
1273  {
1274  *config=(struct lirc_config *)
1275  malloc(sizeof(struct lirc_config));
1276  if(*config==nullptr)
1277  {
1278  lirc_printf(state, "%s: out of memory\n",state->lirc_prog);
1280  return(-1);
1281  }
1282  (*config)->first=first;
1283  (*config)->next=first;
1284  char *startupmode = lirc_startupmode(state, (*config)->first);
1285  (*config)->current_mode=startupmode ? strdup(startupmode):nullptr;
1286  (*config)->sockfd=-1;
1287  }
1288  else
1289  {
1290  *config=nullptr;
1292  sha_bang.clear();
1293  }
1294  if(filestack)
1295  {
1296  stack_free(filestack);
1297  }
1298  return(ret);
1299 }
1300 
1301 static char *lirc_startupmode(const struct lirc_state *state, struct lirc_config_entry *first)
1302 {
1303  char *startupmode=nullptr;
1304  struct lirc_config_entry *scan=first;
1305 
1306  /* Set a startup mode based on flags=startup_mode */
1307  while(scan!=nullptr)
1308  {
1309  if(scan->flags&startup_mode) {
1310  if(scan->change_mode!=nullptr) {
1311  startupmode=scan->change_mode;
1312  /* Remove the startup mode or it confuses lirc mode system */
1313  scan->change_mode=nullptr;
1314  break;
1315  }
1316  lirc_printf(state, "%s: startup_mode flags requires 'mode ='\n",
1317  state->lirc_prog);
1318  }
1319  scan=scan->next;
1320  }
1321 
1322  /* Set a default mode if we find a mode = client app name */
1323  if(startupmode==nullptr) {
1324  scan=first;
1325  while(scan!=nullptr)
1326  {
1327  if(scan->mode!=nullptr && strcasecmp(state->lirc_prog,scan->mode)==0)
1328  {
1329  startupmode=state->lirc_prog;
1330  break;
1331  }
1332  scan=scan->next;
1333  }
1334  }
1335 
1336  if(startupmode==nullptr) return nullptr;
1337  scan=first;
1338  while(scan!=nullptr)
1339  {
1340  if(scan->change_mode!=nullptr && scan->flags&once &&
1341  strcasecmp(startupmode,scan->change_mode)==0)
1342  {
1343  scan->flags|=ecno;
1344  }
1345  scan=scan->next;
1346  }
1347  return(startupmode);
1348 }
1349 
1351 {
1352  if(config!=nullptr)
1353  {
1354  if(config->sockfd!=-1)
1355  {
1356  (void) close(config->sockfd);
1357  config->sockfd=-1;
1358  }
1360  free(config->current_mode);
1361  free(config);
1362  }
1363 }
1364 
1365 static void lirc_freeconfigentries(struct lirc_config_entry *first)
1366 {
1367  struct lirc_config_entry *c=first;
1368  while(c!=nullptr)
1369  {
1370  if(c->prog) free(c->prog);
1371  if(c->change_mode) free(c->change_mode);
1372  if(c->mode) free(c->mode);
1373 
1374  struct lirc_code *code=c->code;
1375  while(code!=nullptr)
1376  {
1377  if(code->remote!=nullptr && code->remote!=LIRC_ALL)
1378  free(code->remote);
1379  if(code->button!=nullptr && code->button!=LIRC_ALL)
1380  free(code->button);
1381  struct lirc_code *code_temp=code->next;
1382  free(code);
1383  code=code_temp;
1384  }
1385 
1386  struct lirc_list *list=c->config;
1387  while(list!=nullptr)
1388  {
1389  if(list->string) free(list->string);
1390  struct lirc_list *list_temp=list->next;
1391  free(list);
1392  list=list_temp;
1393  }
1394  struct lirc_config_entry *config_temp=c->next;
1395  free(c);
1396  c=config_temp;
1397  }
1398 }
1399 
1400 static void lirc_clearmode(struct lirc_config *config)
1401 {
1402  if(config->current_mode==nullptr)
1403  {
1404  return;
1405  }
1406  struct lirc_config_entry *scan=config->first;
1407  while(scan!=nullptr)
1408  {
1409  if(scan->change_mode!=nullptr)
1410  {
1411  if(strcasecmp(scan->change_mode,config->current_mode)==0)
1412  {
1413  scan->flags&=~ecno;
1414  }
1415  }
1416  scan=scan->next;
1417  }
1418  free(config->current_mode);
1419  config->current_mode=nullptr;
1420 }
1421 
1422 static char *lirc_execute(const struct lirc_state *state,
1423  struct lirc_config *config,
1424  struct lirc_config_entry *scan)
1425 {
1426  int do_once=1;
1427 
1428  if(scan->flags&modex)
1429  {
1431  }
1432  if(scan->change_mode!=nullptr)
1433  {
1434  free(config->current_mode);
1435  config->current_mode=strdup(scan->change_mode);
1436  if(scan->flags&once)
1437  {
1438  if(scan->flags&ecno)
1439  {
1440  do_once=0;
1441  }
1442  else
1443  {
1444  scan->flags|=ecno;
1445  }
1446  }
1447  }
1448  if(scan->next_config!=nullptr &&
1449  scan->prog!=nullptr &&
1450  (state->lirc_prog == nullptr || strcasecmp(scan->prog,state->lirc_prog)==0) &&
1451  do_once==1)
1452  {
1453  char *s=scan->next_config->string;
1454  scan->next_config=scan->next_config->next;
1455  if(scan->next_config==nullptr)
1456  scan->next_config=scan->config;
1457  return(s);
1458  }
1459  return nullptr;
1460 }
1461 
1462 static int lirc_iscode(struct lirc_config_entry *scan, char *remote,
1463  char *button,unsigned int rep)
1464 {
1465  /* no remote/button specified */
1466  if(scan->code==nullptr)
1467  {
1468  return static_cast<int>(rep==0 ||
1469  (scan->rep>0 && rep>scan->rep_delay &&
1470  ((rep-scan->rep_delay-1)%scan->rep)==0));
1471  }
1472 
1473  /* remote/button match? */
1474  if(scan->next_code->remote==LIRC_ALL ||
1475  strcasecmp(scan->next_code->remote,remote)==0)
1476  {
1477  if(scan->next_code->button==LIRC_ALL ||
1478  strcasecmp(scan->next_code->button,button)==0)
1479  {
1480  int iscode=0;
1481  /* button sequence? */
1482  if(scan->code->next==nullptr || rep==0)
1483  {
1484  scan->next_code=scan->next_code->next;
1485  if(scan->code->next != nullptr)
1486  {
1487  iscode=1;
1488  }
1489  }
1490  /* sequence completed? */
1491  if(scan->next_code==nullptr)
1492  {
1493  scan->next_code=scan->code;
1494  if(scan->code->next!=nullptr || rep==0 ||
1495  (scan->rep>0 && rep>scan->rep_delay &&
1496  ((rep-scan->rep_delay-1)%scan->rep)==0))
1497  iscode=2;
1498  }
1499  return iscode;
1500  }
1501  }
1502 
1503  if(rep!=0) return(0);
1504 
1505  /* handle toggle_reset */
1506  if(scan->flags & toggle_reset)
1507  {
1508  scan->next_config = scan->config;
1509  }
1510 
1511  struct lirc_code *codes=scan->code;
1512  if(codes==scan->next_code) return(0);
1513  codes=codes->next;
1514  /* rebase code sequence */
1515  while(codes!=scan->next_code->next)
1516  {
1517  int flag=1;
1518  struct lirc_code *prev=scan->code;
1519  struct lirc_code *next=codes;
1520  while(next!=scan->next_code)
1521  {
1522  if(prev->remote==LIRC_ALL ||
1523  strcasecmp(prev->remote,next->remote)==0)
1524  {
1525  if(prev->button==LIRC_ALL ||
1526  strcasecmp(prev->button,next->button)==0)
1527  {
1528  prev=prev->next;
1529  next=next->next;
1530  }
1531  else
1532  {
1533  flag=0;break;
1534  }
1535  }
1536  else
1537  {
1538  flag=0;break;
1539  }
1540  }
1541  if(flag==1)
1542  {
1543  if(prev->remote==LIRC_ALL ||
1544  strcasecmp(prev->remote,remote)==0)
1545  {
1546  if(prev->button==LIRC_ALL ||
1547  strcasecmp(prev->button,button)==0)
1548  {
1549  if(rep==0)
1550  {
1551  scan->next_code=prev->next;
1552  return(0);
1553  }
1554  }
1555  }
1556  }
1557  codes=codes->next;
1558  }
1559  scan->next_code=scan->code;
1560  return(0);
1561 }
1562 
1563 #if 0
1564 char *lirc_ir2char(const struct lirc_state *state,struct lirc_config *config,char *code)
1565 {
1566  static int warning=1;
1567  char *string;
1568 
1569  if(warning)
1570  {
1571  fprintf(stderr,"%s: warning: lirc_ir2char() is obsolete\n",
1572  state->lirc_prog);
1573  warning=0;
1574  }
1575  if(lirc_code2char(state,config,code,&string)==-1) return nullptr;
1576  return(string);
1577 }
1578 #endif
1579 
1580 int lirc_code2char(const struct lirc_state *state, struct lirc_config *config,const char *code,char **string)
1581 {
1582  if(config->sockfd!=-1)
1583  {
1584  char* command = static_cast<char*>(malloc((10+strlen(code)+1+1) * sizeof(char)));
1585  if (command == nullptr)
1586  return LIRC_RET_ERROR;
1587  static std::array<char,LIRC_PACKET_SIZE> s_buf;
1588  size_t buf_len = s_buf.size();
1589  int success = LIRC_RET_ERROR;
1590 
1591  sprintf(command, "CODE %s\n", code);
1592 
1593  int ret = lirc_send_command(state, config->sockfd, command,
1594  s_buf.data(), &buf_len, &success);
1595  if(success == LIRC_RET_SUCCESS)
1596  {
1597  if(ret > 0)
1598  {
1599  *string = s_buf.data();
1600  }
1601  else
1602  {
1603  *string = nullptr;
1604  }
1605  free(command);
1606  return LIRC_RET_SUCCESS;
1607  }
1608  free(command);
1609  return LIRC_RET_ERROR;
1610  }
1611  return lirc_code2char_internal(state, config, code, string, nullptr);
1612 }
1613 
1614 int lirc_code2charprog(struct lirc_state *state,struct lirc_config *config,char *code,char **string,
1615  char **prog)
1616 {
1617  char *backup = state->lirc_prog;
1618  state->lirc_prog = nullptr;
1619 
1620  int ret = lirc_code2char_internal(state,config, code, string, prog);
1621 
1622  state->lirc_prog = backup;
1623  return ret;
1624 }
1625 
1626 static int lirc_code2char_internal(const struct lirc_state *state,
1627  struct lirc_config *config, const char *code,
1628  char **string, char **prog)
1629 {
1630  unsigned int rep = 0;
1631  char *strtok_state = nullptr;
1632  char *s=nullptr;
1633 
1634  *string=nullptr;
1635  if(sscanf(code,"%*20x %20x %*5000s %*5000s\n",&rep)==1)
1636  {
1637  char *backup=strdup(code);
1638  if(backup==nullptr) return(-1);
1639 
1640  strtok_r(backup," ",&strtok_state);
1641  strtok_r(nullptr," ",&strtok_state);
1642  char *button=strtok_r(nullptr," ",&strtok_state);
1643  char *remote=strtok_r(nullptr,"\n",&strtok_state);
1644 
1645  if(button==nullptr || remote==nullptr)
1646  {
1647  free(backup);
1648  return(0);
1649  }
1650 
1651  struct lirc_config_entry *scan=config->next;
1652  int quit_happened=0;
1653  while(scan!=nullptr)
1654  {
1655  int exec_level = lirc_iscode(scan,remote,button,rep);
1656  if(exec_level > 0 &&
1657  (scan->mode==nullptr ||
1658  (scan->mode!=nullptr &&
1659  config->current_mode!=nullptr &&
1660  strcasecmp(scan->mode,config->current_mode)==0)) &&
1661  quit_happened==0
1662  )
1663  {
1664  if(exec_level > 1)
1665  {
1666  s=lirc_execute(state,config,scan);
1667  if(s != nullptr && prog != nullptr)
1668  {
1669  *prog = scan->prog;
1670  }
1671  }
1672  else
1673  {
1674  s = nullptr;
1675  }
1676  if(scan->flags&quit)
1677  {
1678  quit_happened=1;
1679  config->next=nullptr;
1680  scan=scan->next;
1681  continue;
1682  }
1683  if(s!=nullptr)
1684  {
1685  config->next=scan->next;
1686  break;
1687  }
1688  }
1689  scan=scan->next;
1690  }
1691  free(backup);
1692  if(s!=nullptr)
1693  {
1694  *string=s;
1695  return(0);
1696  }
1697  }
1698  config->next=config->first;
1699  return(0);
1700 }
1701 
1702 static constexpr size_t PACKET_SIZE { 100 };
1703 
1704 #if 0
1705 char *lirc_nextir(struct lirc_state *state)
1706 {
1707  static int warning=1;
1708  char *code;
1709  int ret;
1710 
1711  if(warning)
1712  {
1713  fprintf(stderr,"%s: warning: lirc_nextir() is obsolete\n",
1714  state->lirc_prog);
1715  warning=0;
1716  }
1717  ret=lirc_nextcode(state, &code);
1718  if(ret==-1) return nullptr;
1719  return(code);
1720 }
1721 #endif
1722 
1723 int lirc_nextcode(struct lirc_state *state, char **code)
1724 {
1725  static size_t s_packetSize=PACKET_SIZE;
1726  static size_t s_endLen=0;
1727  char *end = nullptr;
1728 
1729  *code=nullptr;
1730  if(state->lirc_buffer==nullptr)
1731  {
1732  state->lirc_buffer=(char *) malloc(s_packetSize+1);
1733  if(state->lirc_buffer==nullptr)
1734  {
1735  lirc_printf(state, "%s: out of memory\n",state->lirc_prog);
1736  return(-1);
1737  }
1738  state->lirc_buffer[0]=0;
1739  }
1740  while((end=strchr(state->lirc_buffer,'\n'))==nullptr)
1741  {
1742  if(s_endLen>=s_packetSize)
1743  {
1744  s_packetSize+=PACKET_SIZE;
1745  char *new_buffer=(char *) realloc(state->lirc_buffer,s_packetSize+1);
1746  if(new_buffer==nullptr)
1747  {
1748  return(-1);
1749  }
1750  state->lirc_buffer=new_buffer;
1751  }
1752  ssize_t len=read(state->lirc_lircd,state->lirc_buffer+s_endLen,s_packetSize-s_endLen);
1753  if(len<=0)
1754  {
1755  if(len==-1 && errno==EAGAIN) return(0);
1756  return(-1);
1757  }
1758  s_endLen+=len;
1759  state->lirc_buffer[s_endLen]=0;
1760  /* return if next code not yet available completely */
1761  if(strchr(state->lirc_buffer,'\n')==nullptr)
1762  {
1763  return(0);
1764  }
1765  }
1766  /* copy first line to buffer (code) and move remaining chars to
1767  state->lirc_buffers start */
1768 
1769  // Cppcheck doesn't parse the previous loop properly. The
1770  // only way for the loop to exit and execute the next line of
1771  // code is if end becomes non-null.
1772  //
1773  end++;
1774  s_endLen=strlen(end);
1775  char c=end[0];
1776  end[0]=0;
1777  *code=strdup(state->lirc_buffer);
1778  end[0]=c;
1779  memmove(state->lirc_buffer,end,s_endLen+1);
1780  if(*code==nullptr) return(-1);
1781  return(0);
1782 }
1783 
1784 size_t lirc_getsocketname(const char *filename, char *buf, size_t size)
1785 {
1786  if(strlen(filename)+2<=size)
1787  {
1788  strcpy(buf, filename);
1789  strcat(buf, "d");
1790  }
1791  return strlen(filename)+2;
1792 }
1793 
1794 const char *lirc_getmode(const struct lirc_state *state, struct lirc_config *config)
1795 {
1796  if(config->sockfd!=-1)
1797  {
1798  static std::array<char,LIRC_PACKET_SIZE> s_buf;
1799  size_t buf_len = s_buf.size();
1800  int success = LIRC_RET_ERROR;
1801 
1802  int ret = lirc_send_command(state, config->sockfd, "GETMODE\n",
1803  s_buf.data(), &buf_len, &success);
1804  if(success == LIRC_RET_SUCCESS)
1805  {
1806  if(ret > 0)
1807  {
1808  return s_buf.data();
1809  }
1810  return nullptr;
1811  }
1812  return nullptr;
1813  }
1814  return config->current_mode;
1815 }
1816 
1817 const char *lirc_setmode(const struct lirc_state *state, struct lirc_config *config, const char *mode)
1818 {
1819  if(config->sockfd!=-1)
1820  {
1821  static std::array<char,LIRC_PACKET_SIZE> s_buf {};
1822  std::array<char,LIRC_PACKET_SIZE> cmd {};
1823  size_t buf_len = s_buf.size();
1824  int success = LIRC_RET_ERROR;
1825  if(snprintf(cmd.data(), LIRC_PACKET_SIZE, "SETMODE%s%s\n",
1826  mode ? " ":"",
1827  mode ? mode:"")
1828  >= static_cast<int>(LIRC_PACKET_SIZE))
1829  {
1830  return nullptr;
1831  }
1832 
1833  int ret = lirc_send_command(state, config->sockfd, cmd.data(),
1834  s_buf.data(), &buf_len, &success);
1835  if(success == LIRC_RET_SUCCESS)
1836  {
1837  if(ret > 0)
1838  {
1839  return s_buf.data();
1840  }
1841  return nullptr;
1842  }
1843  return nullptr;
1844  }
1845 
1846  free(config->current_mode);
1847  config->current_mode = mode ? strdup(mode) : nullptr;
1848  return config->current_mode;
1849 }
1850 
1851 static const char *lirc_read_string(const struct lirc_state *state, int fd)
1852 {
1853  static std::array<char,LIRC_PACKET_SIZE+1> s_buffer;
1854  char *end = nullptr;
1855  static size_t s_head=0;
1856  static size_t s_tail=0;
1857  int ret = 0;
1858  ssize_t n = 0;
1859  fd_set fds;
1860  struct timeval tv {};
1861 
1862  auto cleanup_fn = [&](int */*x*/) {
1863  s_head=s_tail=0;
1864  s_buffer[0]=0;
1865  };
1866  std::unique_ptr<int,decltype(cleanup_fn)> cleanup { &ret, cleanup_fn };
1867 
1868  if(s_head>0)
1869  {
1870  memmove(s_buffer.data(),s_buffer.data()+s_head,s_tail-s_head+1);
1871  s_tail-=s_head;
1872  s_head=0;
1873  end=strchr(s_buffer.data(),'\n');
1874  }
1875  else
1876  {
1877  end=nullptr;
1878  }
1879  if(strlen(s_buffer.data())!=s_tail)
1880  {
1881  lirc_printf(state, "%s: protocol error\n", state->lirc_prog);
1882  return nullptr;
1883  }
1884 
1885  while(end==nullptr)
1886  {
1887  if(LIRC_PACKET_SIZE<=s_tail)
1888  {
1889  lirc_printf(state, "%s: bad packet\n", state->lirc_prog);
1890  return nullptr;
1891  }
1892 
1893  FD_ZERO(&fds); // NOLINT(readability-isolate-declaration)
1894  FD_SET(fd,&fds);
1895  tv.tv_sec=LIRC_TIMEOUT;
1896  tv.tv_usec=0;
1897  ret=select(fd+1,&fds,nullptr,nullptr,&tv);
1898  while(ret==-1 && errno==EINTR)
1899  ret=select(fd+1,&fds,nullptr,nullptr,&tv);
1900  if(ret==-1)
1901  {
1902  lirc_printf(state, "%s: select() failed\n", state->lirc_prog);
1903  lirc_perror(state, state->lirc_prog);
1904  return nullptr;
1905  }
1906  if(ret==0)
1907  {
1908  lirc_printf(state, "%s: timeout\n", state->lirc_prog);
1909  return nullptr;
1910  }
1911 
1912  n=read(fd, s_buffer.data()+s_tail, LIRC_PACKET_SIZE-s_tail);
1913  if(n<=0)
1914  {
1915  lirc_printf(state, "%s: read() failed\n", state->lirc_prog);
1916  lirc_perror(state, state->lirc_prog);
1917  return nullptr;
1918  }
1919  s_buffer[s_tail+n]=0;
1920  s_tail+=n;
1921  end=strchr(s_buffer.data(),'\n');
1922  }
1923 
1924  end[0]=0;
1925  s_head=strlen(s_buffer.data())+1;
1926  (void)cleanup.release();
1927  return(s_buffer.data());
1928 }
1929 
1930 int lirc_send_command(const struct lirc_state *lstate, int sockfd, const char *command, char *buf, size_t *buf_len, int *ret_status)
1931 {
1932  char *endptr = nullptr;
1933  unsigned long n = 0;
1934  unsigned long data_n=0;
1935  size_t written=0;
1936  size_t max=0;
1937  size_t len = 0;
1938 
1939  if(buf_len!=nullptr)
1940  {
1941  max=*buf_len;
1942  }
1943  int todo=strlen(command);
1944  const char *data=command;
1945  lirc_printf(lstate, "%s: sending command: %s",
1946  lstate->lirc_prog, command);
1947  while(todo>0)
1948  {
1949  int done=write(sockfd,(const void *) data,todo);
1950  if(done<0)
1951  {
1952  lirc_printf(lstate, "%s: could not send packet\n",
1953  lstate->lirc_prog);
1954  lirc_perror(lstate, lstate->lirc_prog);
1955  return(-1);
1956  }
1957  data+=done;
1958  todo-=done;
1959  }
1960 
1961  /* get response */
1962  int status=LIRC_RET_SUCCESS;
1963  enum packet_state state=P_BEGIN;
1964  bool good_packet = false;
1965  bool bad_packet = false;
1966  n=0;
1967  while(!good_packet && !bad_packet)
1968  {
1969  const char *string=lirc_read_string(lstate, sockfd);
1970  if(string==nullptr) return(-1);
1971  lirc_printf(lstate, "%s: read response: %s\n",
1972  lstate->lirc_prog, string);
1973  switch(state)
1974  {
1975  case P_BEGIN:
1976  if(strcasecmp(string,"BEGIN")!=0)
1977  {
1978  continue;
1979  }
1980  state=P_MESSAGE;
1981  break;
1982  case P_MESSAGE:
1983  if(strncasecmp(string,command,strlen(string))!=0 ||
1984  strlen(string)+1!=strlen(command))
1985  {
1986  state=P_BEGIN;
1987  continue;
1988  }
1989  state=P_STATUS;
1990  break;
1991  case P_STATUS:
1992  if(strcasecmp(string,"SUCCESS")==0)
1993  {
1994  status=LIRC_RET_SUCCESS;
1995  }
1996  else if(strcasecmp(string,"END")==0)
1997  {
1998  status=LIRC_RET_SUCCESS;
1999  good_packet = true;
2000  break;
2001  }
2002  else if(strcasecmp(string,"ERROR")==0)
2003  {
2004  lirc_printf(lstate, "%s: command failed: %s",
2005  lstate->lirc_prog, command);
2006  status=LIRC_RET_ERROR;
2007  }
2008  else
2009  {
2010  bad_packet = true;
2011  break;
2012  }
2013  state=P_DATA;
2014  break;
2015  case P_DATA:
2016  if(strcasecmp(string,"END")==0)
2017  {
2018  good_packet = true;
2019  break;
2020  }
2021  else if(strcasecmp(string,"DATA")==0)
2022  {
2023  state=P_N;
2024  break;
2025  }
2026  bad_packet = true;
2027  break;
2028  case P_N:
2029  errno=0;
2030  data_n=strtoul(string,&endptr,0);
2031  if(!*string || *endptr)
2032  {
2033  bad_packet = true;
2034  break;
2035  }
2036  if(data_n==0)
2037  {
2038  state=P_END;
2039  }
2040  else
2041  {
2042  state=P_DATA_N;
2043  }
2044  break;
2045  case P_DATA_N:
2046  len=strlen(string);
2047  if(buf!=nullptr && written+len+1<max)
2048  {
2049  memcpy(buf+written, string, len+1);
2050  }
2051  written+=len+1;
2052  n++;
2053  if(n==data_n) state=P_END;
2054  break;
2055  case P_END:
2056  if(strcasecmp(string,"END")==0)
2057  {
2058  good_packet = true;
2059  break;
2060  }
2061  bad_packet = true;
2062  break;
2063  }
2064  }
2065 
2066  if (bad_packet)
2067  {
2068  lirc_printf(lstate, "%s: bad return packet\n", lstate->lirc_prog);
2069  return(-1);
2070  }
2071 
2072  if(ret_status!=nullptr)
2073  {
2074  *ret_status=status;
2075  }
2076  if(buf_len!=nullptr)
2077  {
2078  *buf_len=written;
2079  }
2080  return (int) data_n;
2081 }
2082 
2083 int lirc_identify(const struct lirc_state *state, int sockfd)
2084 {
2085  char* command = static_cast<char*>(malloc((10+strlen(state->lirc_prog)+1+1) * sizeof(char)));
2086  if (command == nullptr)
2087  return LIRC_RET_ERROR;
2088  int success = LIRC_RET_ERROR;
2089 
2090  sprintf(command, "IDENT %s\n", state->lirc_prog);
2091 
2092  (void) lirc_send_command(state, sockfd, command, nullptr, nullptr, &success);
2093  free(command);
2094  return success;
2095 }
2096 // NOLINTEND(performance-no-int-to-ptr)
LIRC_TIMEOUT
static constexpr int8_t LIRC_TIMEOUT
Definition: lirc_client.cpp:43
P_MESSAGE
@ P_MESSAGE
Definition: lirc_client.cpp:56
lirc_state::lircrc_root_file
char * lircrc_root_file
Definition: lirc_client.h:43
P_N
@ P_N
Definition: lirc_client.cpp:59
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:916
lirc_execute
static char * lirc_execute(const struct lirc_state *state, struct lirc_config *config, struct lirc_config_entry *scan)
Definition: lirc_client.cpp:1422
lirc_read_string
static const char * lirc_read_string(const struct lirc_state *state, int fd)
Definition: lirc_client.cpp:1851
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:411
lirc_deinit
int lirc_deinit(struct lirc_state *state)
Definition: lirc_client.cpp:210
P_END
@ P_END
Definition: lirc_client.cpp:61
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:307
filestack_t::m_line
int m_line
Definition: lirc_client.cpp:49
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:1930
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
packet_state
packet_state
Definition: lirc_client.cpp:53
lirc_identify
static int lirc_identify(const struct lirc_state *state, int sockfd)
Definition: lirc_client.cpp:2083
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:1365
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:54
mythburn.FILE
int FILE
Definition: mythburn.py:138
lirc_setmode
const char * lirc_setmode(const struct lirc_state *state, struct lirc_config *config, const char *mode)
Definition: lirc_client.cpp:1817
close
#define close
Definition: compat.h:39
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
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:1350
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
P_DATA_N
@ P_DATA_N
Definition: lirc_client.cpp:60
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:1614
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:1580
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_getsocketname
size_t lirc_getsocketname(const char *filename, char *buf, size_t size)
Definition: lirc_client.cpp:1784
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:1301
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
cleanup
static QString cleanup(const QString &str)
Definition: remoteencoder.cpp:673
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
P_BEGIN
@ P_BEGIN
Definition: lirc_client.cpp:55
lirc_clearmode
static void lirc_clearmode(struct lirc_config *config)
Definition: lirc_client.cpp:1400
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:1462
filestack_t::m_parent
struct filestack_t * m_parent
Definition: lirc_client.cpp:50
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), std::string &full_name, std::string &sha_bang)
Definition: lirc_client.cpp:926
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:1626
PACKET_SIZE
static constexpr size_t PACKET_SIZE
Definition: lirc_client.cpp:1702
filestack_t
Definition: lirc_client.cpp:46
lirc_nextcode
int lirc_nextcode(struct lirc_state *state, char **code)
Definition: lirc_client.cpp:1723
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:59
LIRC_READ
static constexpr size_t LIRC_READ
Definition: lirc_client.cpp:40
P_STATUS
@ P_STATUS
Definition: lirc_client.cpp:57
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:58
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
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:1794