MythTV  0.26-pre
lirc_client.c
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends