param: Add non-global smb.cfg option (support 2 different smb.confs)
[nivanova/samba-autobuild/.git] / source4 / param / pyparam.c
index 4e4d0410a5a63e4dad661962b43d9a5c988ae472..11257c356aa2150404ea9f43f0b92ee73b06f95a 100644 (file)
 */
 
 #include <Python.h>
+#include "python/py3compat.h"
 #include "includes.h"
 #include "param/param.h"
 #include "param/loadparm.h"
-#include "lib/talloc/pytalloc.h"
+#include <pytalloc.h>
+#include "dynconfig/dynconfig.h"
 
-/* There's no Py_ssize_t in 2.4, apparently */
-#if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 5
-typedef int Py_ssize_t;
-typedef inquiry lenfunc;
-#endif
-
-#define PyLoadparmContext_AsLoadparmContext(obj) py_talloc_get_type(obj, struct loadparm_context)
-#define PyLoadparmService_AsLoadparmService(obj) py_talloc_get_type(obj, struct loadparm_service)
+#define PyLoadparmContext_AsLoadparmContext(obj) pytalloc_get_type(obj, struct loadparm_context)
+#define PyLoadparmService_AsLoadparmService(obj) pytalloc_get_type(obj, struct loadparm_service)
 
 extern PyTypeObject PyLoadparmContext;
 extern PyTypeObject PyLoadparmService;
 
-PyObject *PyLoadparmService_FromService(struct loadparm_service *service)
+static PyObject *PyLoadparmService_FromService(struct loadparm_service *service)
 {
-       return py_talloc_reference(&PyLoadparmService, service);
+       return pytalloc_reference(&PyLoadparmService, service);
 }
 
 static PyObject *py_lp_ctx_get_helper(struct loadparm_context *lp_ctx, const char *service_name, const char *param_name)
@@ -67,11 +63,11 @@ static PyObject *py_lp_ctx_get_helper(struct loadparm_context *lp_ctx, const cha
                        if (value == NULL) {
                        return NULL;
                        }
-                       return PyString_FromString(value);
+                       return PyStr_FromString(value);
                }
 
