X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/0b76cd63ee0eacb95285dfb5d2cac2992e1794ef..794f2cbab329127272a3f0aca96098618144f5d2:/params.c diff --git a/params.c b/params.c index b89d034c..a14242e8 100644 --- a/params.c +++ b/params.c @@ -1,10 +1,10 @@ -/* - This modules is based on the params.c module from Samba, written by Karl Auer - and much modifed by Christopher Hertel. +/* This modules is based on the params.c module from Samba, written by Karl Auer + and much modifed by Christopher Hertel. */ +/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, @@ -12,11 +12,11 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * -------------------------------------------------------------------------- ** + * You should have received a copy of the GNU General Public License along + * with this program; if not, visit the http://fsf.org website. + */ + +/* -------------------------------------------------------------------------- ** * * Module name: params * @@ -74,10 +74,8 @@ */ #include "rsync.h" -#define BOOL int -#define False 0 -#define True 1 -#define Realloc realloc +#include "ifuncs.h" +#include "itypes.h" /* -------------------------------------------------------------------------- ** * Constants... @@ -96,6 +94,8 @@ static char *bufr = NULL; static int bSize = 0; +static BOOL (*the_sfunc)(char *); +static BOOL (*the_pfunc)(char *, char *); /* -------------------------------------------------------------------------- ** * Functions... @@ -168,7 +168,7 @@ static int Continuation( char *line, int pos ) */ { pos--; - while( (pos >= 0) && isspace(line[pos]) ) + while( pos >= 0 && isSpace(line + pos) ) pos--; return( ((pos >= 0) && ('\\' == line[pos])) ? pos : -1 ); @@ -211,10 +211,10 @@ static BOOL Section( FILE *InFile, BOOL (*sfunc)(char *) ) if( i > (bSize - 2) ) { bSize += BUFR_INC; - bufr = Realloc( bufr, bSize ); + bufr = realloc_array( bufr, char, bSize ); if( NULL == bufr ) { - rprintf(FERROR, "%s Memory re-allocation failure.", func); + rprintf(FLOG, "%s Memory re-allocation failure.", func); return( False ); } } @@ -226,7 +226,7 @@ static BOOL Section( FILE *InFile, BOOL (*sfunc)(char *) ) bufr[end] = '\0'; if( 0 == end ) /* Don't allow an empty name. */ { - rprintf(FERROR, "%s Empty section name in configuration file.\n", func ); + rprintf(FLOG, "%s Empty section name in config file.\n", func ); return( False ); } if( !sfunc( bufr ) ) /* Got a valid name. Deal with it. */ @@ -239,7 +239,7 @@ static BOOL Section( FILE *InFile, BOOL (*sfunc)(char *) ) if( i < 0 ) { bufr[end] = '\0'; - rprintf(FERROR, "%s Badly formed line in configuration file: %s\n", + rprintf(FLOG, "%s Badly formed line in config file: %s\n", func, bufr ); return( False ); } @@ -264,7 +264,7 @@ static BOOL Section( FILE *InFile, BOOL (*sfunc)(char *) ) } /* We arrive here if we've met the EOF before the closing bracket. */ - rprintf(FERROR, "%s Unexpected EOF in the configuration file: %s\n", func, bufr ); + rprintf(FLOG, "%s Unexpected EOF in the config file: %s\n", func, bufr ); return( False ); } /* Section */ @@ -305,10 +305,10 @@ static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(char *, char *), int c ) if( i > (bSize - 2) ) /* Ensure there's space for next char. */ { bSize += BUFR_INC; - bufr = Realloc( bufr, bSize ); + bufr = realloc_array( bufr, char, bSize ); if( NULL == bufr ) { - rprintf(FERROR, "%s Memory re-allocation failure.", func) ; + rprintf(FLOG, "%s Memory re-allocation failure.", func) ; return( False ); } } @@ -318,13 +318,12 @@ static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(char *, char *), int c ) case '=': /* Equal sign marks end of param name. */ if( 0 == end ) /* Don't allow an empty name. */ { - rprintf(FERROR, "%s Invalid parameter name in config. file.\n", func ); + rprintf(FLOG, "%s Invalid parameter name in config file.\n", func ); return( False ); } bufr[end++] = '\0'; /* Mark end of string & advance. */ - i = end; /* New string starts here. */ - vstart = end; /* New string is parameter value. */ - bufr[i] = '\0'; /* New string is nul, for now. */ + i = vstart = end; /* New string starts here. */ + c = EatWhitespace(InFile); break; case '\n': /* Find continuation char, else error. */ @@ -332,7 +331,7 @@ static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(char *, char *), int c ) if( i < 0 ) { bufr[end] = '\0'; - rprintf(FERROR, "%s Ignoring badly formed line in configuration file: %s\n", + rprintf(FLOG, "%s Ignoring badly formed line in config file: %s\n", func, bufr ); return( True ); } @@ -343,9 +342,22 @@ static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(char *, char *), int c ) case '\0': /* Shouldn't have EOF within param name. */ case EOF: bufr[i] = '\0'; - rprintf(FERROR, "%s Unexpected end-of-file at: %s\n", func, bufr ); + rprintf(FLOG, "%s Unexpected end-of-file at: %s\n", func, bufr ); return( True ); + case ' ': + case '\t': + /* A directive divides at the first space or tab. */ + if (*bufr == '&') { + bufr[end++] = '\0'; + i = vstart = end; + c = EatWhitespace(InFile); + if (c == '=') + c = EatWhitespace(InFile); + break; + } + /* FALL THROUGH */ + default: if( isspace( c ) ) /* One ' ' per whitespace region. */ { @@ -363,17 +375,16 @@ static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(char *, char *), int c ) } /* Now parse the value. */ - c = EatWhitespace( InFile ); /* Again, trim leading whitespace. */ while( (EOF !=c) && (c > 0) ) { if( i > (bSize - 2) ) /* Make sure there's enough room. */ { bSize += BUFR_INC; - bufr = Realloc( bufr, bSize ); + bufr = realloc_array( bufr, char, bSize ); if( NULL == bufr ) { - rprintf(FERROR, "%s Memory re-allocation failure.", func) ; + rprintf(FLOG, "%s Memory re-allocation failure.", func) ; return( False ); } } @@ -390,7 +401,7 @@ static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(char *, char *), int c ) c = 0; else { - for( end = i; (end >= 0) && isspace(bufr[end]); end-- ) + for( end = i; end >= 0 && isSpace(bufr + end); end-- ) ; c = getc( InFile ); } @@ -409,7 +420,87 @@ static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(char *, char *), int c ) return( pfunc( bufr, &bufr[vstart] ) ); /* Pass name & value to pfunc(). */ } /* Parameter */ -static BOOL Parse( FILE *InFile, +static int name_cmp(const void *n1, const void *n2) +{ + return strcmp(*(char * const *)n1, *(char * const *)n2); +} + +static int include_config(char *include, int manage_globals) +{ + STRUCT_STAT sb; + int ret; + + if (do_stat(include, &sb) < 0) { + rsyserr(FLOG, errno, "unable to stat config file \"%s\"", include); + return 0; + } + + if (S_ISREG(sb.st_mode)) { + if (manage_globals && the_sfunc) + the_sfunc("]push"); + ret = pm_process(include, the_sfunc, the_pfunc); + if (manage_globals && the_sfunc) + the_sfunc("]pop"); + } else if (S_ISDIR(sb.st_mode)) { + char buf[MAXPATHLEN], **bpp; + item_list conf_list; + struct dirent *di; + size_t j; + DIR *d; + + if (!(d = opendir(include))) { + rsyserr(FLOG, errno, "unable to open config dir \"%s\"", include); + return 0; + } + + memset(&conf_list, 0, sizeof conf_list); + + while ((di = readdir(d)) != NULL) { + char *dname = d_name(di); + if (!wildmatch("*.conf", dname)) + continue; + bpp = EXPAND_ITEM_LIST(&conf_list, char *, 32); + pathjoin(buf, sizeof buf, include, dname); + *bpp = strdup(buf); + } + closedir(d); + + if (!(bpp = conf_list.items)) + return 1; + + if (conf_list.count > 1) + qsort(bpp, conf_list.count, sizeof (char *), name_cmp); + + for (j = 0, ret = 1; j < conf_list.count; j++) { + if (manage_globals && the_sfunc) + the_sfunc(j == 0 ? "]push" : "]reset"); + if ((ret = pm_process(bpp[j], the_sfunc, the_pfunc)) != 1) + break; + } + + if (manage_globals && the_sfunc) + the_sfunc("]pop"); + + for (j = 0; j < conf_list.count; j++) + free(bpp[j]); + free(bpp); + } else + ret = 0; + + return ret; +} + +static int parse_directives(char *name, char *val) +{ + if (strcasecmp(name, "&include") == 0) + return include_config(val, 1); + if (strcasecmp(name, "&merge") == 0) + return include_config(val, 0); + rprintf(FLOG, "Unknown directive: %s.\n", name); + return 0; +} + +static int Parse( FILE *InFile, BOOL (*sfunc)(char *), BOOL (*pfunc)(char *, char *) ) /* ------------------------------------------------------------------------ ** @@ -421,7 +512,8 @@ static BOOL Parse( FILE *InFile, * pfunc - Function to be called when a parameter is scanned. * See Parameter(). * - * Output: True if the file was successfully scanned, else False. + * Output: 1 if the file was successfully scanned, 2 if the file was + * scanned until a section header with no section function, else 0. * * Notes: The input can be viewed in terms of 'lines'. There are four * types of lines: @@ -430,7 +522,7 @@ static BOOL Parse( FILE *InFile, * The remainder of the line is ignored. * Section - First non-whitespace character is a '['. * Parameter - The default case. - * + * * ------------------------------------------------------------------------ ** */ { @@ -451,8 +543,10 @@ static BOOL Parse( FILE *InFile, break; case '[': /* Section Header. */ + if (!sfunc) + return 2; if( !Section( InFile, sfunc ) ) - return( False ); + return 0; c = EatWhitespace( InFile ); break; @@ -460,19 +554,28 @@ static BOOL Parse( FILE *InFile, c = EatWhitespace( InFile ); break; + case '&': /* Handle directives */ + the_sfunc = sfunc; + the_pfunc = pfunc; + c = Parameter( InFile, parse_directives, c ); + if (c != 1) + return c; + c = EatWhitespace( InFile ); + break; + default: /* Parameter line. */ if( !Parameter( InFile, pfunc, c ) ) - return( False ); + return 0; c = EatWhitespace( InFile ); break; } } - return( True ); + return 1; } /* Parse */ static FILE *OpenConfFile( char *FileName ) /* ------------------------------------------------------------------------ ** - * Open a configuration file. + * Open a config file. * * Input: FileName - The pathname of the config file to be opened. * @@ -487,21 +590,21 @@ static FILE *OpenConfFile( char *FileName ) if( NULL == FileName || 0 == *FileName ) { - rprintf(FERROR,"%s No configuration filename specified.\n", func); + rprintf(FLOG, "%s No config filename specified.\n", func); return( NULL ); } OpenedFile = fopen( FileName, "r" ); if( NULL == OpenedFile ) { - rprintf(FERROR,"%s Unable to open configuration file \"%s\":\n\t%s\n", - func, FileName, strerror(errno)); + rsyserr(FLOG, errno, "unable to open config file \"%s\"", + FileName); } return( OpenedFile ); } /* OpenConfFile */ -BOOL pm_process( char *FileName, +int pm_process( char *FileName, BOOL (*sfunc)(char *), BOOL (*pfunc)(char *, char *) ) /* ------------------------------------------------------------------------ ** @@ -513,7 +616,8 @@ BOOL pm_process( char *FileName, * pfunc - A pointer to a function that will be called when * a parameter name and value are discovered. * - * Output: TRUE if the file was successfully parsed, else FALSE. + * Output: 1 if the file was successfully parsed, 2 if parsing ended at a + * section header w/o a section function, else 0. * * ------------------------------------------------------------------------ ** */ @@ -533,10 +637,10 @@ BOOL pm_process( char *FileName, else /* If we don't have a buffer */ { /* allocate one, then parse, */ bSize = BUFR_INC; /* then free. */ - bufr = (char *)malloc( bSize ); + bufr = new_array( char, bSize ); if( NULL == bufr ) { - rprintf(FERROR,"%s memory allocation failure.\n", func); + rprintf(FLOG, "%s memory allocation failure.\n", func); fclose(InFile); return( False ); } @@ -550,11 +654,12 @@ BOOL pm_process( char *FileName, if( !result ) /* Generic failure. */ { - rprintf(FERROR,"%s Failed. Error returned from params.c:parse().\n", func); - return( False ); + rprintf(FLOG, "%s Failed. Error returned from params.c:parse().\n", func); + return 0; } - return( True ); /* Generic success. */ + return result; } /* pm_process */ /* -------------------------------------------------------------------------- */ +