/* Load parameters.
*
* This module provides suitable callback functions for the params
- * module. It builds the internal table of service details which is
+ * module. It builds the internal table of section details which is
* then used by the rest of the server.
*
* To add a parameter:
*
- * 1) add it to the global or service structure definition
+ * 1) add it to the global or section structure definition
* 2) add it to the parm_table
* 3) add it to the list of available functions (eg: using FN_GLOBAL_STRING())
- * 4) If it's a global then initialise it in init_globals. If a local
- * (ie. service) parameter then initialise it in the sDefault structure
+ * 4) If it's a global then initialise it in init_globals. If a local module
+ * (ie. section) parameter then initialise it in the sDefault structure
*
*
* Notes:
#include "rsync.h"
#include "ifuncs.h"
-#define PTR_DIFF(p1, p2) ((ptrdiff_t)(((char *)(p1)) - (char *)(p2)))
+
+extern item_list dparam_list;
+
#define strequal(a, b) (strcasecmp(a, b)==0)
#define BOOLSTR(b) ((b) ? "Yes" : "No")
-typedef char pstring[1024];
-#define pstrcpy(a, b) strlcpy((a), (b), sizeof (pstring))
#ifndef LOG_DAEMON
#define LOG_DAEMON 0
/* the following are used by loadparm for option lists */
typedef enum {
- P_BOOL, P_BOOLREV, P_CHAR, P_INTEGER, P_OCTAL,
- P_PATH, P_STRING, P_GSTRING, P_ENUM, P_SEP
+ P_BOOL, P_BOOLREV, P_CHAR, P_INTEGER,
+ P_OCTAL, P_PATH, P_STRING, P_ENUM
} parm_type;
typedef enum {
- P_LOCAL, P_GLOBAL, P_SEPARATOR, P_NONE
+ P_LOCAL, P_GLOBAL, P_NONE
} parm_class;
struct enum_list {
#endif
/* some helpful bits */
-#define pSERVICE(i) ServicePtrs[i]
-#define iSERVICE(i) (*pSERVICE(i))
-#define LP_SNUM_OK(iService) (((iService) >= 0) && ((iService) < iNumServices))
+#define iSECTION(i) ((section*)section_list.items)[i]
+#define LP_SNUM_OK(i) ((i) >= 0 && (i) < (int)section_list.count)
+#define SECTION_PTR(s, p) (((char*)(s)) + (ptrdiff_t)(((char *)(p)) - (char *)&sDefault))
/*
* This structure describes global (ie., server-wide) parameters.
static global Globals;
/*
- * This structure describes a single service. Their order must match the
+ * This structure describes a single section. Their order must match the
* initializers below, which you can accomplish by keeping each sub-section
* sorted. (e.g. in vim, just visually select each subsection and use !sort.)
*/
BOOL transfer_logging;
BOOL use_chroot;
BOOL write_only;
-} service;
+} section;
+
+typedef struct {
+ global g;
+ section s;
+} global_and_section;
-/* This is a default service used to prime a services structure. In order
+/* 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
* trailing ';' (to avoid a sorting problem with trailing digits). */
-static service sDefault = {
+static section sDefault = {
/* auth_users; */ NULL,
/* charset; */ NULL,
/* comment; */ NULL,
};
/* local variables */
-static service **ServicePtrs = NULL;
-static int iNumServices = 0;
-static int iServiceIndex = 0;
+static item_list section_list = EMPTY_ITEM_LIST;
+static item_list section_stack = EMPTY_ITEM_LIST;
+static int iSectionIndex = -1;
static BOOL bInGlobalSection = True;
#define NUMPARAMETERS (sizeof (parm_table) / sizeof (struct parm_struct))
int fn_name(void) {return *(int *)(ptr);}
#define FN_LOCAL_STRING(fn_name, val) \
- char *fn_name(int i) {return LP_SNUM_OK(i) && pSERVICE(i)->val? pSERVICE(i)->val : (sDefault.val? sDefault.val : "");}
+ char *fn_name(int i) {return LP_SNUM_OK(i) && iSECTION(i).val? iSECTION(i).val : (sDefault.val? sDefault.val : "");}
#define FN_LOCAL_BOOL(fn_name, val) \
- BOOL fn_name(int i) {return LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val;}
+ BOOL fn_name(int i) {return LP_SNUM_OK(i)? iSECTION(i).val : sDefault.val;}
#define FN_LOCAL_CHAR(fn_name, val) \
- char fn_name(int i) {return LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val;}
+ char fn_name(int i) {return LP_SNUM_OK(i)? iSECTION(i).val : sDefault.val;}
#define FN_LOCAL_INTEGER(fn_name, val) \
- int fn_name(int i) {return LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val;}
+ int fn_name(int i) {return LP_SNUM_OK(i)? iSECTION(i).val : sDefault.val;}
FN_GLOBAL_STRING(lp_bind_address, &Globals.bind_address)
FN_GLOBAL_STRING(lp_motd_file, &Globals.motd_file)
exit_cleanup(RERR_MALLOC);
}
-/* Copy a service structure to another. */
-static void copy_service(service *pserviceDest, service *pserviceSource)
+/* Copy a section structure to another. */
+static void copy_section(section *psectionDest, section *psectionSource)
{
int i;
for (i = 0; parm_table[i].label; i++) {
if (parm_table[i].ptr && parm_table[i].class == P_LOCAL) {
void *def_ptr = parm_table[i].ptr;
- void *src_ptr = ((char *)pserviceSource) + PTR_DIFF(def_ptr, &sDefault);
- void *dest_ptr = ((char *)pserviceDest) + PTR_DIFF(def_ptr, &sDefault);
+ void *src_ptr = SECTION_PTR(psectionSource, def_ptr);
+ void *dest_ptr = SECTION_PTR(psectionDest, def_ptr);
switch (parm_table[i].type) {
case P_BOOL:
}
}
-/* Initialise a service to the defaults. */
-static void init_service(service *pservice)
+/* Initialise a section to the defaults. */
+static void init_section(section *psection)
{
- memset((char *)pservice, 0, sizeof (service));
- copy_service(pservice, &sDefault);
+ memset((char *)psection, 0, sizeof (section));
+ copy_section(psection, &sDefault);
}
/* Do a case-insensitive, whitespace-ignoring string compare. */
return *psz1 - *psz2;
}
-/* Find a service by name. Otherwise works like get_service. */
-static int getservicebyname(char *name, service *pserviceDest)
+/* Find a section by name. Otherwise works like get_section. */
+static int getsectionbyname(char *name, section *psectionDest)
{
int i;
- for (i = iNumServices - 1; i >= 0; i--) {
- if (strwicmp(iSERVICE(i).name, name) == 0) {
- if (pserviceDest != NULL)
- copy_service(pserviceDest, pSERVICE(i));
+ for (i = section_list.count - 1; i >= 0; i--) {
+ if (strwicmp(iSECTION(i).name, name) == 0) {
+ if (psectionDest != NULL)
+ copy_section(psectionDest, &iSECTION(i));
break;
}
}
return i;
}
-/* Add a new service to the services array, with defaults set. */
-static int add_a_service(char *name)
+/* Add a new section to the sections array w/the default values. */
+static int add_a_section(char *name)
{
int i;
- int num_to_alloc = iNumServices+1;
+ section *s;
/* it might already exist */
if (name) {
- i = getservicebyname(name, NULL);
+ i = getsectionbyname(name, NULL);
if (i >= 0)
return i;
}
- i = iNumServices;
- ServicePtrs = realloc_array(ServicePtrs, service *, num_to_alloc);
-
- if (ServicePtrs)
- pSERVICE(iNumServices) = new(service);
-
- if (!ServicePtrs || !pSERVICE(iNumServices))
- return -1;
-
- iNumServices++;
+ i = section_list.count;
+ s = EXPAND_ITEM_LIST(§ion_list, section, 2);
- init_service(pSERVICE(i));
+ init_section(s);
if (name)
- string_set(&iSERVICE(i).name, name);
+ string_set(&s->name, name);
return i;
}
static BOOL do_parameter(char *parmname, char *parmvalue)
{
int parmnum, i;
- void *parm_ptr=NULL; /* where we are going to store the result */
- void *def_ptr=NULL;
+ void *parm_ptr; /* where we are going to store the result */
+ void *def_ptr;
char *cp;
parmnum = map_parameter(parmname);
parm_ptr = def_ptr;
else {
if (parm_table[parmnum].class == P_GLOBAL) {
- rprintf(FLOG, "Global parameter %s found in service section!\n", parmname);
+ rprintf(FLOG, "Global parameter %s found in module section!\n", parmname);
return True;
}
- parm_ptr = ((char *)pSERVICE(iServiceIndex)) + PTR_DIFF(def_ptr, &sDefault);
+ parm_ptr = SECTION_PTR(&iSECTION(iSectionIndex), def_ptr);
}
/* now switch on the type of variable it is */
string_set(parm_ptr, parmvalue);
break;
- case P_GSTRING:
- strlcpy((char *)parm_ptr, parmvalue, sizeof (pstring));
- break;
-
case P_ENUM:
- for (i=0;parm_table[parmnum].enum_list[i].name;i++) {
+ for (i=0; parm_table[parmnum].enum_list[i].name; i++) {
if (strequal(parmvalue, parm_table[parmnum].enum_list[i].name)) {
*(int *)parm_ptr = parm_table[parmnum].enum_list[i].value;
break;
*(int *)parm_ptr = atoi(parmvalue);
}
break;
- case P_SEP:
- break;
}
return True;
* 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)
+ if (bInGlobalSection && !isglobal) {
+ if (!section_list.count)
+ set_dparams(0);
init_locals();
+ }
/* if we've just struck a global section, note the fact. */
bInGlobalSection = isglobal;
return True;
#if 0
- /* If we have a current service, tidy it up before moving on. */
- if (iServiceIndex >= 0) {
+ /* If we have a current section, tidy it up before moving on. */
+ if (iSectionIndex >= 0) {
/* Add any tidy work as needed ... */
if (problem)
return False;
return False;
}
- if ((iServiceIndex = add_a_service(sectionname)) < 0) {
+ if ((iSectionIndex = add_a_section(sectionname)) < 0) {
rprintf(FLOG, "Failed to add a new module\n");
bInGlobalSection = True;
return False;
return True;
}
-/* Load the services array from the services file. Return True on success,
+/* 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;
-
bInGlobalSection = True;
init_globals();
- pstrcpy(n2, pszFname);
+ /* We get sections first, so have to start 'behind' to make up. */
+ iSectionIndex = -1;
+ return pm_process(pszFname, globals_only ? NULL : do_section, do_parameter);
+}
+
+BOOL set_dparams(int syntax_check_only)
+{
+ char *equal, *val, **params = dparam_list.items;
+ unsigned j;
+
+ for (j = 0; j < dparam_list.count; j++) {
+ equal = strchr(params[j], '='); /* options.c verified this */
+ *equal = '\0';
+ if (syntax_check_only) {
+ if (map_parameter(params[j]) < 0) {
+ rprintf(FCLIENT, "Unknown parameter \"%s\"\n", params[j]);
+ *equal = '=';
+ return False;
+ }
+ } else {
+ for (val = equal+1; isSpace(val); val++) {}
+ do_parameter(params[j], val);
+ }
+ *equal = '=';
+ }
- /* We get sections first, so have to start 'behind' to make up */
- iServiceIndex = -1;
- return pm_process(n2, globals_only ? NULL : do_section, do_parameter);
+ return True;
}
-/* Return the max number of services. */
-int lp_numservices(void)
+/* Return the max number of modules (sections). */
+int lp_num_modules(void)
{
- return iNumServices;
+ return section_list.count;
}
-/* Return the number of the service with the given name, or -1 if it doesn't
+/* Return the number of the module with the given name, or -1 if it doesn't
* exist. Note that this is a DIFFERENT ANIMAL from the internal function
- * getservicebyname()! This works ONLY if all services have been loaded,
- * and does not copy the found service. */
+ * getsectionbyname()! This works ONLY if all sections have been loaded,
+ * and does not copy the found section. */
int lp_number(char *name)
{
int i;
- for (i = iNumServices - 1; i >= 0; i--) {
+ for (i = section_list.count - 1; i >= 0; i--) {
if (strcmp(lp_name(i), name) == 0)
break;
}