Added &include and &merge config-file directives that allow the
[rsync/rsync.git] / loadparm.c
index 62712fd..4b3741f 100644 (file)
@@ -87,9 +87,8 @@ struct parm_struct {
 #endif
 
 /* some helpful bits */
-#define pSECTION(i) SectionPtrs[i]
-#define iSECTION(i) (*pSECTION(i))
-#define LP_SNUM_OK(i) ((i) >= 0 && (i) < iNumSections)
+#define iSECTION(i) ((section*)section_list.items)[i]
+#define LP_SNUM_OK(i) ((i) >= 0 && (i) < (int)section_list.count)
 
 /*
  * This structure describes global (ie., server-wide) parameters.
@@ -155,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,8 +209,8 @@ static section sDefault = {
 };
 
 /* local variables */
-static section **SectionPtrs = NULL;
-static int iNumSections = 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;
 
@@ -516,10 +520,10 @@ static int getsectionbyname(char *name, section *psectionDest)
 {
        int i;
 
-       for (i = iNumSections - 1; i >= 0; i--) {
+       for (i = section_list.count - 1; i >= 0; i--) {
                if (strwicmp(iSECTION(i).name, name) == 0) {
                        if (psectionDest != NULL)
-                               copy_section(psectionDest, pSECTION(i));
+                               copy_section(psectionDest, &iSECTION(i));
                        break;
                }
        }
@@ -531,7 +535,7 @@ static int getsectionbyname(char *name, section *psectionDest)
 static int add_a_section(char *name)
 {
        int i;
-       int num_to_alloc = iNumSections+1;
+       section *s;
 
        /* it might already exist */
        if (name) {
@@ -540,20 +544,12 @@ static int add_a_section(char *name)
                        return i;
        }
 
-       i = iNumSections;
-       SectionPtrs = realloc_array(SectionPtrs, section *, num_to_alloc);
-
-       if (SectionPtrs)
-               pSECTION(iNumSections) = new(section);
-
-       if (!SectionPtrs || !pSECTION(iNumSections))
-               return -1;
-
-       iNumSections++;
+       i = section_list.count;
+       s = EXPAND_ITEM_LIST(&section_list, section, 2);
 
-       init_section(pSECTION(i));
+       init_section(s);
        if (name)
-               string_set(&iSECTION(i).name, name);
+               string_set(&s->name, name);
 
        return i;
 }
@@ -620,7 +616,7 @@ static BOOL do_parameter(char *parmname, char *parmvalue)
                        rprintf(FLOG, "Global parameter %s found in module section!\n", parmname);
                        return True;
                }
-               parm_ptr = ((char *)pSECTION(iSectionIndex)) + PTR_DIFF(def_ptr, &sDefault);
+               parm_ptr = ((char *)&iSECTION(iSectionIndex)) + PTR_DIFF(def_ptr, &sDefault);
        }
 
        /* now switch on the type of variable it is */
@@ -686,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(&section_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)
@@ -724,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;
 
@@ -742,7 +760,7 @@ BOOL lp_load(char *pszFname, int globals_only)
 /* Return the max number of modules (sections). */
 int lp_num_modules(void)
 {
-       return iNumSections;
+       return section_list.count;
 }
 
 /* Return the number of the module with the given name, or -1 if it doesn't
@@ -753,7 +771,7 @@ int lp_number(char *name)
 {
        int i;
 
-       for (i = iNumSections - 1; i >= 0; i--) {
+       for (i = section_list.count - 1; i >= 0; i--) {
                if (strcmp(lp_name(i), name) == 0)
                        break;
        }