-               parm = lpcfg_parm_struct(param_name);
-               if (parm == NULL || parm->pclass == P_GLOBAL) {
+               parm = lpcfg_parm_struct(lp_ctx, param_name);
+               if (parm == NULL || parm->p_class == P_GLOBAL) {
                        return NULL;
                }
                parm_ptr = lpcfg_parm_ptr(lp_ctx, service, parm);
@@ -87,10 +83,10 @@ static PyObject *py_lp_ctx_get_helper(struct loadparm_context *lp_ctx, const cha
                value = lpcfg_get_parametric(lp_ctx, NULL, type, option);
                if (value == NULL)
                        return NULL;
-               return PyString_FromString(value);
+               return PyStr_FromString(value);
        } else {
                /* its a global parameter */
-               parm = lpcfg_parm_struct(param_name);
+               parm = lpcfg_parm_struct(lp_ctx, param_name);
                if (parm == NULL) {
                        return NULL;
                }
@@ -103,11 +99,15 @@ static PyObject *py_lp_ctx_get_helper(struct loadparm_context *lp_ctx, const cha
 
     /* construct and return the right type of python object */
     switch (parm->type) {
+    case P_CHAR:
+       return PyStr_FromFormat("%c", *(char *)parm_ptr);
     case P_STRING:
     case P_USTRING:
-       return PyString_FromString(*(char **)parm_ptr);
+       return PyStr_FromString(*(char **)parm_ptr);
     case P_BOOL:
        return PyBool_FromLong(*(bool *)parm_ptr);
+    case P_BOOLREV:
+       return PyBool_FromLong(!(*(bool *)parm_ptr));
     case P_INTEGER:
     case P_OCTAL:
     case P_BYTES:
@@ -115,34 +115,33 @@ static PyObject *py_lp_ctx_get_helper(struct loadparm_context *lp_ctx, const cha
     case P_ENUM:
        for (i=0; parm->enum_list[i].name; i++) {
            if (*(int *)parm_ptr == parm->enum_list[i].value) {
-               return PyString_FromString(parm->enum_list[i].name);
+               return PyStr_FromString(parm->enum_list[i].name);
            }
        }
        return NULL;
+    case P_CMDLIST:
     case P_LIST: 
        {
            int j;
            const char **strlist = *(const char ***)parm_ptr;
            PyObject *pylist;
                
-               if(strlist == NULL) {
-                       return PyList_New(0);
-               }
+           if(strlist == NULL) {
+                   return PyList_New(0);
+           }
                
-               pylist = PyList_New(str_list_length(strlist));
+           pylist = PyList_New(str_list_length(strlist));
            for (j = 0; strlist[j]; j++) 
                PyList_SetItem(pylist, j, 
-                              PyString_FromString(strlist[j]));
+                              PyStr_FromString(strlist[j]));
            return pylist;
        }
-
-       break;
     }
     return NULL;
 
 }
 
-static PyObject *py_lp_ctx_load(py_talloc_Object *self, PyObject *args)
+static PyObject *py_lp_ctx_load(PyObject *self, PyObject *args)
 {
        char *filename;
        bool ret;
@@ -158,7 +157,7 @@ static PyObject *py_lp_ctx_load(py_talloc_Object *self, PyObject *args)
        Py_RETURN_NONE;
 }
 
-static PyObject *py_lp_ctx_load_default(py_talloc_Object *self)
+static PyObject *py_lp_ctx_load_default(PyObject *self, PyObject *unused)
 {
        bool ret;
         ret = lpcfg_load_default(PyLoadparmContext_AsLoadparmContext(self));
@@ -170,7 +169,7 @@ static PyObject *py_lp_ctx_load_default(py_talloc_Object *self)
        Py_RETURN_NONE;
 }
 
-static PyObject *py_lp_ctx_get(py_talloc_Object *self, PyObject *args)
+static PyObject *py_lp_ctx_get(PyObject *self, PyObject *args)
 {
        char *param_name;
        char *section_name = NULL;
@@ -184,7 +183,7 @@ static PyObject *py_lp_ctx_get(py_talloc_Object *self, PyObject *args)
        return ret;
 }
 
-static PyObject *py_lp_ctx_is_myname(py_talloc_Object *self, PyObject *args)
+static PyObject *py_lp_ctx_is_myname(PyObject *self, PyObject *args)
 {
        char *name;
        if (!PyArg_ParseTuple(args, "s", &name))
@@ -193,7 +192,7 @@ static PyObject *py_lp_ctx_is_myname(py_talloc_Object *self, PyObject *args)
        return PyBool_FromLong(lpcfg_is_myname(PyLoadparmContext_AsLoadparmContext(self), name));
 }
 
-static PyObject *py_lp_ctx_is_mydomain(py_talloc_Object *self, PyObject *args)
+static PyObject *py_lp_ctx_is_mydomain(PyObject *self, PyObject *args)
 {
        char *name;
        if (!PyArg_ParseTuple(args, "s", &name))
@@ -202,7 +201,7 @@ static PyObject *py_lp_ctx_is_mydomain(py_talloc_Object *self, PyObject *args)
        return PyBool_FromLong(lpcfg_is_mydomain(PyLoadparmContext_AsLoadparmContext(self), name));
 }
 
-static PyObject *py_lp_ctx_set(py_talloc_Object *self, PyObject *args)
+static PyObject *py_lp_ctx_set(PyObject *self, PyObject *args)
 {
        char *name, *value;
        bool ret;
@@ -218,21 +217,21 @@ static PyObject *py_lp_ctx_set(py_talloc_Object *self, PyObject *args)
        Py_RETURN_NONE;
 }
 
-static PyObject *py_lp_ctx_private_path(py_talloc_Object *self, PyObject *args)
+static PyObject *py_lp_ctx_private_path(PyObject *self, PyObject *args)
 {
        char *name, *path;
        PyObject *ret;
        if (!PyArg_ParseTuple(args, "s", &name))
                return NULL;
 
-       path = private_path(NULL, PyLoadparmContext_AsLoadparmContext(self), name);
-       ret = PyString_FromString(path);
+       path = lpcfg_private_path(NULL, PyLoadparmContext_AsLoadparmContext(self), name);
+       ret = PyStr_FromString(path);
        talloc_free(path);
 
        return ret;
 }
 
-static PyObject *py_lp_ctx_services(py_talloc_Object *self)
+static PyObject *py_lp_ctx_services(PyObject *self, PyObject *unused)
 {
        struct loadparm_context *lp_ctx = PyLoadparmContext_AsLoadparmContext(self);
        PyObject *ret;
@@ -241,74 +240,200 @@ static PyObject *py_lp_ctx_services(py_talloc_Object *self)
        for (i = 0; i < lpcfg_numservices(lp_ctx); i++) {
                struct loadparm_service *service = lpcfg_servicebynum(lp_ctx, i);
                if (service != NULL) {
-                       PyList_SetItem(ret, i, PyString_FromString(lpcfg_servicename(service)));
+                       PyList_SetItem(ret, i, PyStr_FromString(lpcfg_servicename(service)));
                }
        }
        return ret;
 }
 
+static PyObject *py_lp_ctx_server_role(PyObject *self, PyObject *unused)
+{
+       struct loadparm_context *lp_ctx = PyLoadparmContext_AsLoadparmContext(self);
+       uint32_t role;
+       const char *role_str;
+
+       role = lpcfg_server_role(lp_ctx);
+       role_str = server_role_str(role);
+
+       return PyStr_FromString(role_str);
+}
+
 static PyObject *py_lp_dump(PyObject *self, PyObject *args)
 {
-       PyObject *py_stream;
        bool show_defaults = false;
+       const char *file_name = "";
+       const char *mode = "w";
        FILE *f;
        struct loadparm_context *lp_ctx = PyLoadparmContext_AsLoadparmContext(self);
 
-       if (!PyArg_ParseTuple(args, "O|b", &py_stream, &show_defaults))
+       if (!PyArg_ParseTuple(args, "|bss", &show_defaults, &file_name, &mode))
                return NULL;
 
-       f = PyFile_AsFile(py_stream);
+       if (file_name[0] == '\0') {
+               f = stdout;
+       } else {
+               f = fopen(file_name, mode);
+       }
+
        if (f == NULL) {
-               PyErr_SetString(PyExc_TypeError, "Not a file stream");
+               PyErr_SetFromErrno(PyExc_IOError);
                return NULL;
        }
 
        lpcfg_dump(lp_ctx, f, show_defaults, lpcfg_numservices(lp_ctx));
 
+       if (f != stdout) {
+               fclose(f);
+       }
+
        Py_RETURN_NONE;
 }
 
+static PyObject *py_lp_dump_a_parameter(PyObject *self, PyObject *args)
+{
+       char *param_name;
+       const char *section_name = NULL;
+       const char *file_name = "";
+       const char *mode = "w";
+       FILE *f;
+       struct loadparm_context *lp_ctx = PyLoadparmContext_AsLoadparmContext(self);
+       struct loadparm_service *service;
+       bool ret;
+
+       if (!PyArg_ParseTuple(args, "s|zss", &param_name, &section_name, &file_name, &mode))
+               return NULL;
+
+       if (file_name[0] == '\0') {
+               f = stdout;
+       } else {
+               f = fopen(file_name, mode);
+       }
+
+       if (f == NULL) {
+               return NULL;
+       }
+
+       if (section_name != NULL && strwicmp(section_name, GLOBAL_NAME) &&
+               strwicmp(section_name, GLOBAL_NAME2)) {
+               /* it's a share parameter */
+               service = lpcfg_service(lp_ctx, section_name);
+               if (service == NULL) {
+                       PyErr_Format(PyExc_RuntimeError, "Unknown section %s", section_name);
+                       return NULL;
+               }
+       } else {
+               /* it's global */
+               service = NULL;
+               section_name = "global";
+       }
+
+       ret = lpcfg_dump_a_parameter(lp_ctx, service, param_name, f);
+
+       if (!ret) {
+               PyErr_Format(PyExc_RuntimeError, "Parameter %s unknown for section %s", param_name, section_name);
+               if (f != stdout) {
+                       fclose(f);
+               }
+               return NULL;
+       }
+
+       if (f != stdout) {
+               fclose(f);
+       }
+
+       Py_RETURN_NONE;
+
+}
+
+static PyObject *py_lp_log_level(PyObject *self, PyObject *unused)
+{
+       int ret = DEBUGLEVEL_CLASS[DBGC_CLASS];
+       return PyInt_FromLong(ret);
+}
+
+
+static PyObject *py_samdb_url(PyObject *self, PyObject *unused)
+{
+       struct loadparm_context *lp_ctx = PyLoadparmContext_AsLoadparmContext(self);
+       return PyStr_FromFormat("tdb://%s/sam.ldb", lpcfg_private_dir(lp_ctx));
+}
+
+static PyObject *py_cache_path(PyObject *self, PyObject *args)
+{
+       struct loadparm_context *lp_ctx = PyLoadparmContext_AsLoadparmContext(self);
+       char *name = NULL;
+       char *path = NULL;
+       PyObject *ret = NULL;
+
+       if (!PyArg_ParseTuple(args, "s", &name)) {
+               return NULL;
+       }
+
+       path = lpcfg_cache_path(NULL, lp_ctx, name);
+       if (!path) {
+               PyErr_Format(PyExc_RuntimeError,
+                            "Unable to access cache %s", name);
+               return NULL;
+       }
+       ret = PyStr_FromString(path);
+       talloc_free(path);
+
+       return ret;
+}
 
 static PyMethodDef py_lp_ctx_methods[] = {
-       { "load", (PyCFunction)py_lp_ctx_load, METH_VARARGS, 
+       { "load", py_lp_ctx_load, METH_VARARGS,
                "S.load(filename) -> None\n"
                "Load specified file." },
-       { "load_default", (PyCFunction)py_lp_ctx_load_default, METH_NOARGS,
+       { "load_default", py_lp_ctx_load_default, METH_NOARGS,
                "S.load_default() -> None\n"
                "Load default smb.conf file." },
-       { "is_myname", (PyCFunction)py_lp_ctx_is_myname, METH_VARARGS,
+       { "is_myname", py_lp_ctx_is_myname, METH_VARARGS,
                "S.is_myname(name) -> bool\n"
                "Check whether the specified name matches one of our netbios names." },
-       { "is_mydomain", (PyCFunction)py_lp_ctx_is_mydomain, METH_VARARGS,
+       { "is_mydomain", py_lp_ctx_is_mydomain, METH_VARARGS,
                "S.is_mydomain(name) -> bool\n"
                "Check whether the specified name matches our domain name." },
-       { "get", (PyCFunction)py_lp_ctx_get, METH_VARARGS,
+       { "get", py_lp_ctx_get, METH_VARARGS,
                "S.get(name, service_name) -> value\n"
                "Find specified parameter." },
-       { "set", (PyCFunction)py_lp_ctx_set, METH_VARARGS,
+       { "set", py_lp_ctx_set, METH_VARARGS,
                "S.set(name, value) -> bool\n"
                "Change a parameter." },
-       { "private_path", (PyCFunction)py_lp_ctx_private_path, METH_VARARGS,
+       { "private_path", py_lp_ctx_private_path, METH_VARARGS,
                "S.private_path(name) -> path\n" },
-       { "services", (PyCFunction)py_lp_ctx_services, METH_NOARGS,
+       { "services", py_lp_ctx_services, METH_NOARGS,
                "S.services() -> list" },
-       { "dump", (PyCFunction)py_lp_dump, METH_VARARGS, 
-               "S.dump(stream, show_defaults=False)" },
+       { "server_role", py_lp_ctx_server_role, METH_NOARGS,
+               "S.server_role() -> value\n"
+               "Get the server role." },
+       { "dump", py_lp_dump, METH_VARARGS,
+               "S.dump(show_defaults=False, file_name='', mode='w')" },
+       { "dump_a_parameter", py_lp_dump_a_parameter, METH_VARARGS,
+               "S.dump_a_parameter(name, service_name, file_name='', mode='w')" },
+       { "log_level", py_lp_log_level, METH_NOARGS,
+               "S.log_level() -> int\n Get the active log level" },
+       { "samdb_url", py_samdb_url, METH_NOARGS,
+               "S.samdb_url() -> string\n"
+               "Returns the current URL for sam.ldb." },
+       { "cache_path", py_cache_path, METH_VARARGS,
+               "S.cache_path(name) -> string\n"
+               "Returns a path in the Samba cache directory." },
        { NULL }
 };
 
-static PyObject *py_lp_ctx_default_service(py_talloc_Object *self, void *closure)
+static PyObject *py_lp_ctx_default_service(PyObject *self, void *closure)
 {
        return PyLoadparmService_FromService(lpcfg_default_service(PyLoadparmContext_AsLoadparmContext(self)));
 }
 
-static PyObject *py_lp_ctx_config_file(py_talloc_Object *self, void *closure)
+static PyObject *py_lp_ctx_config_file(PyObject *self, void *closure)
 {
        const char *configfile = lpcfg_configfile(PyLoadparmContext_AsLoadparmContext(self));
        if (configfile == NULL)
                Py_RETURN_NONE;
        else
-               return PyString_FromString(configfile);
+               return PyStr_FromString(configfile);
 }
 
 static PyGetSetDef py_lp_ctx_getset[] = {
@@ -320,33 +445,67 @@ static PyGetSetDef py_lp_ctx_getset[] = {
 
 static PyObject *py_lp_ctx_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
 {
-       py_talloc_Object *ret = (py_talloc_Object *)type->tp_alloc(type, 0);
-       if (ret == NULL) {
-               PyErr_NoMemory();
+       const char *kwnames[] = {"filename_for_non_global_lp", NULL};
+       PyObject *lp_ctx;
+       const char *non_global_conf = NULL;
+       struct loadparm_context *ctx;
+
+       if (!PyArg_ParseTupleAndKeywords(args,
+                                        kwargs,
+                                        "|s",
+                                        discard_const_p(char *,
+                                                        kwnames),
+                                        &non_global_conf)) {
                return NULL;
        }
-       ret->talloc_ctx = talloc_new(NULL);
-       if (ret->talloc_ctx == NULL) {
-               PyErr_NoMemory();
-               return NULL;
+
+       /*
+        * by default, any LoadParm python objects map to a single global
+        * underlying object. The filename_for_non_global_lp arg overrides this
+        * default behaviour and creates a separate underlying LoadParm object.
+        */
+       if (non_global_conf != NULL) {
+               bool ok;
+               ctx = loadparm_init(NULL);
+               if (ctx == NULL) {
+                       PyErr_NoMemory();
+                       return NULL;
+               }
+
+               lp_ctx = pytalloc_reference(type, ctx);
+               if (lp_ctx == NULL) {
+                       PyErr_NoMemory();
+                       return NULL;
+               }
+
+               ok = lpcfg_load_no_global(
+                       PyLoadparmContext_AsLoadparmContext(lp_ctx),
+                       non_global_conf);
+               if (!ok) {
+                       PyErr_Format(PyExc_ValueError,
+                                    "Could not load non-global conf %s",
+                                    non_global_conf);
+                       return NULL;
+               }
+               return lp_ctx;
+       } else{
+               return pytalloc_reference(type, loadparm_init_global(false));
        }
-       ret->ptr = loadparm_init_global(false);
-       return (PyObject *)ret;
 }
 
-static Py_ssize_t py_lp_ctx_len(py_talloc_Object *self)
+static Py_ssize_t py_lp_ctx_len(PyObject *self)
 {
        return lpcfg_numservices(PyLoadparmContext_AsLoadparmContext(self));
 }
 
-static PyObject *py_lp_ctx_getitem(py_talloc_Object *self, PyObject *name)
+static PyObject *py_lp_ctx_getitem(PyObject *self, PyObject *name)
 {
        struct loadparm_service *service;
-       if (!PyString_Check(name)) {
+       if (!(PyStr_Check(name) || PyUnicode_Check(name))) {
                PyErr_SetString(PyExc_TypeError, "Only string subscripts are supported");
                return NULL;
        }
-       service = lpcfg_service(PyLoadparmContext_AsLoadparmContext(self), PyString_AsString(name));
+       service = lpcfg_service(PyLoadparmContext_AsLoadparmContext(self), PyStr_AsString(name));
        if (service == NULL) {
                PyErr_SetString(PyExc_KeyError, "No such section");
                return NULL;
@@ -360,8 +519,7 @@ static PyMappingMethods py_lp_ctx_mapping = {
 };
 
 PyTypeObject PyLoadparmContext = {
-       .tp_name = "LoadParm",
-       .tp_basicsize = sizeof(py_talloc_Object),
+       .tp_name = "param.LoadParm",
        .tp_getset = py_lp_ctx_getset,
        .tp_methods = py_lp_ctx_methods,
        .tp_new = py_lp_ctx_new,
@@ -371,25 +529,32 @@ PyTypeObject PyLoadparmContext = {
 
 static PyObject *py_lp_service_dump(PyObject *self, PyObject *args)
 {
-       PyObject *py_stream;
        bool show_defaults = false;
        FILE *f;
+       const char *file_name = "";
+       const char *mode = "w";
        struct loadparm_service *service = PyLoadparmService_AsLoadparmService(self);
        struct loadparm_service *default_service;
        PyObject *py_default_service;
 
-       if (!PyArg_ParseTuple(args, "OO|b", &py_stream, &py_default_service,
-                                                 &show_defaults))
+       if (!PyArg_ParseTuple(args, "O|bss", &py_default_service, &show_defaults, &file_name, &mode))
                return NULL;
 
-       f = PyFile_AsFile(py_stream);
+       if (file_name[0] == '\0') {
+               f = stdout;
+       } else {
+               f = fopen(file_name, mode);
+       }
+
        if (f == NULL) {
-               PyErr_SetString(PyExc_TypeError, "Not a file stream");
                return NULL;
        }
 
        if (!PyObject_TypeCheck(py_default_service, &PyLoadparmService)) {
                PyErr_SetNone(PyExc_TypeError);
+               if (f != stdout) {
+                       fclose(f);
+               }
                return NULL;
        }
 
@@ -397,53 +562,90 @@ static PyObject *py_lp_service_dump(PyObject *self, PyObject *args)
 
        lpcfg_dump_one(f, show_defaults, service, default_service);
 
+       if (f != stdout) {
+               fclose(f);
+       }
+
        Py_RETURN_NONE;
 }
 
 static PyMethodDef py_lp_service_methods[] = {
        { "dump", (PyCFunction)py_lp_service_dump, METH_VARARGS, 
-               "S.dump(f, default_service, show_defaults=False)" },
+               "S.dump(default_service, show_defaults=False, file_name='', mode='w')" },
        { NULL }
 };
 
 PyTypeObject PyLoadparmService = {
-       .tp_name = "LoadparmService",
-       .tp_basicsize = sizeof(py_talloc_Object),
+       .tp_name = "param.LoadparmService",
        .tp_methods = py_lp_service_methods,
        .tp_flags = Py_TPFLAGS_DEFAULT,
 };
 
 static PyObject *py_default_path(PyObject *self)
 {
-    return PyString_FromString(lp_default_path());
+       return PyStr_FromString(lp_default_path());
+}
+
+static PyObject *py_setup_dir(PyObject *self)
+{
+       return PyStr_FromString(dyn_SETUPDIR);
+}
+
+static PyObject *py_modules_dir(PyObject *self)
+{
+       return PyStr_FromString(dyn_MODULESDIR);
+}
+
+static PyObject *py_bin_dir(PyObject *self)
+{
+       return PyStr_FromString(dyn_BINDIR);
+}
+
+static PyObject *py_sbin_dir(PyObject *self)
+{
+       return PyStr_FromString(dyn_SBINDIR);
 }
 
 static PyMethodDef pyparam_methods[] = {
-    { "default_path", (PyCFunction)py_default_path, METH_NOARGS, 
-        "Returns the default smb.conf path." },
-    { NULL }
+       { "default_path", (PyCFunction)py_default_path, METH_NOARGS, 
+               "Returns the default smb.conf path." },
+       { "setup_dir", (PyCFunction)py_setup_dir, METH_NOARGS,
+               "Returns the compiled in location of provision tempates." },
+       { "modules_dir", (PyCFunction)py_modules_dir, METH_NOARGS,
+               "Returns the compiled in location of modules." },
+       { "bin_dir", (PyCFunction)py_bin_dir, METH_NOARGS,
+               "Returns the compiled in BINDIR." },
+       { "sbin_dir", (PyCFunction)py_sbin_dir, METH_NOARGS,
+               "Returns the compiled in SBINDIR." },
+       { NULL }
 };
 
-void initparam(void)
+static struct PyModuleDef moduledef = {
+       PyModuleDef_HEAD_INIT,
+       .m_name = "param",
+       .m_doc = "Parsing and writing Samba configuration files.",
+       .m_size = -1,
+       .m_methods = pyparam_methods,
+};
+
+MODULE_INIT_FUNC(param)
 {
        PyObject *m;
-       PyTypeObject *talloc_type = PyTalloc_GetObjectType();
+       PyTypeObject *talloc_type = pytalloc_GetObjectType();
        if (talloc_type == NULL)
-               return;
-
-       PyLoadparmContext.tp_base = talloc_type;
-       PyLoadparmService.tp_base = talloc_type;
+               return NULL;
 
-       if (PyType_Ready(&PyLoadparmContext) < 0)
-               return;
+       if (pytalloc_BaseObject_PyType_Ready(&PyLoadparmContext) < 0)
+               return NULL;
 
-       if (PyType_Ready(&PyLoadparmService) < 0)
-               return;
+       if (pytalloc_BaseObject_PyType_Ready(&PyLoadparmService) < 0)
+               return NULL;
 
-       m = Py_InitModule3("param", pyparam_methods, "Parsing and writing Samba configuration files.");
+       m = PyModule_Create(&moduledef);
        if (m == NULL)
-               return;
+               return NULL;
 
        Py_INCREF(&PyLoadparmContext);
        PyModule_AddObject(m, "LoadParm", (PyObject *)&PyLoadparmContext);
+       return m;
 }