s4-param Allow +foo syntax in smb.conf list parsing
authorAndrew Bartlett <abartlet@samba.org>
Wed, 8 Dec 2010 05:27:38 +0000 (16:27 +1100)
committerAndrew Bartlett <abartlet@samba.org>
Wed, 8 Dec 2010 08:39:06 +0000 (09:39 +0100)
The idea here is to allow an smb.conf file to work from the defaults,
rather than override them.  For example, 'server services = +openchange'.

Pair-Programmed-With: Andrew Tridgell <tridge@samba.org>

Autobuild-User: Andrew Bartlett <abartlet@samba.org>
Autobuild-Date: Wed Dec  8 09:39:06 CET 2010 on sn-devel-104

source4/param/loadparm.c
source4/param/loadparm.h
source4/param/pyparam.c
source4/scripting/bin/samba_dnsupdate

index 55cb45eaedef0433d8be428717c7afc25e8a8d2f..fa3b591df08a324fba6393824bfcd30be76c1d12 100644 (file)
@@ -188,7 +188,7 @@ struct loadparm_global
        const char **szRNDCCommand;
        const char **szDNSUpdateCommand;
        const char **szSPNUpdateCommand;
-       char *szNSUpdateCommand;
+       const char **szNSUpdateCommand;
        struct parmlist_entry *param_opt;
 };
 
@@ -505,10 +505,10 @@ static struct parm_struct parm_table[] = {
        {"idmap trusted only", P_BOOL, P_GLOBAL, GLOBAL_VAR(bIdmapTrustedOnly), NULL, NULL},
 
        {"ntp signd socket directory", P_STRING, P_GLOBAL, GLOBAL_VAR(szNTPSignDSocketDirectory), NULL, NULL },
-       {"rndc command", P_LIST, P_GLOBAL, GLOBAL_VAR(szRNDCCommand), NULL, NULL },
-       {"dns update command", P_LIST, P_GLOBAL, GLOBAL_VAR(szDNSUpdateCommand), NULL, NULL },
-       {"spn update command", P_LIST, P_GLOBAL, GLOBAL_VAR(szSPNUpdateCommand), NULL, NULL },
-       {"nsupdate command", P_STRING, P_GLOBAL, GLOBAL_VAR(szNSUpdateCommand), NULL, NULL },
+       {"rndc command", P_CMDLIST, P_GLOBAL, GLOBAL_VAR(szRNDCCommand), NULL, NULL },
+       {"dns update command", P_CMDLIST, P_GLOBAL, GLOBAL_VAR(szDNSUpdateCommand), NULL, NULL },
+       {"spn update command", P_CMDLIST, P_GLOBAL, GLOBAL_VAR(szSPNUpdateCommand), NULL, NULL },
+       {"nsupdate command", P_CMDLIST, P_GLOBAL, GLOBAL_VAR(szNSUpdateCommand), NULL, NULL },
 
        {NULL, P_BOOL, P_NONE, 0, NULL, NULL}
 };
@@ -678,7 +678,7 @@ FN_GLOBAL_STRING(piddir, szPidDir)
 FN_GLOBAL_LIST(rndc_command, szRNDCCommand)
 FN_GLOBAL_LIST(dns_update_command, szDNSUpdateCommand)
 FN_GLOBAL_LIST(spn_update_command, szSPNUpdateCommand)
-FN_GLOBAL_STRING(nsupdate_command, szNSUpdateCommand)
+FN_GLOBAL_LIST(nsupdate_command, szNSUpdateCommand)
 FN_GLOBAL_LIST(dcerpc_endpoint_servers, dcerpc_ep_servers)
 FN_GLOBAL_LIST(server_services, server_services)
 FN_GLOBAL_STRING(ntptr_providor, ntptr_providor)
@@ -1682,11 +1682,40 @@ static bool set_variable(TALLOC_CTX *mem_ctx, int parmnum, void *parm_ptr,
                        return false;
                }
 
-               case P_LIST:
+               case P_CMDLIST:
                        *(const char ***)parm_ptr = (const char **)str_list_make(mem_ctx,
                                                                  pszParmValue, NULL);
                        break;
