diff -Naurp lirc-0.8.3.orig/daemons/config_file.c lirc-0.8.3/daemons/config_file.c --- lirc-0.8.3.orig/daemons/config_file.c 2007-07-29 14:20:06.000000000 -0400 +++ lirc-0.8.3/daemons/config_file.c 2008-05-12 18:02:32.000000000 -0400 @@ -1,4 +1,4 @@ -/* $Id: config_file.c,v 5.27 2007/07/29 18:20:06 lirc Exp $ */ +/* $Id: config_file.c,v 5.28 2008/05/09 18:40:59 lirc Exp $ */ /**************************************************************************** ** config_file.c *********************************************************** @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -32,9 +33,14 @@ #include "config_file.h" #define LINE_LEN 1024 +#define MAX_INCLUDES 10 -int line; -int parse_error; +const char *whitespace = " \t"; + +static int line; +static int parse_error; + +static struct ir_remote * read_config_recursive(FILE *f, const char *name, int depth); void **init_void_array(struct void_array *ar,size_t chunk_size, size_t item_size) { @@ -643,7 +649,84 @@ struct ir_remote *sort_by_bit_count(stru return top; } -struct ir_remote * read_config(FILE *f) +static const char *lirc_parse_include(char *s) +{ + char *last; + size_t len; + + len=strlen(s); + if(len<2) + { + return NULL; + } + last = s+len-1; + while(last > s && strchr(whitespace, *last) != NULL) + { + last--; + } + if(last <= s) + { + return NULL; + } + if(*s!='"' && *s!='<') + { + return NULL; + } + if(*s=='"' && *last!='"') + { + return NULL; + } + else if(*s=='<' && *last!='>') + { + return NULL; + } + *last = 0; + memmove(s, s+1, len-2+1); /* terminating 0 is copied, and + maybe more, but we don't care */ + return s; +} + +static const char *lirc_parse_relative(char *dst, size_t dst_size, + const char *child, const char *current) +{ + char *dir; + size_t dirlen; + + if (!current) + return child; + + /* Not a relative path */ + if (*child == '/') + return child; + + if(strlen(current) >= dst_size) + { + return NULL; + } + strcpy(dst, current); + dir = dirname(dst); + dirlen = strlen(dir); + if(dir != dst) + { + memmove(dst, dir, dirlen + 1); + } + + if(dirlen + 1 + strlen(child) + 1 > dst_size) + { + return NULL; + } + strcat(dst, "/"); + strcat(dst, child); + + return dst; +} + +struct ir_remote * read_config(FILE *f, const char *name) +{ + return read_config_recursive(f, name, 0); +} + +static struct ir_remote * read_config_recursive(FILE *f, const char *name, int depth) { char buf[LINE_LEN+1], *key, *val, *val2; int len,argc; @@ -656,6 +739,7 @@ struct ir_remote * read_config(FILE *f) line=0; parse_error=0; + LOGPRINTF(2, "parsing '%s'", name); while(fgets(buf,LINE_LEN,f)!=NULL) { @@ -683,14 +767,74 @@ struct ir_remote * read_config(FILE *f) if(buf[0]=='#'){ continue; } - key=strtok(buf," \t"); + key=strtok(buf, whitespace); /* ignore empty lines */ if(key==NULL) continue; - val=strtok(NULL, " \t"); + val=strtok(NULL, whitespace); if(val!=NULL){ - val2=strtok(NULL, " \t"); + val2=strtok(NULL, whitespace); LOGPRINTF(3,"\"%s\" \"%s\"",key,val); - if (strcasecmp("begin",key)==0){ + if (strcasecmp("include",key)==0){ + FILE* childFile; + const char *childName; + const char *fullPath; + char result[FILENAME_MAX+1]; + + + if (depth > MAX_INCLUDES) { + logprintf(LOG_ERR,"error opening child file defined at %s:%d",name,line); + logprintf(LOG_ERR,"too many files included"); + parse_error=-1; + break; + } + + childName = lirc_parse_include(val); + if (!childName){ + logprintf(LOG_ERR,"error parsing child file value defined at line %d:",line); + logprintf(LOG_ERR,"invalid quoting"); + parse_error=-1; + break; + } + + fullPath = lirc_parse_relative(result, sizeof(result), childName, name); + if (!fullPath) { + logprintf(LOG_ERR,"error composing relative file path defined at line %d:",line); + logprintf(LOG_ERR,"resulting path too long"); + parse_error=-1; + break; + } + + childFile = fopen(fullPath, "r"); + if (childFile == NULL){ + logprintf(LOG_ERR,"error opening child file '%s' defined at line %d:",fullPath, line); + logprintf(LOG_ERR,"ignoring this child file for now."); + } + else{ + int save_line = line; + + if (!top_rem){ + /* create first remote */ + LOGPRINTF(2,"creating first remote"); + rem = read_config_recursive(childFile, fullPath, depth + 1); + if(rem != (void *) -1 && rem != NULL) { + top_rem = rem; + } else { + rem = NULL; + } + }else{ + /* create new remote */ + LOGPRINTF(2,"creating next remote"); + rem->next=read_config_recursive(childFile, fullPath, depth + 1); + if(rem->next != (void *) -1 && rem->next != NULL) { + rem=rem->next; + } else { + rem->next = NULL; + } + } + fclose(childFile); + line = save_line; + } + }else if (strcasecmp("begin",key)==0){ if (strcasecmp("codes", val)==0){ /* init codes mode */ LOGPRINTF(2," begin codes"); @@ -744,7 +888,7 @@ struct ir_remote * read_config(FILE *f) if(val2[0]=='#') break; /* comment */ node=defineNode(code, val2); - val2=strtok(NULL, " \t"); + val2=strtok(NULL, whitespace); } code->current=NULL; add_void_array(&codes_list, code); @@ -822,7 +966,7 @@ struct ir_remote * read_config(FILE *f) if(val2[0]=='#') break; /* comment */ node=defineNode(code, val2); - val2=strtok(NULL, " \t"); + val2=strtok(NULL, whitespace); } code->current=NULL; add_void_array(&codes_list, code); @@ -842,7 +986,7 @@ struct ir_remote * read_config(FILE *f) case ID_remote: argc=defineRemote(key, val, val2, rem); if(!parse_error && ((argc==1 && val2!=NULL) || - (argc==2 && val2!=NULL && strtok(NULL," \t")!=NULL))) + (argc==2 && val2!=NULL && strtok(NULL, whitespace)!=NULL))) { logprintf(LOG_WARNING,"garbage after '%s'" " token in line %d ignored", @@ -857,7 +1001,7 @@ struct ir_remote * read_config(FILE *f) if(val2[0]=='#') break; /* comment */ node=defineNode(code, val2); - val2=strtok(NULL, " \t"); + val2=strtok(NULL, whitespace); } code->current=NULL; add_void_array(&codes_list, code); @@ -905,7 +1049,7 @@ struct ir_remote * read_config(FILE *f) break; } } - while ((val=strtok(NULL," \t"))){ + while ((val=strtok(NULL, whitespace))){ if (!addSignal(&signals, val)) break; } } @@ -950,7 +1094,15 @@ struct ir_remote * read_config(FILE *f) } } if (parse_error){ + static int print_error = 1; + + if(print_error) { + logprintf(LOG_ERR, "reading of file '%s' failed", + name); + print_error = 0; + } free_config(top_rem); + if(depth == 0) print_error = 1; return((void *) -1); } /* kick reverse flag */ diff -Naurp lirc-0.8.3.orig/daemons/config_file.h lirc-0.8.3/daemons/config_file.h --- lirc-0.8.3.orig/daemons/config_file.h 2006-01-28 13:36:44.000000000 -0500 +++ lirc-0.8.3/daemons/config_file.h 2008-05-12 18:02:22.000000000 -0400 @@ -1,4 +1,4 @@ -/* $Id: config_file.h,v 5.10 2006/01/28 18:36:44 lirc Exp $ */ +/* $Id: config_file.h,v 5.11 2008/05/09 18:40:59 lirc Exp $ */ /**************************************************************************** ** config_file.h *********************************************************** @@ -86,7 +86,7 @@ int addSignal(struct void_array *signals struct ir_ncode * defineCode(char *key, char *val, struct ir_ncode *code); struct ir_code_node *defineNode(struct ir_ncode *code, const char *val); int defineRemote(char * key, char * val, char *val2, struct ir_remote *rem); -struct ir_remote *read_config(FILE *f); +struct ir_remote *read_config(FILE *f, const char *name); void free_config(struct ir_remote *remotes); #endif diff -Naurp lirc-0.8.3.orig/daemons/irrecord.c lirc-0.8.3/daemons/irrecord.c --- lirc-0.8.3.orig/daemons/irrecord.c 2008-02-14 15:42:56.000000000 -0500 +++ lirc-0.8.3/daemons/irrecord.c 2008-05-12 18:03:51.000000000 -0400 @@ -1,4 +1,4 @@ -/* $Id: irrecord.c,v 5.69 2008/02/14 20:42:56 lirc Exp $ */ +/* $Id: irrecord.c,v 5.71 2008/05/09 18:40:59 lirc Exp $ */ /**************************************************************************** ** irrecord.c ************************************************************** @@ -311,7 +311,7 @@ int main(int argc,char **argv) progname, filename, progname); exit(EXIT_FAILURE); } - remotes=read_config(fin); + remotes=read_config(fin, filename); fclose(fin); if(remotes==(void *) -1 || remotes==NULL) { @@ -748,7 +748,7 @@ int main(int argc,char **argv) if(hw.deinit_func) hw.deinit_func(); exit(EXIT_FAILURE); } - remotes=read_config(fin); + remotes=read_config(fin,filename); fclose(fin); if(remotes==NULL) { diff -Naurp lirc-0.8.3.orig/daemons/lircd.c lirc-0.8.3/daemons/lircd.c --- lirc-0.8.3.orig/daemons/lircd.c 2008-03-30 10:53:06.000000000 -0400 +++ lirc-0.8.3/daemons/lircd.c 2008-05-12 18:02:12.000000000 -0400 @@ -1,4 +1,4 @@ -/* $Id: lircd.c,v 5.76 2008/03/30 14:53:06 lirc Exp $ */ +/* $Id: lircd.c,v 5.77 2008/05/09 18:40:59 lirc Exp $ */ /**************************************************************************** ** lircd.c ***************************************************************** @@ -406,7 +406,7 @@ void config(void) logperror(LOG_ERR,NULL); return; } - config_remotes=read_config(fd); + config_remotes=read_config(fd, configfile); fclose(fd); if(config_remotes==(void *) -1) { diff -Naurp lirc-0.8.3.orig/NEWS lirc-0.8.3/NEWS --- lirc-0.8.3.orig/NEWS 2008-05-12 17:59:40.000000000 -0400 +++ lirc-0.8.3/NEWS 2008-05-12 18:05:04.000000000 -0400 @@ -1,3 +1,6 @@ +0.8.4-CVS: future + * support for include directive in lircd.conf + 0.8.3: 05/04/08 * added support for Samsung USB IR Receiver (Robert Schedel) * added support for Soundgraph iMON IR/LCD (Dean Harding)