00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifdef HAVE_CONFIG_H
00018 # include <config.h>
00019 #endif
00020
00021 #include <errno.h>
00022 #include <unistd.h>
00023 #include <stdio.h>
00024 #include <stdlib.h>
00025 #include <stdarg.h>
00026 #include <string.h>
00027 #include <limits.h>
00028 #include <sys/socket.h>
00029 #include <sys/un.h>
00030 #include <sys/stat.h>
00031 #include <sys/types.h>
00032 #include <sys/wait.h>
00033
00034 #include "lirc_client.h"
00035 #include "mythsystem.h"
00036
00037
00038
00039 #define MAX_INCLUDES 10
00040 #define LIRC_READ 255
00041 #define LIRC_PACKET_SIZE 255
00042
00043 #define LIRC_TIMEOUT 3
00044
00045
00046 struct filestack_t {
00047 FILE *file;
00048 char *name;
00049 int line;
00050 struct filestack_t *parent;
00051 };
00052
00053 enum packet_state
00054 {
00055 P_BEGIN,
00056 P_MESSAGE,
00057 P_STATUS,
00058 P_DATA,
00059 P_N,
00060 P_DATA_N,
00061 P_END
00062 };
00063
00064
00065 static void lirc_printf(const struct lirc_state*, const char *format_str, ...);
00066 static void lirc_perror(const struct lirc_state*, const char *s);
00067 static int lirc_readline(const struct lirc_state *state, char **line,FILE *f);
00068 static char *lirc_trim(char *s);
00069 static char lirc_parse_escape(const struct lirc_state *state, char **s,const char *name,int line);
00070 static void lirc_parse_string(const struct lirc_state *state, char *s,const char *name,int line);
00071 static void lirc_parse_include(char *s,const char *name,int line);
00072 static int lirc_mode(
00073 const struct lirc_state *state,
00074 const char *token,const char *token2,char **mode,
00075 struct lirc_config_entry **new_config,
00076 struct lirc_config_entry **first_config,
00077 struct lirc_config_entry **last_config,
00078 int (check)(char *s),
00079 const char *name,int line);
00080
00081
00082
00083
00084
00085 static unsigned int lirc_flags(const struct lirc_state *state, char *string);
00086 static char *lirc_getfilename(const struct lirc_state *state,
00087 const char *file,
00088 const char *current_file);
00089 static FILE *lirc_open(const struct lirc_state *state,
00090 const char *file, const char *current_file,
00091 char **full_name);
00092 static struct filestack_t *stack_push(const struct lirc_state *state, struct filestack_t *parent);
00093 static struct filestack_t *stack_pop(struct filestack_t *entry);
00094 static void stack_free(struct filestack_t *entry);
00095 static int lirc_readconfig_only_internal(const struct lirc_state *state,
00096 const char *file,
00097 struct lirc_config **config,
00098 int (check)(char *s),
00099 char **full_name,
00100 char **sha_bang);
00101 static char *lirc_startupmode(const struct lirc_state *state,
00102 struct lirc_config_entry *first);
00103 static void lirc_freeconfigentries(struct lirc_config_entry *first);
00104 static void lirc_clearmode(struct lirc_config *config);
00105 static char *lirc_execute(const struct lirc_state *state,
00106 struct lirc_config *config,
00107 struct lirc_config_entry *scan);
00108 static int lirc_iscode(struct lirc_config_entry *scan, char *remote,
00109 char *button,int rep);
00110 static int lirc_code2char_internal(const struct lirc_state *state,
00111 struct lirc_config *config,char *code,
00112 char **string, char **prog);
00113 static const char *lirc_read_string(const struct lirc_state *state, int fd);
00114 static int lirc_identify(const struct lirc_state *state, int sockfd);
00115
00116 static int lirc_send_command(const struct lirc_state *state, int sockfd, const char *command, char *buf, size_t *buf_len, int *ret_status);
00117
00118 static void lirc_printf(const struct lirc_state *state, const char *format_str, ...)
00119 {
00120 va_list ap;
00121
00122 if(state && !state->lirc_verbose) return;
00123
00124 va_start(ap,format_str);
00125 vfprintf(stderr,format_str,ap);
00126 va_end(ap);
00127 }
00128
00129 static void lirc_perror(const struct lirc_state *state, const char *s)
00130 {
00131 if(!state->lirc_verbose) return;
00132
00133 perror(s);
00134 }
00135
00136 struct lirc_state *lirc_init(const char *lircrc_root_file,
00137 const char *lircrc_user_file,
00138 const char *prog,
00139 const char *lircd,
00140 int verbose)
00141 {
00142 struct sockaddr_un addr;
00143
00144
00145
00146 if(lircrc_root_file==NULL || lircrc_user_file == NULL || prog==NULL)
00147 {
00148 lirc_printf(NULL, "%s: lirc_init invalid params\n",prog);
00149 return(NULL);
00150 }
00151
00152 struct lirc_state *state = (struct lirc_state *) calloc(1, sizeof(struct lirc_state));
00153 if(state==NULL)
00154 {
00155 lirc_printf(NULL, "%s: out of memory\n",prog);
00156 return(NULL);
00157 }
00158 state->lirc_lircd=-1;
00159 state->lirc_verbose=verbose;
00160
00161 state->lircrc_root_file=strdup(lircrc_root_file);
00162 if(state->lircrc_root_file==NULL)
00163 {
00164 lirc_printf(state, "%s: out of memory\n",prog);
00165 lirc_deinit(state);
00166 return(NULL);
00167 }
00168
00169 state->lircrc_user_file=strdup(lircrc_user_file);
00170 if(state->lircrc_user_file==NULL)
00171 {
00172 lirc_printf(state, "%s: out of memory\n",prog);
00173 lirc_deinit(state);
00174 return(NULL);
00175 }
00176
00177 state->lirc_prog=strdup(prog);
00178 if(state->lirc_prog==NULL)
00179 {
00180 lirc_printf(state, "%s: out of memory\n",prog);
00181 lirc_deinit(state);
00182 return(NULL);
00183 }
00184
00185 if (lircd)
00186 {
00187 addr.sun_family=AF_UNIX;
00188 strncpy(addr.sun_path,lircd,sizeof(addr.sun_path)-1);
00189 state->lirc_lircd=socket(AF_UNIX,SOCK_STREAM,0);
00190 if(state->lirc_lircd==-1)
00191 {
00192 lirc_printf(state, "%s: could not open socket\n",state->lirc_prog);
00193 lirc_perror(state, state->lirc_prog);
00194 lirc_deinit(state);
00195 return(NULL);
00196 }
00197 if(connect(state->lirc_lircd,(struct sockaddr *)&addr,sizeof(addr))==-1)
00198 {
00199 close(state->lirc_lircd);
00200 lirc_printf(state, "%s: could not connect to socket\n",state->lirc_prog);
00201 lirc_perror(state, state->lirc_prog);
00202 lirc_deinit(state);
00203 return(NULL);
00204 }
00205 }
00206
00207 return(state);
00208 }
00209
00210 int lirc_deinit(struct lirc_state *state)
00211 {
00212 int ret = LIRC_RET_SUCCESS;
00213 if (state==NULL)
00214 return ret;
00215 if(state->lircrc_root_file!=NULL)
00216 {
00217 free(state->lircrc_root_file);
00218 state->lircrc_root_file=NULL;
00219 }
00220 if(state->lircrc_user_file!=NULL)
00221 {
00222 free(state->lircrc_user_file);
00223 state->lircrc_user_file=NULL;
00224 }
00225 if(state->lirc_prog!=NULL)
00226 {
00227 free(state->lirc_prog);
00228 state->lirc_prog=NULL;
00229 }
00230 if(state->lirc_buffer!=NULL)
00231 {
00232 free(state->lirc_buffer);
00233 state->lirc_buffer=NULL;
00234 }
00235 if (state->lirc_lircd!=-1)
00236 ret = close(state->lirc_lircd);
00237 free(state);
00238 return ret;
00239 }
00240
00241 static int lirc_readline(const struct lirc_state *state, char **line,FILE *f)
00242 {
00243 char *newline,*ret,*enlargeline;
00244 int len;
00245
00246 newline=(char *) malloc(LIRC_READ+1);
00247 if(newline==NULL)
00248 {
00249 lirc_printf(state, "%s: out of memory\n",state->lirc_prog);
00250 return(-1);
00251 }
00252 len=0;
00253 while(1)
00254 {
00255 ret=fgets(newline+len,LIRC_READ+1,f);
00256 if(ret==NULL)
00257 {
00258 if(feof(f) && len>0)
00259 {
00260 *line=newline;
00261 }
00262 else
00263 {
00264 free(newline);
00265 *line=NULL;
00266 }
00267 return(0);
00268 }
00269 len=strlen(newline);
00270 if(newline[len-1]=='\n')
00271 {
00272 newline[len-1]=0;
00273 *line=newline;
00274 return(0);
00275 }
00276
00277 enlargeline=(char *) realloc(newline,len+1+LIRC_READ);
00278 if(enlargeline==NULL)
00279 {
00280 free(newline);
00281 lirc_printf(state, "%s: out of memory\n",state->lirc_prog);
00282 return(-1);
00283 }
00284 newline=enlargeline;
00285 }
00286 }
00287
00288 static char *lirc_trim(char *s)
00289 {
00290 int len;
00291
00292 while(s[0]==' ' || s[0]=='\t') s++;
00293 len=strlen(s);
00294 while(len>0)
00295 {
00296 len--;
00297 if(s[len]==' ' || s[len]=='\t') s[len]=0;
00298 else break;
00299 }
00300 return(s);
00301 }
00302
00303
00304
00305 static char lirc_parse_escape(const struct lirc_state *state, char **s,const char *name,int line)
00306 {
00307
00308 char c;
00309 unsigned int i,overflow,count;
00310 int digits_found,digit;
00311
00312 c=**s;
00313 (*s)++;
00314 switch(c)
00315 {
00316 case 'a':
00317 return('\a');
00318 case 'b':
00319 return('\b');
00320 case 'e':
00321 #if 0
00322 case 'E':
00323 #endif
00324 return(033);
00325 case 'f':
00326 return('\f');
00327 case 'n':
00328 return('\n');
00329 case 'r':
00330 return('\r');
00331 case 't':
00332 return('\t');
00333 case 'v':
00334 return('\v');
00335 case '\n':
00336 return(0);
00337 case 0:
00338 (*s)--;
00339 return 0;
00340 case '0':
00341 case '1':
00342 case '2':
00343 case '3':
00344 case '4':
00345 case '5':
00346 case '6':
00347 case '7':
00348 i=c-'0';
00349 count=0;
00350
00351 while(++count<3)
00352 {
00353 c=*(*s)++;
00354 if(c>='0' && c<='7')
00355 {
00356 i=(i << 3)+c-'0';
00357 }
00358 else
00359 {
00360 (*s)--;
00361 break;
00362 }
00363 }
00364 if(i>(1<<CHAR_BIT)-1)
00365 {
00366 i&=(1<<CHAR_BIT)-1;
00367 lirc_printf(state, "%s: octal escape sequence "
00368 "out of range in %s:%d\n",state->lirc_prog,
00369 name,line);
00370 }
00371 return((char) i);
00372 case 'x':
00373 {
00374 i=0;
00375 overflow=0;
00376 digits_found=0;
00377 for (;;)
00378 {
00379 c = *(*s)++;
00380 if(c>='0' && c<='9')
00381 digit=c-'0';
00382 else if(c>='a' && c<='f')
00383 digit=c-'a'+10;
00384 else if(c>='A' && c<='F')
00385 digit=c-'A'+10;
00386 else
00387 {
00388 (*s)--;
00389 break;
00390 }
00391 overflow|=i^(i<<4>>4);
00392 i=(i<<4)+digit;
00393 digits_found=1;
00394 }
00395 if(!digits_found)
00396 {
00397 lirc_printf(state, "%s: \\x used with no "
00398 "following hex digits in %s:%d\n",
00399 state->lirc_prog,name,line);
00400 }
00401 if(overflow || i>(1<<CHAR_BIT)-1)
00402 {
00403 i&=(1<<CHAR_BIT)-1;
00404 lirc_printf(state, "%s: hex escape sequence out "
00405 "of range in %s:%d\n",
00406 state->lirc_prog,name,line);
00407 }
00408 return((char) i);
00409 }
00410 default:
00411 if(c>='@' && c<='Z') return(c-'@');
00412 return(c);
00413 }
00414 }
00415
00416 static void lirc_parse_string(const struct lirc_state *state, char *s,const char *name,int line)
00417 {
00418 char *t;
00419
00420 t=s;
00421 while(*s!=0)
00422 {
00423 if(*s=='\\')
00424 {
00425 s++;
00426 *t=lirc_parse_escape(state, &s,name,line);
00427 t++;
00428 }
00429 else
00430 {
00431 *t=*s;
00432 s++;
00433 t++;
00434 }
00435 }
00436 *t=0;
00437 }
00438
00439 static void lirc_parse_include(char *s,const char *name,int line)
00440 {
00441 char last;
00442 size_t len;
00443
00444 len=strlen(s);
00445 if(len<2)
00446 {
00447 return;
00448 }
00449 last=s[len-1];
00450 if(*s!='"' && *s!='<')
00451 {
00452 return;
00453 }
00454 if(*s=='"' && last!='"')
00455 {
00456 return;
00457 }
00458 else if(*s=='<' && last!='>')
00459 {
00460 return;
00461 }
00462 s[len-1]=0;
00463 memmove(s, s+1, len-2+1);
00464 }
00465
00466 int lirc_mode(const struct lirc_state *state,
00467 const char *token,const char *token2,char **mode,
00468 struct lirc_config_entry **new_config,
00469 struct lirc_config_entry **first_config,
00470 struct lirc_config_entry **last_config,
00471 int (check)(char *s),
00472 const char *name,int line)
00473 {
00474 struct lirc_config_entry *new_entry;
00475
00476 new_entry=*new_config;
00477 if(strcasecmp(token,"begin")==0)
00478 {
00479 if(token2==NULL)
00480 {
00481 if(new_entry==NULL)
00482 {
00483 new_entry=(struct lirc_config_entry *)
00484 malloc(sizeof(struct lirc_config_entry));
00485 if(new_entry==NULL)
00486 {
00487 lirc_printf(state, "%s: out of memory\n",
00488 state->lirc_prog);
00489 return(-1);
00490 }
00491 else
00492 {
00493 new_entry->prog=NULL;
00494 new_entry->code=NULL;
00495 new_entry->rep_delay=0;
00496 new_entry->rep=0;
00497 new_entry->config=NULL;
00498 new_entry->change_mode=NULL;
00499 new_entry->flags=none;
00500 new_entry->mode=NULL;
00501 new_entry->next_config=NULL;
00502 new_entry->next_code=NULL;
00503 new_entry->next=NULL;
00504
00505 *new_config=new_entry;
00506 }
00507 }
00508 else
00509 {
00510 lirc_printf(state, "%s: bad file format, "
00511 "%s:%d\n",state->lirc_prog,name,line);
00512 return(-1);
00513 }
00514 }
00515 else
00516 {
00517 if(new_entry==NULL && *mode==NULL)
00518 {
00519 *mode=strdup(token2);
00520 if(*mode==NULL)
00521 {
00522 return(-1);
00523 }
00524 }
00525 else
00526 {
00527 lirc_printf(state, "%s: bad file format, "
00528 "%s:%d\n",state->lirc_prog,name,line);
00529 return(-1);
00530 }
00531 }
00532 }
00533 else if(strcasecmp(token,"end")==0)
00534 {
00535 if(token2==NULL)
00536 {
00537 if(new_entry!=NULL)
00538 {
00539 #if 0
00540 if(new_entry->prog==NULL)
00541 {
00542 lirc_printf(state, "%s: prog missing in "
00543 "config before line %d\n",
00544 state->lirc_prog,line);
00545 lirc_freeconfigentries(new_entry);
00546 *new_config=NULL;
00547 return(-1);
00548 }
00549 if(strcasecmp(new_entry->prog,state->lirc_prog)!=0)
00550 {
00551 lirc_freeconfigentries(new_entry);
00552 *new_config=NULL;
00553 return(0);
00554 }
00555 #endif
00556 new_entry->next_code=new_entry->code;
00557 new_entry->next_config=new_entry->config;
00558 if(*last_config==NULL)
00559 {
00560 *first_config=new_entry;
00561 *last_config=new_entry;
00562 }
00563 else
00564 {
00565 (*last_config)->next=new_entry;
00566 *last_config=new_entry;
00567 }
00568 *new_config=NULL;
00569
00570 if(*mode!=NULL)
00571 {
00572 new_entry->mode=strdup(*mode);
00573 if(new_entry->mode==NULL)
00574 {
00575 lirc_printf(state, "%s: out of "
00576 "memory\n",
00577 state->lirc_prog);
00578 return(-1);
00579 }
00580 }
00581
00582 if(check!=NULL &&
00583 new_entry->prog!=NULL &&
00584 strcasecmp(new_entry->prog,state->lirc_prog)==0)
00585 {
00586 struct lirc_list *list;
00587
00588 list=new_entry->config;
00589 while(list!=NULL)
00590 {
00591 if(check(list->string)==-1)
00592 {
00593 return(-1);
00594 }
00595 list=list->next;
00596 }
00597 }
00598
00599 if (new_entry->rep_delay==0 &&
00600 new_entry->rep>0)
00601 {
00602 new_entry->rep_delay=new_entry->rep-1;
00603 }
00604 }
00605 else
00606 {
00607 lirc_printf(state, "%s: %s:%d: 'end' without "
00608 "'begin'\n",state->lirc_prog,name,line);
00609 return(-1);
00610 }
00611 }
00612 else
00613 {
00614 if(*mode!=NULL)
00615 {
00616 if(new_entry!=NULL)
00617 {
00618 lirc_printf(state, "%s: %s:%d: missing "
00619 "'end' token\n",state->lirc_prog,
00620 name,line);
00621 return(-1);
00622 }
00623 if(strcasecmp(*mode,token2)==0)
00624 {
00625 free(*mode);
00626 *mode=NULL;
00627 }
00628 else
00629 {
00630 lirc_printf(state, "%s: \"%s\" doesn't "
00631 "match mode \"%s\"\n",
00632 state->lirc_prog,token2,*mode);
00633 return(-1);
00634 }
00635 }
00636 else
00637 {
00638 lirc_printf(state, "%s: %s:%d: 'end %s' without "
00639 "'begin'\n",state->lirc_prog,name,line,
00640 token2);
00641 return(-1);
00642 }
00643 }
00644 }
00645 else
00646 {
00647 lirc_printf(state, "%s: unknown token \"%s\" in %s:%d ignored\n",
00648 state->lirc_prog,token,name,line);
00649 }
00650 return(0);
00651 }
00652
00653 unsigned int lirc_flags(const struct lirc_state *state, char *string)
00654 {
00655 char *s, *strtok_state = NULL;
00656 unsigned int flags;
00657
00658 flags=none;
00659 s=strtok_r(string," \t|",&strtok_state);
00660 while(s)
00661 {
00662 if(strcasecmp(s,"once")==0)
00663 {
00664 flags|=once;
00665 }
00666 else if(strcasecmp(s,"quit")==0)
00667 {
00668 flags|=quit;
00669 }
00670 else if(strcasecmp(s,"mode")==0)
00671 {
00672 flags|=mode;
00673 }
00674 else if(strcasecmp(s,"startup_mode")==0)
00675 {
00676 flags|=startup_mode;
00677 }
00678 else if(strcasecmp(s,"toggle_reset")==0)
00679 {
00680 flags|=toggle_reset;
00681 }
00682 else
00683 {
00684 lirc_printf(state, "%s: unknown flag \"%s\"\n",state->lirc_prog,s);
00685 }
00686 s=strtok_r(NULL," \t",&strtok_state);
00687 }
00688 return(flags);
00689 }
00690
00691 static char *lirc_getfilename(const struct lirc_state *state,
00692 const char *file,
00693 const char *current_file)
00694 {
00695 const char *home;
00696 char *filename;
00697
00698 if(file==NULL)
00699 {
00700 home=getenv("HOME");
00701 if(home==NULL)
00702 {
00703 home="/";
00704 }
00705 filename=(char *) malloc(strlen(home)+1+
00706 strlen(state->lircrc_user_file)+1);
00707 if(filename==NULL)
00708 {
00709 lirc_printf(state, "%s: out of memory\n",state->lirc_prog);
00710 return NULL;
00711 }
00712 strcpy(filename,home);
00713 if(strlen(home)>0 && filename[strlen(filename)-1]!='/')
00714 {
00715 strcat(filename,"/");
00716 }
00717 strcat(filename,state->lircrc_user_file);
00718 }
00719 else if(strncmp(file, "~/", 2)==0)
00720 {
00721 home=getenv("HOME");
00722 if(home==NULL)
00723 {
00724 home="/";
00725 }
00726 filename=(char *) malloc(strlen(home)+strlen(file)+1);
00727 if(filename==NULL)
00728 {
00729 lirc_printf(state, "%s: out of memory\n",state->lirc_prog);
00730 return NULL;
00731 }
00732 strcpy(filename,home);
00733 strcat(filename,file+1);
00734 }
00735 else if(file[0]=='/' || current_file==NULL)
00736 {
00737
00738 filename=strdup(file);
00739 if(filename==NULL)
00740 {
00741 lirc_printf(state, "%s: out of memory\n",state->lirc_prog);
00742 return NULL;
00743 }
00744 }
00745 else
00746 {
00747
00748 int pathlen = strlen(current_file);
00749 while (pathlen>0 && current_file[pathlen-1]!='/')
00750 pathlen--;
00751 filename=(char *) malloc(pathlen+strlen(file)+1);
00752 if(filename==NULL)
00753 {
00754 lirc_printf(state, "%s: out of memory\n",state->lirc_prog);
00755 return NULL;
00756 }
00757 memcpy(filename,current_file,pathlen);
00758 filename[pathlen]=0;
00759 strcat(filename,file);
00760 }
00761 return filename;
00762 }
00763
00764 static FILE *lirc_open(const struct lirc_state *state,
00765 const char *file, const char *current_file,
00766 char **full_name)
00767 {
00768 FILE *fin;
00769 char *filename;
00770
00771 filename=lirc_getfilename(state, file, current_file);
00772 if(filename==NULL)
00773 {
00774 return NULL;
00775 }
00776
00777 fin=fopen(filename,"r");
00778 if(fin==NULL && (file!=NULL || errno!=ENOENT))
00779 {
00780 lirc_printf(state, "%s: could not open config file %s\n",
00781 state->lirc_prog,filename);
00782 lirc_perror(state, state->lirc_prog);
00783 }
00784 else if(fin==NULL)
00785 {
00786 fin=fopen(state->lircrc_root_file,"r");
00787 if(fin==NULL && errno!=ENOENT)
00788 {
00789 lirc_printf(state, "%s: could not open config file %s\n",
00790 state->lirc_prog,state->lircrc_root_file);
00791 lirc_perror(state, state->lirc_prog);
00792 }
00793 else if(fin==NULL)
00794 {
00795 lirc_printf(state, "%s: could not open config files "
00796 "%s and %s\n",
00797 state->lirc_prog,filename,state->lircrc_root_file);
00798 lirc_perror(state, state->lirc_prog);
00799 }
00800 else
00801 {
00802 free(filename);
00803 filename = strdup(state->lircrc_root_file);
00804 if(filename==NULL)
00805 {
00806 fclose(fin);
00807 lirc_printf(state, "%s: out of memory\n",state->lirc_prog);
00808 return NULL;
00809 }
00810 }
00811 }
00812 if(full_name && fin!=NULL)
00813 {
00814 *full_name = filename;
00815 }
00816 else
00817 {
00818 free(filename);
00819 }
00820 return fin;
00821 }
00822
00823 static struct filestack_t *stack_push(const struct lirc_state *state, struct filestack_t *parent)
00824 {
00825 struct filestack_t *entry;
00826 entry = malloc(sizeof(struct filestack_t));
00827 if (entry == NULL)
00828 {
00829 lirc_printf(state, "%s: out of memory\n",state->lirc_prog);
00830 return NULL;
00831 }
00832 entry->file = NULL;
00833 entry->name = NULL;
00834 entry->line = 0;
00835 entry->parent = parent;
00836 return entry;
00837 }
00838
00839 static struct filestack_t *stack_pop(struct filestack_t *entry)
00840 {
00841 struct filestack_t *parent = NULL;
00842 if (entry)
00843 {
00844 parent = entry->parent;
00845 if (entry->name)
00846 free(entry->name);
00847 free(entry);
00848 }
00849 return parent;
00850 }
00851
00852 static void stack_free(struct filestack_t *entry)
00853 {
00854 while (entry)
00855 {
00856 entry = stack_pop(entry);
00857 }
00858 }
00859
00860 int lirc_readconfig(const struct lirc_state *state,
00861 const char *file,
00862 struct lirc_config **config,
00863 int (check)(char *s))
00864 {
00865 struct sockaddr_un addr;
00866 int sockfd = -1;
00867 char *sha_bang, *filename;
00868 const char *sha_bang2;
00869 char *command;
00870 unsigned int ret;
00871
00872 filename = NULL;
00873 sha_bang = NULL;
00874 if(lirc_readconfig_only_internal(state,file,config,check,&filename,&sha_bang)==-1)
00875 {
00876 return -1;
00877 }
00878
00879 if(sha_bang == NULL)
00880 {
00881 goto lirc_readconfig_compat;
00882 }
00883
00884
00885
00886 addr.sun_family=AF_UNIX;
00887 if(lirc_getsocketname(filename, addr.sun_path, sizeof(addr.sun_path))>sizeof(addr.sun_path))
00888 {
00889 lirc_printf(state, "%s: WARNING: file name too long\n", state->lirc_prog);
00890 goto lirc_readconfig_compat;
00891 }
00892 sockfd=socket(AF_UNIX,SOCK_STREAM,0);
00893 if(sockfd==-1)
00894 {
00895 lirc_printf(state, "%s: WARNING: could not open socket\n",state->lirc_prog);
00896 lirc_perror(state, state->lirc_prog);
00897 goto lirc_readconfig_compat;
00898 }
00899 if(connect(sockfd, (struct sockaddr *)&addr, sizeof(addr))!=-1)
00900 {
00901 if(sha_bang!=NULL) free(sha_bang);
00902 (*config)->sockfd=sockfd;
00903 free(filename);
00904
00905
00906 if(lirc_identify(state, sockfd) == LIRC_RET_SUCCESS)
00907 {
00908
00909 return 0;
00910 }
00911 close(sockfd);
00912 lirc_freeconfig(*config);
00913 return -1;
00914 }
00915 close(sockfd);
00916 sockfd = -1;
00917
00918
00919 sha_bang2=sha_bang!=NULL ? sha_bang:"lircrcd";
00920
00921 command=malloc(strlen(sha_bang2)+1+strlen(filename)+1);
00922 if(command==NULL)
00923 {
00924 goto lirc_readconfig_compat;
00925 }
00926 strcpy(command, sha_bang2);
00927 strcat(command, " ");
00928 strcat(command, filename);
00929
00930 ret = myth_system_c(command, kMSNone, 0);
00931 free(command);
00932
00933 if(ret!=EXIT_SUCCESS)
00934 {
00935 goto lirc_readconfig_compat;
00936 }
00937
00938 if(sha_bang!=NULL) { free(sha_bang); sha_bang = NULL; }
00939 free(filename); filename = NULL;
00940
00941 sockfd=socket(AF_UNIX,SOCK_STREAM,0);
00942 if(sockfd==-1)
00943 {
00944 lirc_printf(state, "%s: WARNING: could not open socket\n",state->lirc_prog);
00945 lirc_perror(state, state->lirc_prog);
00946 goto lirc_readconfig_compat;
00947 }
00948 if(connect(sockfd, (struct sockaddr *)&addr, sizeof(addr))!=-1)
00949 {
00950 if(lirc_identify(state, sockfd) == LIRC_RET_SUCCESS)
00951 {
00952 (*config)->sockfd=sockfd;
00953 return 0;
00954 }
00955 }
00956 close(sockfd);
00957 lirc_freeconfig(*config);
00958 return -1;
00959
00960 lirc_readconfig_compat:
00961
00962 if(sockfd != -1) close(sockfd);
00963 if(sha_bang!=NULL) free(sha_bang);
00964 free(filename);
00965 return 0;
00966 }
00967
00968 int lirc_readconfig_only(const struct lirc_state *state,
00969 const char *file,
00970 struct lirc_config **config,
00971 int (check)(char *s))
00972 {
00973 return lirc_readconfig_only_internal(state, file, config, check, NULL, NULL);
00974 }
00975
00976 static int lirc_readconfig_only_internal(const struct lirc_state *state,
00977 const char *file,
00978 struct lirc_config **config,
00979 int (check)(char *s),
00980 char **full_name,
00981 char **sha_bang)
00982 {
00983 char *string,*eq,*token,*token2,*token3,*strtok_state = NULL;
00984 struct filestack_t *filestack, *stack_tmp;
00985 int open_files;
00986 struct lirc_config_entry *new_entry,*first,*last;
00987 char *mode,*remote;
00988 int ret=0;
00989 int firstline=1;
00990 char *save_full_name = NULL;
00991
00992 filestack = stack_push(state, NULL);
00993 if (filestack == NULL)
00994 {
00995 return -1;
00996 }
00997 filestack->file = lirc_open(state, file, NULL, &(filestack->name));
00998 if (filestack->file == NULL)
00999 {
01000 stack_free(filestack);
01001 return -1;
01002 }
01003 filestack->line = 0;
01004 open_files = 1;
01005
01006 first=new_entry=last=NULL;
01007 mode=NULL;
01008 remote=LIRC_ALL;
01009 while (filestack)
01010 {
01011 if((ret=lirc_readline(state,&string,filestack->file))==-1 ||
01012 string==NULL)
01013 {
01014 fclose(filestack->file);
01015 if(open_files == 1 && full_name != NULL)
01016 {
01017 save_full_name = filestack->name;
01018 filestack->name = NULL;
01019 }
01020 filestack = stack_pop(filestack);
01021 open_files--;
01022 continue;
01023 }
01024
01025 if(firstline && sha_bang)
01026 {
01027 firstline = 0;
01028 if(strncmp(string, "#!", 2)==0)
01029 {
01030 *sha_bang=strdup(string+2);
01031 if(*sha_bang==NULL)
01032 {
01033 lirc_printf(state, "%s: out of memory\n",
01034 state->lirc_prog);
01035 ret=-1;
01036 free(string);
01037 break;
01038 }
01039 }
01040 }
01041 filestack->line++;
01042 eq=strchr(string,'=');
01043 if(eq==NULL)
01044 {
01045 token=strtok_r(string," \t",&strtok_state);
01046 if(token==NULL)
01047 {
01048
01049 }
01050 else if(token[0]=='#')
01051 {
01052
01053 }
01054 else if(strcasecmp(token, "include") == 0)
01055 {
01056 if (open_files >= MAX_INCLUDES)
01057 {
01058 lirc_printf(state, "%s: too many files "
01059 "included at %s:%d\n",
01060 state->lirc_prog,
01061 filestack->name,
01062 filestack->line);
01063 ret=-1;
01064 }
01065 else
01066 {
01067 token2 = strtok_r(NULL, "", &strtok_state);
01068 token2 = lirc_trim(token2);
01069 lirc_parse_include
01070 (token2, filestack->name,
01071 filestack->line);
01072 stack_tmp = stack_push(state, filestack);
01073 if (stack_tmp == NULL)
01074 {
01075 ret=-1;
01076 }
01077 else
01078 {
01079 stack_tmp->file = lirc_open(state, token2, filestack->name, &(stack_tmp->name));
01080 stack_tmp->line = 0;
01081 if (stack_tmp->file)
01082 {
01083 open_files++;
01084 filestack = stack_tmp;
01085 }
01086 else
01087 {
01088 stack_pop(stack_tmp);
01089 ret=-1;
01090 }
01091 }
01092 }
01093 }
01094 else
01095 {
01096 token2=strtok_r(NULL," \t",&strtok_state);
01097 if(token2!=NULL &&
01098 (token3=strtok_r(NULL," \t",&strtok_state))!=NULL)
01099 {
01100 lirc_printf(state, "%s: unexpected token in line %s:%d\n",
01101 state->lirc_prog,filestack->name,filestack->line);
01102 }
01103 else
01104 {
01105 ret=lirc_mode(state, token,token2,&mode,
01106 &new_entry,&first,&last,
01107 check,
01108 filestack->name,
01109 filestack->line);
01110 if(ret==0)
01111 {
01112 if(remote!=LIRC_ALL)
01113 free(remote);
01114 remote=LIRC_ALL;
01115 }
01116 else
01117 {
01118 if(mode!=NULL)
01119 {
01120 free(mode);
01121 mode=NULL;
01122 }
01123 if(new_entry!=NULL)
01124 {
01125 lirc_freeconfigentries
01126 (new_entry);
01127 new_entry=NULL;
01128 }
01129 }
01130 }
01131 }
01132 }
01133 else
01134 {
01135 eq[0]=0;
01136 token=lirc_trim(string);
01137 token2=lirc_trim(eq+1);
01138 if(token[0]=='#')
01139 {
01140
01141 }
01142 else if(new_entry==NULL)
01143 {
01144 lirc_printf(state, "%s: bad file format, %s:%d\n",
01145 state->lirc_prog,filestack->name,filestack->line);
01146 ret=-1;
01147 }
01148 else
01149 {
01150 token2=strdup(token2);
01151 if(token2==NULL)
01152 {
01153 lirc_printf(state, "%s: out of memory\n",
01154 state->lirc_prog);
01155 ret=-1;
01156 }
01157 else if(strcasecmp(token,"prog")==0)
01158 {
01159 if(new_entry->prog!=NULL) free(new_entry->prog);
01160 new_entry->prog=token2;
01161 }
01162 else if(strcasecmp(token,"remote")==0)
01163 {
01164 if(remote!=LIRC_ALL)
01165 free(remote);
01166
01167 if(strcasecmp("*",token2)==0)
01168 {
01169 remote=LIRC_ALL;
01170 free(token2);
01171 }
01172 else
01173 {
01174 remote=token2;
01175 }
01176 }
01177 else if(strcasecmp(token,"button")==0)
01178 {
01179 struct lirc_code *code;
01180
01181 code=(struct lirc_code *)
01182 malloc(sizeof(struct lirc_code));
01183 if(code==NULL)
01184 {
01185 free(token2);
01186 lirc_printf(state, "%s: out of "
01187 "memory\n",
01188 state->lirc_prog);
01189 ret=-1;
01190 }
01191 else
01192 {
01193 code->remote=remote;
01194 if(strcasecmp("*",token2)==0)
01195 {
01196 code->button=LIRC_ALL;
01197 free(token2);
01198 }
01199 else
01200 {
01201 code->button=token2;
01202 }
01203 code->next=NULL;
01204
01205 if(new_entry->code==NULL)
01206 {
01207 new_entry->code=code;
01208 }
01209 else
01210 {
01211 new_entry->next_code->next
01212 =code;
01213 }
01214 new_entry->next_code=code;
01215 if(remote!=LIRC_ALL)
01216 {
01217 remote=strdup(remote);
01218 if(remote==NULL)
01219 {
01220 lirc_printf(state, "%s: out of memory\n",state->lirc_prog);
01221 ret=-1;
01222 }
01223 }
01224 }
01225 }
01226 else if(strcasecmp(token,"delay")==0)
01227 {
01228 char *end;
01229
01230 errno=ERANGE+1;
01231 new_entry->rep_delay=strtoul(token2,&end,0);
01232 if((new_entry->rep_delay==UINT_MAX
01233 && errno==ERANGE)
01234 || end[0]!=0
01235 || strlen(token2)==0)
01236 {
01237 lirc_printf(state, "%s: \"%s\" not"
01238 " a valid number for "
01239 "delay\n",state->lirc_prog,
01240 token2);
01241 }
01242 free(token2);
01243 }
01244 else if(strcasecmp(token,"repeat")==0)
01245 {
01246 char *end;
01247
01248 errno=ERANGE+1;
01249 new_entry->rep=strtoul(token2,&end,0);
01250 if((new_entry->rep==UINT_MAX
01251 && errno==ERANGE)
01252 || end[0]!=0
01253 || strlen(token2)==0)
01254 {
01255 lirc_printf(state, "%s: \"%s\" not"
01256 " a valid number for "
01257 "repeat\n",state->lirc_prog,
01258 token2);
01259 }
01260 free(token2);
01261 }
01262 else if(strcasecmp(token,"config")==0)
01263 {
01264 struct lirc_list *new_list;
01265
01266 new_list=(struct lirc_list *)
01267 malloc(sizeof(struct lirc_list));
01268 if(new_list==NULL)
01269 {
01270 free(token2);
01271 lirc_printf(state, "%s: out of "
01272 "memory\n",
01273 state->lirc_prog);
01274 ret=-1;
01275 }
01276 else
01277 {
01278 lirc_parse_string(state,token2,filestack->name,filestack->line);
01279 new_list->string=token2;
01280 new_list->next=NULL;
01281 if(new_entry->config==NULL)
01282 {
01283 new_entry->config=new_list;
01284 }
01285 else
01286 {
01287 new_entry->next_config->next
01288 =new_list;
01289 }
01290 new_entry->next_config=new_list;
01291 }
01292 }
01293 else if(strcasecmp(token,"mode")==0)
01294 {
01295 if(new_entry->change_mode!=NULL) free(new_entry->change_mode);
01296 new_entry->change_mode=token2;
01297 }
01298 else if(strcasecmp(token,"flags")==0)
01299 {
01300 new_entry->flags=lirc_flags(state, token2);
01301 free(token2);
01302 }
01303 else
01304 {
01305 free(token2);
01306 lirc_printf(state, "%s: unknown token \"%s\" in %s:%d ignored\n",
01307 state->lirc_prog,token,filestack->name,filestack->line);
01308 }
01309 }
01310 }
01311 free(string);
01312 if(ret==-1) break;
01313 }
01314 if(remote!=LIRC_ALL)
01315 free(remote);
01316 if(new_entry!=NULL)
01317 {
01318 if(ret==0)
01319 {
01320 ret=lirc_mode(state, "end",NULL,&mode,&new_entry,
01321 &first,&last,check,"",0);
01322 lirc_printf(state, "%s: warning: end token missing at end "
01323 "of file\n",state->lirc_prog);
01324 }
01325 else
01326 {
01327 lirc_freeconfigentries(new_entry);
01328 new_entry=NULL;
01329 }
01330 }
01331 if(mode!=NULL)
01332 {
01333 if(ret==0)
01334 {
01335 lirc_printf(state, "%s: warning: no end token found for mode "
01336 "\"%s\"\n",state->lirc_prog,mode);
01337 }
01338 free(mode);
01339 }
01340 if(ret==0)
01341 {
01342 char *startupmode;
01343
01344 *config=(struct lirc_config *)
01345 malloc(sizeof(struct lirc_config));
01346 if(*config==NULL)
01347 {
01348 lirc_printf(state, "%s: out of memory\n",state->lirc_prog);
01349 lirc_freeconfigentries(first);
01350 return(-1);
01351 }
01352 (*config)->first=first;
01353 (*config)->next=first;
01354 startupmode = lirc_startupmode(state, (*config)->first);
01355 (*config)->current_mode=startupmode ? strdup(startupmode):NULL;
01356 (*config)->sockfd=-1;
01357 if(full_name != NULL)
01358 {
01359 *full_name = save_full_name;
01360 save_full_name = NULL;
01361 }
01362 }
01363 else
01364 {
01365 *config=NULL;
01366 lirc_freeconfigentries(first);
01367 if(sha_bang && *sha_bang!=NULL)
01368 {
01369 free(*sha_bang);
01370 *sha_bang=NULL;
01371 }
01372 }
01373 if(filestack)
01374 {
01375 stack_free(filestack);
01376 }
01377 if(save_full_name)
01378 {
01379 free(save_full_name);
01380 }
01381 return(ret);
01382 }
01383
01384 static char *lirc_startupmode(const struct lirc_state *state, struct lirc_config_entry *first)
01385 {
01386 struct lirc_config_entry *scan;
01387 char *startupmode;
01388
01389 startupmode=NULL;
01390 scan=first;
01391
01392 while(scan!=NULL)
01393 {
01394 if(scan->flags&startup_mode) {
01395 if(scan->change_mode!=NULL) {
01396 startupmode=scan->change_mode;
01397
01398 scan->change_mode=NULL;
01399 break;
01400 }
01401 else {
01402 lirc_printf(state, "%s: startup_mode flags requires 'mode ='\n",
01403 state->lirc_prog);
01404 }
01405 }
01406 scan=scan->next;
01407 }
01408
01409
01410 if(startupmode==NULL) {
01411 scan=first;
01412 while(scan!=NULL)
01413 {
01414 if(scan->mode!=NULL && strcasecmp(state->lirc_prog,scan->mode)==0)
01415 {
01416 startupmode=state->lirc_prog;
01417 break;
01418 }
01419 scan=scan->next;
01420 }
01421 }
01422
01423 if(startupmode==NULL) return(NULL);
01424 scan=first;
01425 while(scan!=NULL)
01426 {
01427 if(scan->change_mode!=NULL && scan->flags&once &&
01428 strcasecmp(startupmode,scan->change_mode)==0)
01429 {
01430 scan->flags|=ecno;
01431 }
01432 scan=scan->next;
01433 }
01434 return(startupmode);
01435 }
01436
01437 void lirc_freeconfig(struct lirc_config *config)
01438 {
01439 if(config!=NULL)
01440 {
01441 if(config->sockfd!=-1)
01442 {
01443 (void) close(config->sockfd);
01444 config->sockfd=-1;
01445 }
01446 lirc_freeconfigentries(config->first);
01447 free(config->current_mode);
01448 free(config);
01449 }
01450 }
01451
01452 static void lirc_freeconfigentries(struct lirc_config_entry *first)
01453 {
01454 struct lirc_config_entry *c,*config_temp;
01455 struct lirc_list *list,*list_temp;
01456 struct lirc_code *code,*code_temp;
01457
01458 c=first;
01459 while(c!=NULL)
01460 {
01461 if(c->prog) free(c->prog);
01462 if(c->change_mode) free(c->change_mode);
01463 if(c->mode) free(c->mode);
01464
01465 code=c->code;
01466 while(code!=NULL)
01467 {
01468 if(code->remote!=NULL && code->remote!=LIRC_ALL)
01469 free(code->remote);
01470 if(code->button!=NULL && code->button!=LIRC_ALL)
01471 free(code->button);
01472 code_temp=code->next;
01473 free(code);
01474 code=code_temp;
01475 }
01476
01477 list=c->config;
01478 while(list!=NULL)
01479 {
01480 if(list->string) free(list->string);
01481 list_temp=list->next;
01482 free(list);
01483 list=list_temp;
01484 }
01485 config_temp=c->next;
01486 free(c);
01487 c=config_temp;
01488 }
01489 }
01490
01491 static void lirc_clearmode(struct lirc_config *config)
01492 {
01493 struct lirc_config_entry *scan;
01494
01495 if(config->current_mode==NULL)
01496 {
01497 return;
01498 }
01499 scan=config->first;
01500 while(scan!=NULL)
01501 {
01502 if(scan->change_mode!=NULL)
01503 {
01504 if(strcasecmp(scan->change_mode,config->current_mode)==0)
01505 {
01506 scan->flags&=~ecno;
01507 }
01508 }
01509 scan=scan->next;
01510 }
01511 free(config->current_mode);
01512 config->current_mode=NULL;
01513 }
01514
01515 static char *lirc_execute(const struct lirc_state *state,
01516 struct lirc_config *config,
01517 struct lirc_config_entry *scan)
01518 {
01519 char *s;
01520 int do_once=1;
01521
01522 if(scan->flags&mode)
01523 {
01524 lirc_clearmode(config);
01525 }
01526 if(scan->change_mode!=NULL)
01527 {
01528 free(config->current_mode);
01529 config->current_mode=strdup(scan->change_mode);
01530 if(scan->flags&once)
01531 {
01532 if(scan->flags&ecno)
01533 {
01534 do_once=0;
01535 }
01536 else
01537 {
01538 scan->flags|=ecno;
01539 }
01540 }
01541 }
01542 if(scan->next_config!=NULL &&
01543 scan->prog!=NULL &&
01544 (state->lirc_prog == NULL || strcasecmp(scan->prog,state->lirc_prog)==0) &&
01545 do_once==1)
01546 {
01547 s=scan->next_config->string;
01548 scan->next_config=scan->next_config->next;
01549 if(scan->next_config==NULL)
01550 scan->next_config=scan->config;
01551 return(s);
01552 }
01553 return(NULL);
01554 }
01555
01556 static int lirc_iscode(struct lirc_config_entry *scan, char *remote,
01557 char *button,int rep)
01558 {
01559 struct lirc_code *codes;
01560
01561
01562 if(scan->code==NULL)
01563 {
01564 return rep==0 ||
01565 (scan->rep>0 && rep>scan->rep_delay &&
01566 ((rep-scan->rep_delay-1)%scan->rep)==0);
01567 }
01568
01569
01570 if(scan->next_code->remote==LIRC_ALL ||
01571 strcasecmp(scan->next_code->remote,remote)==0)
01572 {
01573 if(scan->next_code->button==LIRC_ALL ||
01574 strcasecmp(scan->next_code->button,button)==0)
01575 {
01576 int iscode=0;
01577
01578 if(scan->code->next==NULL || rep==0)
01579 {
01580 scan->next_code=scan->next_code->next;
01581 if(scan->code->next != NULL)
01582 {
01583 iscode=1;
01584 }
01585 }
01586
01587 if(scan->next_code==NULL)
01588 {
01589 scan->next_code=scan->code;
01590 if(scan->code->next!=NULL || rep==0 ||
01591 (scan->rep>0 && rep>scan->rep_delay &&
01592 ((rep-scan->rep_delay-1)%scan->rep)==0))
01593 iscode=2;
01594 }
01595 return iscode;
01596 }
01597 }
01598
01599 if(rep!=0) return(0);
01600
01601
01602 if(scan->flags & toggle_reset)
01603 {
01604 scan->next_config = scan->config;
01605 }
01606
01607 codes=scan->code;
01608 if(codes==scan->next_code) return(0);
01609 codes=codes->next;
01610
01611 while(codes!=scan->next_code->next)
01612 {
01613 struct lirc_code *prev,*next;
01614 int flag=1;
01615
01616 prev=scan->code;
01617 next=codes;
01618 while(next!=scan->next_code)
01619 {
01620 if(prev->remote==LIRC_ALL ||
01621 strcasecmp(prev->remote,next->remote)==0)
01622 {
01623 if(prev->button==LIRC_ALL ||
01624 strcasecmp(prev->button,next->button)==0)
01625 {
01626 prev=prev->next;
01627 next=next->next;
01628 }
01629 else
01630 {
01631 flag=0;break;
01632 }
01633 }
01634 else
01635 {
01636 flag=0;break;
01637 }
01638 }
01639 if(flag==1)
01640 {
01641 if(prev->remote==LIRC_ALL ||
01642 strcasecmp(prev->remote,remote)==0)
01643 {
01644 if(prev->button==LIRC_ALL ||
01645 strcasecmp(prev->button,button)==0)
01646 {
01647 if(rep==0)
01648 {
01649 scan->next_code=prev->next;
01650 return(0);
01651 }
01652 }
01653 }
01654 }
01655 codes=codes->next;
01656 }
01657 scan->next_code=scan->code;
01658 return(0);
01659 }
01660
01661 #if 0
01662 char *lirc_ir2char(const struct lirc_state *state,struct lirc_config *config,char *code)
01663 {
01664 static int warning=1;
01665 char *string;
01666
01667 if(warning)
01668 {
01669 fprintf(stderr,"%s: warning: lirc_ir2char() is obsolete\n",
01670 state->lirc_prog);
01671 warning=0;
01672 }
01673 if(lirc_code2char(state,config,code,&string)==-1) return(NULL);
01674 return(string);
01675 }
01676 #endif
01677
01678 int lirc_code2char(const struct lirc_state *state, struct lirc_config *config,char *code,char **string)
01679 {
01680 if(config->sockfd!=-1)
01681 {
01682 char command[10+strlen(code)+1+1];
01683 static char buf[LIRC_PACKET_SIZE];
01684 size_t buf_len = LIRC_PACKET_SIZE;
01685 int success;
01686 int ret;
01687
01688 sprintf(command, "CODE %s\n", code);
01689
01690 ret = lirc_send_command(state, config->sockfd, command,
01691 buf, &buf_len, &success);
01692 if(success == LIRC_RET_SUCCESS)
01693 {
01694 if(ret > 0)
01695 {
01696 *string = buf;
01697 }
01698 else
01699 {
01700 *string = NULL;
01701 }
01702 return LIRC_RET_SUCCESS;
01703 }
01704 return LIRC_RET_ERROR;
01705 }
01706 return lirc_code2char_internal(state, config, code, string, NULL);
01707 }
01708
01709 int lirc_code2charprog(struct lirc_state *state,struct lirc_config *config,char *code,char **string,
01710 char **prog)
01711 {
01712 char *backup;
01713 int ret;
01714
01715 backup = state->lirc_prog;
01716 state->lirc_prog = NULL;
01717
01718 ret = lirc_code2char_internal(state,config, code, string, prog);
01719
01720 state->lirc_prog = backup;
01721 return ret;
01722 }
01723
01724 static int lirc_code2char_internal(const struct lirc_state *state,
01725 struct lirc_config *config,char *code,
01726 char **string, char **prog)
01727 {
01728 int rep;
01729 char *backup, *strtok_state = NULL;
01730 char *remote,*button;
01731 char *s=NULL;
01732 struct lirc_config_entry *scan;
01733 int exec_level;
01734 int quit_happened;
01735
01736 *string=NULL;
01737 if(sscanf(code,"%*20x %20x %*5000s %*5000s\n",&rep)==1)
01738 {
01739 backup=strdup(code);
01740 if(backup==NULL) return(-1);
01741
01742 strtok_r(backup," ",&strtok_state);
01743 strtok_r(NULL," ",&strtok_state);
01744 button=strtok_r(NULL," ",&strtok_state);
01745 remote=strtok_r(NULL,"\n",&strtok_state);
01746
01747 if(button==NULL || remote==NULL)
01748 {
01749 free(backup);
01750 return(0);
01751 }
01752
01753 scan=config->next;
01754 quit_happened=0;
01755 while(scan!=NULL)
01756 {
01757 exec_level = lirc_iscode(scan,remote,button,rep);
01758 if(exec_level > 0 &&
01759 (scan->mode==NULL ||
01760 (scan->mode!=NULL &&
01761 config->current_mode!=NULL &&
01762 strcasecmp(scan->mode,config->current_mode)==0)) &&
01763 quit_happened==0
01764 )
01765 {
01766 if(exec_level > 1)
01767 {
01768 s=lirc_execute(state,config,scan);
01769 if(s != NULL && prog != NULL)
01770 {
01771 *prog = scan->prog;
01772 }
01773 }
01774 else
01775 {
01776 s = NULL;
01777 }
01778 if(scan->flags&quit)
01779 {
01780 quit_happened=1;
01781 config->next=NULL;
01782 scan=scan->next;
01783 continue;
01784 }
01785 else if(s!=NULL)
01786 {
01787 config->next=scan->next;
01788 break;
01789 }
01790 }
01791 scan=scan->next;
01792 }
01793 free(backup);
01794 if(s!=NULL)
01795 {
01796 *string=s;
01797 return(0);
01798 }
01799 }
01800 config->next=config->first;
01801 return(0);
01802 }
01803
01804 #define PACKET_SIZE 100
01805
01806 #if 0
01807 char *lirc_nextir(struct lirc_state *state)
01808 {
01809 static int warning=1;
01810 char *code;
01811 int ret;
01812
01813 if(warning)
01814 {
01815 fprintf(stderr,"%s: warning: lirc_nextir() is obsolete\n",
01816 state->lirc_prog);
01817 warning=0;
01818 }
01819 ret=lirc_nextcode(state, &code);
01820 if(ret==-1) return(NULL);
01821 return(code);
01822 }
01823 #endif
01824
01825 int lirc_nextcode(struct lirc_state *state, char **code)
01826 {
01827 static int packet_size=PACKET_SIZE;
01828 static int end_len=0;
01829 ssize_t len=0;
01830 char *end,c;
01831
01832 *code=NULL;
01833 if(state->lirc_buffer==NULL)
01834 {
01835 state->lirc_buffer=(char *) malloc(packet_size+1);
01836 if(state->lirc_buffer==NULL)
01837 {
01838 lirc_printf(state, "%s: out of memory\n",state->lirc_prog);
01839 return(-1);
01840 }
01841 state->lirc_buffer[0]=0;
01842 }
01843 while((end=strchr(state->lirc_buffer,'\n'))==NULL)
01844 {
01845 if(end_len>=packet_size)
01846 {
01847 char *new_buffer;
01848
01849 packet_size+=PACKET_SIZE;
01850 new_buffer=(char *) realloc(state->lirc_buffer,packet_size+1);
01851 if(new_buffer==NULL)
01852 {
01853 return(-1);
01854 }
01855 state->lirc_buffer=new_buffer;
01856 }
01857 len=read(state->lirc_lircd,state->lirc_buffer+end_len,packet_size-end_len);
01858 if(len<=0)
01859 {
01860 if(len==-1 && errno==EAGAIN) return(0);
01861 else return(-1);
01862 }
01863 end_len+=len;
01864 state->lirc_buffer[end_len]=0;
01865
01866 if((end=strchr(state->lirc_buffer,'\n'))==NULL)
01867 {
01868 return(0);
01869 }
01870 }
01871
01872
01873 end++;
01874 end_len=strlen(end);
01875 c=end[0];
01876 end[0]=0;
01877 *code=strdup(state->lirc_buffer);
01878 end[0]=c;
01879 memmove(state->lirc_buffer,end,end_len+1);
01880 if(*code==NULL) return(-1);
01881 return(0);
01882 }
01883
01884 size_t lirc_getsocketname(const char *filename, char *buf, size_t size)
01885 {
01886 if(strlen(filename)+2<=size)
01887 {
01888 strcpy(buf, filename);
01889 strcat(buf, "d");
01890 }
01891 return strlen(filename)+2;
01892 }
01893
01894 const char *lirc_getmode(const struct lirc_state *state, struct lirc_config *config)
01895 {
01896 if(config->sockfd!=-1)
01897 {
01898 static char buf[LIRC_PACKET_SIZE];
01899 size_t buf_len = LIRC_PACKET_SIZE;
01900 int success;
01901 int ret;
01902
01903 ret = lirc_send_command(state, config->sockfd, "GETMODE\n",
01904 buf, &buf_len, &success);
01905 if(success == LIRC_RET_SUCCESS)
01906 {
01907 if(ret > 0)
01908 {
01909 return buf;
01910 }
01911 else
01912 {
01913 return NULL;
01914 }
01915 }
01916 return NULL;
01917 }
01918 return config->current_mode;
01919 }
01920
01921 const char *lirc_setmode(const struct lirc_state *state, struct lirc_config *config, const char *mode)
01922 {
01923 if(config->sockfd!=-1)
01924 {
01925 static char buf[LIRC_PACKET_SIZE];
01926 size_t buf_len = LIRC_PACKET_SIZE;
01927 int success;
01928 int ret;
01929 char cmd[LIRC_PACKET_SIZE];
01930 if(snprintf(cmd, LIRC_PACKET_SIZE, "SETMODE%s%s\n",
01931 mode ? " ":"",
01932 mode ? mode:"")
01933 >= LIRC_PACKET_SIZE)
01934 {
01935 return NULL;
01936 }
01937
01938 ret = lirc_send_command(state, config->sockfd, cmd,
01939 buf, &buf_len, &success);
01940 if(success == LIRC_RET_SUCCESS)
01941 {
01942 if(ret > 0)
01943 {
01944 return buf;
01945 }
01946 else
01947 {
01948 return NULL;
01949 }
01950 }
01951 return NULL;
01952 }
01953
01954 free(config->current_mode);
01955 config->current_mode = mode ? strdup(mode) : NULL;
01956 return config->current_mode;
01957 }
01958
01959 static const char *lirc_read_string(const struct lirc_state *state, int fd)
01960 {
01961 static char buffer[LIRC_PACKET_SIZE+1]="";
01962 char *end;
01963 static int head=0, tail=0;
01964 int ret;
01965 ssize_t n;
01966 fd_set fds;
01967 struct timeval tv;
01968
01969 if(head>0)
01970 {
01971 memmove(buffer,buffer+head,tail-head+1);
01972 tail-=head;
01973 head=0;
01974 end=strchr(buffer,'\n');
01975 }
01976 else
01977 {
01978 end=NULL;
01979 }
01980 if(strlen(buffer)!=tail)
01981 {
01982 lirc_printf(state, "%s: protocol error\n", state->lirc_prog);
01983 goto lirc_read_string_error;
01984 }
01985
01986 while(end==NULL)
01987 {
01988 if(LIRC_PACKET_SIZE<=tail)
01989 {
01990 lirc_printf(state, "%s: bad packet\n", state->lirc_prog);
01991 goto lirc_read_string_error;
01992 }
01993
01994 FD_ZERO(&fds);
01995 FD_SET(fd,&fds);
01996 tv.tv_sec=LIRC_TIMEOUT;
01997 tv.tv_usec=0;
01998 do
01999 {
02000 ret=select(fd+1,&fds,NULL,NULL,&tv);
02001 }
02002 while(ret==-1 && errno==EINTR);
02003 if(ret==-1)
02004 {
02005 lirc_printf(state, "%s: select() failed\n", state->lirc_prog);
02006 lirc_perror(state, state->lirc_prog);
02007 goto lirc_read_string_error;
02008 }
02009 else if(ret==0)
02010 {
02011 lirc_printf(state, "%s: timeout\n", state->lirc_prog);
02012 goto lirc_read_string_error;
02013 }
02014
02015 n=read(fd, buffer+tail, LIRC_PACKET_SIZE-tail);
02016 if(n<=0)
02017 {
02018 lirc_printf(state, "%s: read() failed\n", state->lirc_prog);
02019 lirc_perror(state, state->lirc_prog);
02020 goto lirc_read_string_error;
02021 }
02022 buffer[tail+n]=0;
02023 tail+=n;
02024 end=strchr(buffer,'\n');
02025 }
02026
02027 end[0]=0;
02028 head=strlen(buffer)+1;
02029 return(buffer);
02030
02031 lirc_read_string_error:
02032 head=tail=0;
02033 buffer[0]=0;
02034 return(NULL);
02035 }
02036
02037 int lirc_send_command(const struct lirc_state *lstate, int sockfd, const char *command, char *buf, size_t *buf_len, int *ret_status)
02038 {
02039 int done,todo;
02040 const char *string,*data;
02041 char *endptr;
02042 enum packet_state state;
02043 int status,n;
02044 unsigned long data_n=0;
02045 size_t written=0, max=0, len;
02046
02047 if(buf_len!=NULL)
02048 {
02049 max=*buf_len;
02050 }
02051 todo=strlen(command);
02052 data=command;
02053 while(todo>0)
02054 {
02055 done=write(sockfd,(const void *) data,todo);
02056 if(done<0)
02057 {
02058 lirc_printf(lstate, "%s: could not send packet\n",
02059 lstate->lirc_prog);
02060 lirc_perror(lstate, lstate->lirc_prog);
02061 return(-1);
02062 }
02063 data+=done;
02064 todo-=done;
02065 }
02066
02067
02068 status=LIRC_RET_SUCCESS;
02069 state=P_BEGIN;
02070 n=0;
02071 while(1)
02072 {
02073 string=lirc_read_string(lstate, sockfd);
02074 if(string==NULL) return(-1);
02075 switch(state)
02076 {
02077 case P_BEGIN:
02078 if(strcasecmp(string,"BEGIN")!=0)
02079 {
02080 continue;
02081 }
02082 state=P_MESSAGE;
02083 break;
02084 case P_MESSAGE:
02085 if(strncasecmp(string,command,strlen(string))!=0 ||
02086 strlen(string)+1!=strlen(command))
02087 {
02088 state=P_BEGIN;
02089 continue;
02090 }
02091 state=P_STATUS;
02092 break;
02093 case P_STATUS:
02094 if(strcasecmp(string,"SUCCESS")==0)
02095 {
02096 status=LIRC_RET_SUCCESS;
02097 }
02098 else if(strcasecmp(string,"END")==0)
02099 {
02100 status=LIRC_RET_SUCCESS;
02101 goto good_packet;
02102 }
02103 else if(strcasecmp(string,"ERROR")==0)
02104 {
02105 lirc_printf(lstate, "%s: command failed: %s",
02106 lstate->lirc_prog, command);
02107 status=LIRC_RET_ERROR;
02108 }
02109 else
02110 {
02111 goto bad_packet;
02112 }
02113 state=P_DATA;
02114 break;
02115 case P_DATA:
02116 if(strcasecmp(string,"END")==0)
02117 {
02118 goto good_packet;
02119 }
02120 else if(strcasecmp(string,"DATA")==0)
02121 {
02122 state=P_N;
02123 break;
02124 }
02125 goto bad_packet;
02126 case P_N:
02127 errno=0;
02128 data_n=strtoul(string,&endptr,0);
02129 if(!*string || *endptr)
02130 {
02131 goto bad_packet;
02132 }
02133 if(data_n==0)
02134 {
02135 state=P_END;
02136 }
02137 else
02138 {
02139 state=P_DATA_N;
02140 }
02141 break;
02142 case P_DATA_N:
02143 len=strlen(string);
02144 if(buf!=NULL && written+len+1<max)
02145 {
02146 memcpy(buf+written, string, len+1);
02147 }
02148 written+=len+1;
02149 n++;
02150 if(n==data_n) state=P_END;
02151 break;
02152 case P_END:
02153 if(strcasecmp(string,"END")==0)
02154 {
02155 goto good_packet;
02156 }
02157 goto bad_packet;
02158 break;
02159 }
02160 }
02161
02162
02163
02164 bad_packet:
02165 lirc_printf(lstate, "%s: bad return packet\n", lstate->lirc_prog);
02166 return(-1);
02167
02168 good_packet:
02169 if(ret_status!=NULL)
02170 {
02171 *ret_status=status;
02172 }
02173 if(buf_len!=NULL)
02174 {
02175 *buf_len=written;
02176 }
02177 return (int) data_n;
02178 }
02179
02180 int lirc_identify(const struct lirc_state *state, int sockfd)
02181 {
02182 char command[10+strlen(state->lirc_prog)+1+1];
02183 int success;
02184
02185 sprintf(command, "IDENT %s\n", state->lirc_prog);
02186
02187 (void) lirc_send_command(state, sockfd, command, NULL, NULL, &success);
02188 return success;
02189 }