version 1.1, 2012/02/17 15:09:30
|
version 1.1.1.3, 2021/03/17 00:32:36
|
Line 1
|
Line 1
|
/* This modules is based on the params.c module from Samba, written by Karl Auer |
/* This modules is based on the params.c module from Samba, written by Karl Auer |
and much modifed by Christopher Hertel. */ | and much modified by Christopher Hertel. */ |
|
|
/* |
/* |
* This program is free software; you can redistribute it and/or modify |
* This program is free software; you can redistribute it and/or modify |
Line 59
|
Line 59
|
* beginning with either a semicolon (';') or a pound sign ('#'). |
* beginning with either a semicolon (';') or a pound sign ('#'). |
* |
* |
* All whitespace in section names and parameter names is compressed |
* All whitespace in section names and parameter names is compressed |
* to single spaces. Leading and trailing whitespace is stipped from | * to single spaces. Leading and trailing whitespace is stripped from |
* both names and values. |
* both names and values. |
* |
* |
* Only the first equals sign in a parameter line is significant. |
* Only the first equals sign in a parameter line is significant. |
Line 75
|
Line 75
|
|
|
#include "rsync.h" |
#include "rsync.h" |
#include "ifuncs.h" |
#include "ifuncs.h" |
|
#include "itypes.h" |
|
|
/* -------------------------------------------------------------------------- ** |
/* -------------------------------------------------------------------------- ** |
* Constants... |
* Constants... |
Line 93
|
Line 94
|
|
|
static char *bufr = NULL; |
static char *bufr = NULL; |
static int bSize = 0; |
static int bSize = 0; |
|
static BOOL (*the_sfunc)(char *); |
|
static BOOL (*the_pfunc)(char *, char *); |
|
|
/* -------------------------------------------------------------------------- ** |
/* -------------------------------------------------------------------------- ** |
* Functions... |
* Functions... |
Line 150 static int EatComment( FILE *InFile )
|
Line 153 static int EatComment( FILE *InFile )
|
|
|
static int Continuation( char *line, int pos ) |
static int Continuation( char *line, int pos ) |
/* ------------------------------------------------------------------------ ** |
/* ------------------------------------------------------------------------ ** |
* Scan backards within a string to discover if the last non-whitespace | * Scan backwards within a string to discover if the last non-whitespace |
* character is a line-continuation character ('\\'). |
* character is a line-continuation character ('\\'). |
* |
* |
* Input: line - A pointer to a buffer containing the string to be |
* Input: line - A pointer to a buffer containing the string to be |
Line 209 static BOOL Section( FILE *InFile, BOOL (*sfunc)(char
|
Line 212 static BOOL Section( FILE *InFile, BOOL (*sfunc)(char
|
{ |
{ |
bSize += BUFR_INC; |
bSize += BUFR_INC; |
bufr = realloc_array( bufr, char, bSize ); |
bufr = realloc_array( bufr, char, bSize ); |
if( NULL == bufr ) |
|
{ |
|
rprintf(FLOG, "%s Memory re-allocation failure.", func); |
|
return( False ); |
|
} |
|
} |
} |
|
|
/* Handle a single character. */ |
/* Handle a single character. */ |
Line 223 static BOOL Section( FILE *InFile, BOOL (*sfunc)(char
|
Line 221 static BOOL Section( FILE *InFile, BOOL (*sfunc)(char
|
bufr[end] = '\0'; |
bufr[end] = '\0'; |
if( 0 == end ) /* Don't allow an empty name. */ |
if( 0 == end ) /* Don't allow an empty name. */ |
{ |
{ |
rprintf(FLOG, "%s Empty section name in configuration file.\n", func ); | rprintf(FLOG, "%s Empty section name in config file.\n", func ); |
return( False ); |
return( False ); |
} |
} |
if( !sfunc( bufr ) ) /* Got a valid name. Deal with it. */ |
if( !sfunc( bufr ) ) /* Got a valid name. Deal with it. */ |
Line 236 static BOOL Section( FILE *InFile, BOOL (*sfunc)(char
|
Line 234 static BOOL Section( FILE *InFile, BOOL (*sfunc)(char
|
if( i < 0 ) |
if( i < 0 ) |
{ |
{ |
bufr[end] = '\0'; |
bufr[end] = '\0'; |
rprintf(FLOG, "%s Badly formed line in configuration file: %s\n", | rprintf(FLOG, "%s Badly formed line in config file: %s\n", |
func, bufr ); |
func, bufr ); |
return( False ); |
return( False ); |
} |
} |
Line 261 static BOOL Section( FILE *InFile, BOOL (*sfunc)(char
|
Line 259 static BOOL Section( FILE *InFile, BOOL (*sfunc)(char
|
} |
} |
|
|
/* We arrive here if we've met the EOF before the closing bracket. */ |
/* We arrive here if we've met the EOF before the closing bracket. */ |
rprintf(FLOG, "%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 ); |
return( False ); |
} /* Section */ |
} /* Section */ |
|
|
Line 303 static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(cha
|
Line 301 static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(cha
|
{ |
{ |
bSize += BUFR_INC; |
bSize += BUFR_INC; |
bufr = realloc_array( bufr, char, bSize ); |
bufr = realloc_array( bufr, char, bSize ); |
if( NULL == bufr ) |
|
{ |
|
rprintf(FLOG, "%s Memory re-allocation failure.", func) ; |
|
return( False ); |
|
} |
|
} |
} |
|
|
switch( c ) |
switch( c ) |
Line 315 static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(cha
|
Line 308 static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(cha
|
case '=': /* Equal sign marks end of param name. */ |
case '=': /* Equal sign marks end of param name. */ |
if( 0 == end ) /* Don't allow an empty name. */ |
if( 0 == end ) /* Don't allow an empty name. */ |
{ |
{ |
rprintf(FLOG, "%s Invalid parameter name in config. file.\n", func ); | rprintf(FLOG, "%s Invalid parameter name in config file.\n", func ); |
return( False ); |
return( False ); |
} |
} |
bufr[end++] = '\0'; /* Mark end of string & advance. */ |
bufr[end++] = '\0'; /* Mark end of string & advance. */ |
i = end; /* New string starts here. */ | i = vstart = end; /* New string starts here. */ |
vstart = end; /* New string is parameter value. */ | c = EatWhitespace(InFile); |
bufr[i] = '\0'; /* New string is nul, for now. */ | |
break; |
break; |
|
|
case '\n': /* Find continuation char, else error. */ |
case '\n': /* Find continuation char, else error. */ |
Line 329 static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(cha
|
Line 321 static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(cha
|
if( i < 0 ) |
if( i < 0 ) |
{ |
{ |
bufr[end] = '\0'; |
bufr[end] = '\0'; |
rprintf(FLOG, "%s Ignoring badly formed line in configuration file: %s\n", | rprintf(FLOG, "%s Ignoring badly formed line in config file: %s\n", |
func, bufr ); |
func, bufr ); |
return( True ); |
return( True ); |
} |
} |
Line 343 static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(cha
|
Line 335 static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(cha
|
rprintf(FLOG, "%s Unexpected end-of-file at: %s\n", func, bufr ); |
rprintf(FLOG, "%s Unexpected end-of-file at: %s\n", func, bufr ); |
return( True ); |
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: |
default: |
if( isspace( c ) ) /* One ' ' per whitespace region. */ |
if( isspace( c ) ) /* One ' ' per whitespace region. */ |
{ |
{ |
Line 360 static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(cha
|
Line 365 static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(cha
|
} |
} |
|
|
/* Now parse the value. */ |
/* Now parse the value. */ |
c = EatWhitespace( InFile ); /* Again, trim leading whitespace. */ |
|
while( (EOF !=c) && (c > 0) ) |
while( (EOF !=c) && (c > 0) ) |
{ |
{ |
|
|
Line 368 static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(cha
|
Line 372 static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(cha
|
{ |
{ |
bSize += BUFR_INC; |
bSize += BUFR_INC; |
bufr = realloc_array( bufr, char, bSize ); |
bufr = realloc_array( bufr, char, bSize ); |
if( NULL == bufr ) |
|
{ |
|
rprintf(FLOG, "%s Memory re-allocation failure.", func) ; |
|
return( False ); |
|
} |
|
} |
} |
|
|
switch( c ) |
switch( c ) |
Line 406 static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(cha
|
Line 405 static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(cha
|
return( pfunc( bufr, &bufr[vstart] ) ); /* Pass name & value to pfunc(). */ |
return( pfunc( bufr, &bufr[vstart] ) ); /* Pass name & value to pfunc(). */ |
} /* Parameter */ |
} /* 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; |
| char *match = manage_globals ? "*.conf" : "*.inc"; |
| 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(match, 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 (*sfunc)(char *), |
BOOL (*pfunc)(char *, char *) ) |
BOOL (*pfunc)(char *, char *) ) |
/* ------------------------------------------------------------------------ ** |
/* ------------------------------------------------------------------------ ** |
Line 418 static BOOL Parse( FILE *InFile,
|
Line 498 static BOOL Parse( FILE *InFile,
|
* pfunc - Function to be called when a parameter is scanned. |
* pfunc - Function to be called when a parameter is scanned. |
* See Parameter(). |
* 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 |
* Notes: The input can be viewed in terms of 'lines'. There are four |
* types of lines: |
* types of lines: |
Line 427 static BOOL Parse( FILE *InFile,
|
Line 508 static BOOL Parse( FILE *InFile,
|
* The remainder of the line is ignored. |
* The remainder of the line is ignored. |
* Section - First non-whitespace character is a '['. |
* Section - First non-whitespace character is a '['. |
* Parameter - The default case. |
* Parameter - The default case. |
* | * |
* ------------------------------------------------------------------------ ** |
* ------------------------------------------------------------------------ ** |
*/ |
*/ |
{ |
{ |
Line 448 static BOOL Parse( FILE *InFile,
|
Line 529 static BOOL Parse( FILE *InFile,
|
break; |
break; |
|
|
case '[': /* Section Header. */ |
case '[': /* Section Header. */ |
if (!sfunc) return True; | if (!sfunc) |
if( !Section( InFile, sfunc ) ) | return 2; |
return( False ); | if( !Section( InFile, sfunc ) ) |
c = EatWhitespace( InFile ); | return 0; |
break; | c = EatWhitespace( InFile ); |
| break; |
|
|
case '\\': /* Bogus backslash. */ |
case '\\': /* Bogus backslash. */ |
c = EatWhitespace( InFile ); |
c = EatWhitespace( InFile ); |
break; |
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. */ |
default: /* Parameter line. */ |
if( !Parameter( InFile, pfunc, c ) ) |
if( !Parameter( InFile, pfunc, c ) ) |
return( False ); | return 0; |
c = EatWhitespace( InFile ); |
c = EatWhitespace( InFile ); |
break; |
break; |
} |
} |
} |
} |
return( True ); | return 1; |
} /* Parse */ |
} /* Parse */ |
|
|
static FILE *OpenConfFile( char *FileName ) |
static FILE *OpenConfFile( char *FileName ) |
/* ------------------------------------------------------------------------ ** |
/* ------------------------------------------------------------------------ ** |
* Open a configuration file. | * Open a config file. |
* |
* |
* Input: FileName - The pathname of the config file to be opened. |
* Input: FileName - The pathname of the config file to be opened. |
* |
* |
Line 485 static FILE *OpenConfFile( char *FileName )
|
Line 576 static FILE *OpenConfFile( char *FileName )
|
|
|
if( NULL == FileName || 0 == *FileName ) |
if( NULL == FileName || 0 == *FileName ) |
{ |
{ |
rprintf(FLOG, "%s No configuration filename specified.\n", func); | rprintf(FLOG, "%s No config filename specified.\n", func); |
return( NULL ); |
return( NULL ); |
} |
} |
|
|
OpenedFile = fopen( FileName, "r" ); |
OpenedFile = fopen( FileName, "r" ); |
if( NULL == OpenedFile ) |
if( NULL == OpenedFile ) |
{ |
{ |
rsyserr(FLOG, errno, "unable to open configuration file \"%s\"", | rsyserr(FLOG, errno, "unable to open config file \"%s\"", |
FileName); |
FileName); |
} |
} |
|
|
return( OpenedFile ); |
return( OpenedFile ); |
} /* OpenConfFile */ |
} /* OpenConfFile */ |
|
|
BOOL pm_process( char *FileName, | int pm_process( char *FileName, |
BOOL (*sfunc)(char *), |
BOOL (*sfunc)(char *), |
BOOL (*pfunc)(char *, char *) ) |
BOOL (*pfunc)(char *, char *) ) |
/* ------------------------------------------------------------------------ ** |
/* ------------------------------------------------------------------------ ** |
Line 511 BOOL pm_process( char *FileName,
|
Line 602 BOOL pm_process( char *FileName,
|
* pfunc - A pointer to a function that will be called when |
* pfunc - A pointer to a function that will be called when |
* a parameter name and value are discovered. |
* 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. |
* |
* |
* ------------------------------------------------------------------------ ** |
* ------------------------------------------------------------------------ ** |
*/ |
*/ |
Line 532 BOOL pm_process( char *FileName,
|
Line 624 BOOL pm_process( char *FileName,
|
{ /* allocate one, then parse, */ |
{ /* allocate one, then parse, */ |
bSize = BUFR_INC; /* then free. */ |
bSize = BUFR_INC; /* then free. */ |
bufr = new_array( char, bSize ); |
bufr = new_array( char, bSize ); |
if( NULL == bufr ) |
|
{ |
|
rprintf(FLOG, "%s memory allocation failure.\n", func); |
|
fclose(InFile); |
|
return( False ); |
|
} |
|
result = Parse( InFile, sfunc, pfunc ); |
result = Parse( InFile, sfunc, pfunc ); |
free( bufr ); |
free( bufr ); |
bufr = NULL; |
bufr = NULL; |
Line 549 BOOL pm_process( char *FileName,
|
Line 635 BOOL pm_process( char *FileName,
|
if( !result ) /* Generic failure. */ |
if( !result ) /* Generic failure. */ |
{ |
{ |
rprintf(FLOG, "%s Failed. Error returned from params.c:parse().\n", func); |
rprintf(FLOG, "%s Failed. Error returned from params.c:parse().\n", func); |
return( False ); | return 0; |
} |
} |
|
|
return( True ); /* Generic success. */ | return result; |
} /* pm_process */ |
} /* pm_process */ |
|
|
/* -------------------------------------------------------------------------- */ |
/* -------------------------------------------------------------------------- */ |