|
MythTV
0.26-pre
|
00001 /* NOTE: Extracted from LIRC release 0.8.4a -- dtk */ 00002 /* Updated to LIRC release 0.8.6 */ 00003 /* Modified to use myth_system -- Gavin Hurlbut */ 00004 00005 /**************************************************************************** 00006 ** lirc_client.c *********************************************************** 00007 **************************************************************************** 00008 * 00009 * lirc_client - common routines for lircd clients 00010 * 00011 * Copyright (C) 1998 Trent Piepho <xyzzy@u.washington.edu> 00012 * Copyright (C) 1998 Christoph Bartelmus <lirc@bartelmus.de> 00013 * 00014 * System wide LIRCRC support by Michal Svec <rebel@atrey.karlin.mff.cuni.cz> 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 /* internal defines */ 00039 #define MAX_INCLUDES 10 00040 #define LIRC_READ 255 00041 #define LIRC_PACKET_SIZE 255 00042 /* three seconds */ 00043 #define LIRC_TIMEOUT 3 00044 00045 /* internal data structures */ 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 /* internal functions */ 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 lircrc_config relies on this function, hence don't make it static 00082 but it's not part of the official interface, so there's no guarantee 00083 that it will stay available in the future 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 /* connect to lircd */ 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 /* parse standard C escape sequences + \@,\A-\Z is ^@,^A-^Z */ 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': /* this should become ^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); /* terminating 0 is copied */ 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 /* absulute path or root */ 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 /* get path from parent filename */ 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 /* connect to lircrcd */ 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 /* tell daemon state->lirc_prog */ 00906 if(lirc_identify(state, sockfd) == LIRC_RET_SUCCESS) 00907 { 00908 /* we're connected */ 00909 return 0; 00910 } 00911 close(sockfd); 00912 lirc_freeconfig(*config); 00913 return -1; 00914 } 00915 close(sockfd); 00916 sockfd = -1; 00917 00918 /* launch lircrcd */ 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 /* compat fallback */ 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 /* check for sha-bang */ 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 /* ignore empty line */ 01049 } 01050 else if(token[0]=='#') 01051 { 01052 /* ignore comment */ 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 /* ignore comment */ 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 /* Set a startup mode based on flags=startup_mode */ 01392 while(scan!=NULL) 01393 { 01394 if(scan->flags&startup_mode) { 01395 if(scan->change_mode!=NULL) { 01396 startupmode=scan->change_mode; 01397 /* Remove the startup mode or it confuses lirc mode system */ 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 /* Set a default mode if we find a mode = client app name */ 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 /* no remote/button specified */ 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 /* remote/button match? */ 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 /* button sequence? */ 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 /* sequence completed? */ 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 /* handle toggle_reset */ 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 /* rebase code sequence */ 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 /* return if next code not yet available completely */ 01866 if((end=strchr(state->lirc_buffer,'\n'))==NULL) 01867 { 01868 return(0); 01869 } 01870 } 01871 /* copy first line to buffer (code) and move remaining chars to 01872 state->lirc_buffers start */ 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 /* get response */ 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 /* never reached */ 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 }
1.7.6.1