+               case P_LIST:
+               {
+                       char **new_list = str_list_make(mem_ctx,
+                                                       pszParmValue, NULL);
+                       for (i=0; new_list[i]; i++) {
+                               if (new_list[i][0] == '+' && new_list[i][1]) {
+                                       *(const char ***)parm_ptr = str_list_add(*(const char ***)parm_ptr,
+                                                                                &new_list[i][1]);
+                               } else if (new_list[i][0] == '-' && new_list[i][1]) {
+                                       if (!str_list_check(*(const char ***)parm_ptr,
+                                                           &new_list[i][1])) {
+                                               DEBUG(0, ("Unsupported value for: %s = %s, %s is not in the original list\n",
+                                                         pszParmName, pszParmValue, new_list[i]));
+                                               return false;
 
+                                       }
+                                       str_list_remove(*(const char ***)parm_ptr,
+                                                       &new_list[i][1]);
+                               } else {
+                                       if (i != 0) {
+                                               DEBUG(0, ("Unsupported list syntax for: %s = %s\n",
+                                                         pszParmName, pszParmValue));
+                                               return false;
+                                       }
+                                       *(const char ***)parm_ptr = new_list;
+                                       break;
+                               }
+                       }
+                       break;
+               }
                case P_STRING:
                        string_set(mem_ctx, (char **)parm_ptr, pszParmValue);
                        break;
@@ -1918,6 +1947,7 @@ bool lpcfg_set_option(struct loadparm_context *lp_ctx, const char *option)
 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
 {
        int i;
+       const char *list_sep = ", "; /* For the seperation of lists values that we print below */
        switch (p->type)
        {
                case P_ENUM:
@@ -1943,13 +1973,20 @@ static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
                        fprintf(f, "0%o", *(int *)ptr);
                        break;
 
+               case P_CMDLIST:
+                       list_sep = " ";
+                       /* fall through */
                case P_LIST:
                        if ((char ***)ptr && *(char ***)ptr) {
                                char **list = *(char ***)ptr;
 
-                               for (; *list; list++)
-                                       fprintf(f, "%s%s", *list,
-                                               ((*(list+1))?", ":""));
+                               for (; *list; list++) {
+                                       if (*(list+1) == NULL) {
+                                               /* last item, print no extra seperator after */
+                                               list_sep = "";
+                                       }
+                                       fprintf(f, "%s%s", *list, list_sep);
+                               }
                        }
                        break;
 
@@ -1978,6 +2015,7 @@ static bool equal_parameter(parm_type type, void *ptr1, void *ptr2)
                case P_ENUM:
                        return (*((int *)ptr1) == *((int *)ptr2));
 
+               case P_CMDLIST:
                case P_LIST:
                        return str_list_equal((const char **)(*(char ***)ptr1),
                                              (const char **)(*(char ***)ptr2));
@@ -2055,6 +2093,7 @@ static bool is_default(struct loadparm_service *sDefault, int i)
        if (!defaults_saved)
                return false;
        switch (parm_table[i].type) {
+               case P_CMDLIST:
                case P_LIST:
                        return str_list_equal((const char **)parm_table[i].def.lvalue, 
                                              (const char **)def_ptr);
index 454d3f885347ad9a648b4b06acf7b897e42ed435..7a76321b06e09c8d40dff9223f4f02b5f38398a4 100644 (file)
@@ -29,7 +29,7 @@
 
 /* the following are used by loadparm for option lists */
 typedef enum {
-       P_BOOL,P_INTEGER,P_OCTAL,P_BYTES,P_LIST,P_STRING,P_USTRING,P_ENUM
+       P_BOOL,P_INTEGER,P_OCTAL,P_BYTES,P_LIST,P_CMDLIST,P_STRING,P_USTRING,P_ENUM
 } parm_type;
 
 typedef enum {
index 4e4d0410a5a63e4dad661962b43d9a5c988ae472..fb7ff88cfc220be281c0cd97ee5acc71e842ff87 100644 (file)
@@ -119,6 +119,7 @@ static PyObject *py_lp_ctx_get_helper(struct loadparm_context *lp_ctx, const cha
            }
        }
        return NULL;
+    case P_CMDLIST:
     case P_LIST: 
        {
            int j;
index faba1243361d7a83f3c70ab2074fbb2d5971fc1e..cacdc36194f7e06be26c7808c61f560b8a52f335 100755 (executable)
@@ -261,8 +261,9 @@ def call_nsupdate(d):
 
     os.putenv("KRB5CCNAME", ccachename)
     try:
-        cmd = "%s %s" % (nsupdate_cmd, tmpfile)
-        subprocess.check_call(cmd, shell=True)
+        cmd = nsupdate_cmd[:]
+        cmd.append(tmpfile)
+        subprocess.check_call(cmd, shell=False)
     except Exception, estr:
         global error_count
         if opts.fail_immediately: