mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-02-25 02:47:39 -05:00
Added &include and &merge config-file directives that allow the
daemon's config file incorporate the contents of other files.
This commit is contained in:
32
loadparm.c
32
loadparm.c
@@ -154,6 +154,11 @@ typedef struct {
|
||||
BOOL write_only;
|
||||
} section;
|
||||
|
||||
typedef struct {
|
||||
global g;
|
||||
section s;
|
||||
} global_and_section;
|
||||
|
||||
/* This is a default section used to prime a sections structure. In order
|
||||
* to make these easy to keep sorted in the same way as the variables
|
||||
* above, use the variable name in the leading comment, including a
|
||||
@@ -205,6 +210,7 @@ static section sDefault = {
|
||||
|
||||
/* local variables */
|
||||
static item_list section_list = EMPTY_ITEM_LIST;
|
||||
static item_list section_stack = EMPTY_ITEM_LIST;
|
||||
static int iSectionIndex = -1;
|
||||
static BOOL bInGlobalSection = True;
|
||||
|
||||
@@ -676,7 +682,29 @@ static BOOL do_parameter(char *parmname, char *parmvalue)
|
||||
* Returns True on success, False on failure. */
|
||||
static BOOL do_section(char *sectionname)
|
||||
{
|
||||
BOOL isglobal = strwicmp(sectionname, GLOBAL_NAME) == 0;
|
||||
BOOL isglobal;
|
||||
|
||||
if (*sectionname == ']') { /* A special push/pop/reset directive from params.c */
|
||||
bInGlobalSection = 1;
|
||||
if (strcmp(sectionname+1, "push") == 0) {
|
||||
global_and_section *gs = EXPAND_ITEM_LIST(§ion_stack, global_and_section, 2);
|
||||
memcpy(&gs->g, &Globals, sizeof Globals);
|
||||
memcpy(&gs->s, &sDefault, sizeof sDefault);
|
||||
} else if (strcmp(sectionname+1, "pop") == 0
|
||||
|| strcmp(sectionname+1, "reset") == 0) {
|
||||
global_and_section *gs = ((global_and_section *)section_stack.items) + section_stack.count - 1;
|
||||
if (!section_stack.count)
|
||||
return False;
|
||||
memcpy(&Globals, &gs->g, sizeof Globals);
|
||||
memcpy(&sDefault, &gs->s, sizeof sDefault);
|
||||
if (sectionname[1] == 'p')
|
||||
section_stack.count--;
|
||||
} else
|
||||
return False;
|
||||
return True;
|
||||
}
|
||||
|
||||
isglobal = strwicmp(sectionname, GLOBAL_NAME) == 0;
|
||||
|
||||
/* if we were in a global section then do the local inits */
|
||||
if (bInGlobalSection && !isglobal)
|
||||
@@ -714,7 +742,7 @@ static BOOL do_section(char *sectionname)
|
||||
|
||||
/* Load the modules from the config file. Return True on success,
|
||||
* False on failure. */
|
||||
BOOL lp_load(char *pszFname, int globals_only)
|
||||
int lp_load(char *pszFname, int globals_only)
|
||||
{
|
||||
pstring n2;
|
||||
|
||||
|
||||
107
params.c
107
params.c
@@ -93,6 +93,8 @@
|
||||
|
||||
static char *bufr = NULL;
|
||||
static int bSize = 0;
|
||||
static BOOL (*the_sfunc)(char *);
|
||||
static BOOL (*the_pfunc)(char *, char *);
|
||||
|
||||
/* -------------------------------------------------------------------------- **
|
||||
* Functions...
|
||||
@@ -406,7 +408,71 @@ 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)
|
||||
{
|
||||
item_list conf_list;
|
||||
struct dirent *di;
|
||||
char buf[MAXPATHLEN], **bpp;
|
||||
int ret = 1;
|
||||
size_t j;
|
||||
DIR *d;
|
||||
|
||||
memset(&conf_list, 0, sizeof conf_list);
|
||||
|
||||
if ((d = opendir(include)) != NULL) {
|
||||
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);
|
||||
} else {
|
||||
STRUCT_STAT sb;
|
||||
if (stat(include, &sb) < 0)
|
||||
return 0;
|
||||
bpp = EXPAND_ITEM_LIST(&conf_list, char *, 1);
|
||||
*bpp = strdup(include);
|
||||
}
|
||||
|
||||
if (conf_list.count > 1)
|
||||
qsort(conf_list.items, conf_list.count, sizeof (char *), name_cmp);
|
||||
|
||||
bpp = conf_list.items;
|
||||
for (j = 0; 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 && conf_list.count)
|
||||
the_sfunc("]pop");
|
||||
|
||||
for (j = 0; j < conf_list.count; j++)
|
||||
free(bpp[j]);
|
||||
|
||||
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 *) )
|
||||
/* ------------------------------------------------------------------------ **
|
||||
@@ -418,7 +484,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:
|
||||
@@ -427,7 +494,7 @@ static BOOL Parse( FILE *InFile,
|
||||
* The remainder of the line is ignored.
|
||||
* Section - First non-whitespace character is a '['.
|
||||
* Parameter - The default case.
|
||||
*
|
||||
*
|
||||
* ------------------------------------------------------------------------ **
|
||||
*/
|
||||
{
|
||||
@@ -448,24 +515,35 @@ static BOOL Parse( FILE *InFile,
|
||||
break;
|
||||
|
||||
case '[': /* Section Header. */
|
||||
if (!sfunc) return True;
|
||||
if( !Section( InFile, sfunc ) )
|
||||
return( False );
|
||||
c = EatWhitespace( InFile );
|
||||
break;
|
||||
if (!sfunc)
|
||||
return 2;
|
||||
if( !Section( InFile, sfunc ) )
|
||||
return 0;
|
||||
c = EatWhitespace( InFile );
|
||||
break;
|
||||
|
||||
case '\\': /* Bogus backslash. */
|
||||
c = EatWhitespace( InFile );
|
||||
break;
|
||||
|
||||
case '&': /* Handle directives */
|
||||
the_sfunc = sfunc;
|
||||
the_pfunc = pfunc;
|
||||
c = EatWhitespace( InFile );
|
||||
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 )
|
||||
@@ -499,7 +577,7 @@ static FILE *OpenConfFile( char *FileName )
|
||||
return( OpenedFile );
|
||||
} /* OpenConfFile */
|
||||
|
||||
BOOL pm_process( char *FileName,
|
||||
int pm_process( char *FileName,
|
||||
BOOL (*sfunc)(char *),
|
||||
BOOL (*pfunc)(char *, char *) )
|
||||
/* ------------------------------------------------------------------------ **
|
||||
@@ -511,7 +589,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.
|
||||
*
|
||||
* ------------------------------------------------------------------------ **
|
||||
*/
|
||||
@@ -549,10 +628,10 @@ BOOL pm_process( char *FileName,
|
||||
if( !result ) /* Generic failure. */
|
||||
{
|
||||
rprintf(FLOG, "%s Failed. Error returned from params.c:parse().\n", func);
|
||||
return( False );
|
||||
return 0;
|
||||
}
|
||||
|
||||
return( True ); /* Generic success. */
|
||||
return result;
|
||||
} /* pm_process */
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
@@ -616,6 +616,49 @@ module's uid/gid setting) without any chroot restrictions.
|
||||
|
||||
enddit()
|
||||
|
||||
manpagesection(CONFIG DIRECTIVES)
|
||||
|
||||
There are currently two config directives available that allow a config file to
|
||||
incorporate the contents of other files: bf(&include) and bf(&merge). Both
|
||||
allow a reference to either a file or a directory. They differ in how
|
||||
segregated the file's contents are considered to be. The bf(&include)
|
||||
directive treats each file as more distinct, with each one inheriting the
|
||||
defaults of the parent file, and starting the parameter parsing as
|
||||
globals/defaults. The bf(&merge) directive, on the other hand, treats the
|
||||
file's contents as if it were simply inserted in place of the directive, and
|
||||
thus it can contain parameters that can be set inside a parent file's module
|
||||
settings, or whatever you like.
|
||||
|
||||
When an bf(&include) or bf(&merge) directive refers to a directory, it will read
|
||||
in all the bf(*.conf) files contained inside that directory (without any
|
||||
recursive scanning), with the files sorted into alpha order. So, if you have a
|
||||
directory named "rsyncd.d" with the files "foo.conf", "bar.conf", and
|
||||
"baz.conf" inside it, this directive:
|
||||
|
||||
verb( &include = /path/rsyncd.d )
|
||||
|
||||
would be the same as this set of directives:
|
||||
|
||||
verb( &include = /path/rsyncd.d/bar.conf
|
||||
&include = /path/rsyncd.d/baz.conf
|
||||
&include = /path/rsyncd.d/foo.conf )
|
||||
|
||||
except that it adjusts as files are added and removed from the directory.
|
||||
|
||||
The advantage of the bf(&include) directive is that you can define one or more
|
||||
modules in a separate file with only the defaults you set in the parent file
|
||||
affecting it, so you don't need to worry about the settings of a prior include
|
||||
file changing a default. For instance, this is a useful /etc/rsyncd.conf file:
|
||||
|
||||
verb( port = 873
|
||||
log file = /path/rsync.log
|
||||
pid file = /var/lock/rsync.lock
|
||||
|
||||
&include /etc/rsyncd.d )
|
||||
|
||||
The advantage of the bf(&merge) directive is that you can load config snippets
|
||||
that can be included into multiple module definitions.
|
||||
|
||||
manpagesection(AUTHENTICATION STRENGTH)
|
||||
|
||||
The authentication protocol used in rsync is a 128 bit MD4 based
|
||||
|
||||
Reference in New Issue
Block a user