Fix more tests, improve repr() functions for various Python types.
[kai/samba-autobuild/.git] / source4 / param / pyparam.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Samba utility functions
4    Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007-2008
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <stdint.h>
21 #include <stdbool.h>
22
23 #include "includes.h"
24 #include "param/param.h"
25 #include "param/loadparm.h"
26 #include "pytalloc.h"
27
28 #define PyLoadparmContext_AsLoadparmContext(obj) py_talloc_get_ptr(obj)
29
30 PyAPI_DATA(PyTypeObject) PyLoadparmContext;
31 PyAPI_DATA(PyTypeObject) PyLoadparmService;
32
33 PyObject *PyLoadparmService_FromService(struct loadparm_service *service)
34 {
35         return py_talloc_import(&PyLoadparmService, service);
36 }
37
38 static PyObject *py_lp_ctx_get_helper(struct loadparm_context *lp_ctx, const char *service_name, const char *param_name)
39 {
40     struct parm_struct *parm = NULL;
41     void *parm_ptr = NULL;
42     int i;
43
44     if (service_name != NULL) {
45         struct loadparm_service *service;
46         /* its a share parameter */
47         service = lp_service(lp_ctx, service_name);
48         if (service == NULL) {
49             return NULL;
50         }
51         if (strchr(param_name, ':')) {
52             /* its a parametric option on a share */
53             const char *type = talloc_strndup(lp_ctx, 
54                               param_name, 
55                               strcspn(param_name, ":"));
56             const char *option = strchr(param_name, ':') + 1;
57             const char *value;
58             if (type == NULL || option == NULL) {
59                 return NULL;
60             }
61             value = lp_get_parametric(lp_ctx, service, type, option);
62             if (value == NULL) {
63                 return NULL;
64             }
65             return PyString_FromString(value);
66         }
67
68         parm = lp_parm_struct(param_name);
69         if (parm == NULL || parm->class == P_GLOBAL) {
70             return NULL;
71         }
72         parm_ptr = lp_parm_ptr(lp_ctx, service, parm);
73     } else if (strchr(param_name, ':')) {
74         /* its a global parametric option */
75         const char *type = talloc_strndup(lp_ctx, 
76                           param_name, strcspn(param_name, ":"));
77         const char *option = strchr(param_name, ':') + 1;
78         const char *value;
79         if (type == NULL || option == NULL) {
80             return NULL;
81         }
82         value = lp_get_parametric(lp_ctx, NULL, type, option);
83         if (value == NULL)
84             return NULL;
85         return PyString_FromString(value);
86     } else {
87         /* its a global parameter */
88         parm = lp_parm_struct(param_name);
89         if (parm == NULL) {
90             return NULL;
91         }
92         parm_ptr = lp_parm_ptr(lp_ctx, NULL, parm);
93     }
94
95     if (parm == NULL || parm_ptr == NULL) {
96         return NULL;
97     }
98
99     /* construct and return the right type of python object */
100     switch (parm->type) {
101     case P_STRING:
102     case P_USTRING:
103         return PyString_FromString(*(char **)parm_ptr);
104     case P_BOOL:
105         return PyBool_FromLong(*(bool *)parm_ptr);
106     case P_INTEGER:
107     case P_OCTAL:
108     case P_BYTES:
109         return PyLong_FromLong(*(int *)parm_ptr);
110     case P_ENUM:
111         for (i=0; parm->enum_list[i].name; i++) {
112             if (*(int *)parm_ptr == parm->enum_list[i].value) {
113                 return PyString_FromString(parm->enum_list[i].name);
114             }
115         }
116         return NULL;
117     case P_LIST: 
118         {
119             int j;
120             const char **strlist = *(const char ***)parm_ptr;
121             PyObject *pylist = PyList_New(str_list_length(strlist));
122             for (j = 0; strlist[j]; j++) 
123                 PyList_SetItem(pylist, j, 
124                                PyString_FromString(strlist[j]));
125             return pylist;
126         }
127
128         break;
129     }
130     return NULL;
131
132 }
133
134 static PyObject *py_lp_ctx_load(py_talloc_Object *self, PyObject *args)
135 {
136         char *filename;
137         bool ret;
138         if (!PyArg_ParseTuple(args, "s", &filename))
139                 return NULL;
140
141         ret = lp_load((struct loadparm_context *)self->ptr, filename);
142
143         if (!ret) {
144                 PyErr_Format(PyExc_RuntimeError, "Unable to load file %s", filename);
145                 return NULL;
146         }
147         return Py_None;
148 }
149
150 static PyObject *py_lp_ctx_load_default(py_talloc_Object *self)
151 {
152         bool ret;
153         ret = lp_load_default(self->ptr);
154
155         if (!ret) {
156                 PyErr_SetString(PyExc_RuntimeError, "Unable to load default file");
157                 return NULL;
158         }
159         return Py_None;
160 }
161
162 static PyObject *py_lp_ctx_get(py_talloc_Object *self, PyObject *args)
163 {
164         char *param_name;
165         char *section_name = NULL;
166         PyObject *ret;
167         if (!PyArg_ParseTuple(args, "s|s", &param_name, &section_name))
168                 return NULL;
169
170         ret = py_lp_ctx_get_helper(self->ptr, section_name, param_name);
171         if (ret == NULL)
172                 return Py_None;
173         return ret;
174 }
175
176 static PyObject *py_lp_ctx_is_myname(py_talloc_Object *self, PyObject *args)
177 {
178         char *name;
179         if (!PyArg_ParseTuple(args, "s", &name))
180                 return NULL;
181
182         return PyBool_FromLong(lp_is_myname(self->ptr, name));
183 }
184
185 static PyObject *py_lp_ctx_is_mydomain(py_talloc_Object *self, PyObject *args)
186 {
187         char *name;
188         if (!PyArg_ParseTuple(args, "s", &name))
189                 return NULL;
190
191         return PyBool_FromLong(lp_is_mydomain(self->ptr, name));
192 }
193
194 static PyObject *py_lp_ctx_set(py_talloc_Object *self, PyObject *args)
195 {
196         char *name, *value;
197         bool ret;
198         if (!PyArg_ParseTuple(args, "ss", &name, &value))
199                 return NULL;
200
201         ret = lp_set_cmdline(self->ptr, name, value);
202         if (!ret) {
203                 PyErr_SetString(PyExc_RuntimeError, "Unable to set parameter");
204                 return NULL;
205         }
206
207         return Py_None;
208 }
209
210 static PyObject *py_lp_ctx_private_path(py_talloc_Object *self, PyObject *args)
211 {
212         char *name, *path;
213         PyObject *ret;
214         if (!PyArg_ParseTuple(args, "s", &name))
215                 return NULL;
216
217         path = private_path(NULL, self->ptr, name);
218         ret = PyString_FromString(path);
219         talloc_free(path);
220
221         return ret;
222 }
223
224 static PyMethodDef py_lp_ctx_methods[] = {
225         { "load", (PyCFunction)py_lp_ctx_load, METH_VARARGS, 
226                 "S.load(filename) -> None\n"
227                 "Load specified file." },
228         { "load_default", (PyCFunction)py_lp_ctx_load_default, METH_NOARGS,
229                 "S.load_default() -> None\n"
230                 "Load default smb.conf file." },
231         { "is_myname", (PyCFunction)py_lp_ctx_is_myname, METH_VARARGS,
232                 "S.is_myname(name) -> bool\n"
233                 "Check whether the specified name matches one of our netbios names." },
234         { "is_mydomain", (PyCFunction)py_lp_ctx_is_mydomain, METH_VARARGS,
235                 "S.is_mydomain(name) -> bool\n"
236                 "Check whether the specified name matches our domain name." },
237         { "get", (PyCFunction)py_lp_ctx_get, METH_VARARGS,
238                 "S.get(name, service_name) -> value\n"
239                 "Find specified parameter." },
240         { "set", (PyCFunction)py_lp_ctx_set, METH_VARARGS,
241                 "S.set(name, value) -> bool\n"
242                 "Change a parameter." },
243         { "private_path", (PyCFunction)py_lp_ctx_private_path, METH_VARARGS,
244                 "S.private_path(name) -> path\n" },
245         { NULL }
246 };
247
248 static PyObject *py_lp_ctx_default_service(py_talloc_Object *self, void *closure)
249 {
250         return PyLoadparmService_FromService(lp_default_service((struct loadparm_context *)self->ptr));
251 }
252
253 static PyObject *py_lp_ctx_config_file(py_talloc_Object *self, void *closure)
254 {
255         return PyString_FromString(lp_configfile(self->ptr));
256 }
257
258 static PyGetSetDef py_lp_ctx_getset[] = {
259         { (char *)"default_service", (getter)py_lp_ctx_default_service, NULL, NULL },
260         { (char *)"configfile", (getter)py_lp_ctx_config_file, NULL, 
261                 (char *)"Name of last config file that was loaded." },
262         { NULL }
263 };
264
265 static PyObject *py_lp_ctx_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
266 {
267         return py_talloc_import(type, loadparm_init(NULL));
268 }
269
270 static Py_ssize_t py_lp_ctx_len(py_talloc_Object *self)
271 {
272         return lp_numservices(self->ptr);
273 }
274
275 static PyObject *py_lp_ctx_getitem(py_talloc_Object *self, PyObject *name)
276 {
277         struct loadparm_service *service;
278         if (!PyString_Check(name)) {
279                 PyErr_SetString(PyExc_TypeError, "Only string subscripts are supported");
280                 return NULL;
281         }
282         service = lp_service(self->ptr, PyString_AsString(name));
283         if (service == NULL) {
284                 PyErr_SetString(PyExc_KeyError, "No such section");
285                 return NULL;
286         }
287         return PyLoadparmService_FromService(service);
288 }
289
290 static PyMappingMethods py_lp_ctx_mapping = {
291         .mp_length = (lenfunc)py_lp_ctx_len,
292         .mp_subscript = (binaryfunc)py_lp_ctx_getitem,
293 };
294
295 PyTypeObject PyLoadparmContext = {
296         .tp_name = "LoadParm",
297         .tp_basicsize = sizeof(py_talloc_Object),
298         .tp_dealloc = py_talloc_dealloc,
299         .tp_getset = py_lp_ctx_getset,
300         .tp_methods = py_lp_ctx_methods,
301         .tp_new = py_lp_ctx_new,
302         .tp_as_mapping = &py_lp_ctx_mapping,
303         .tp_flags = Py_TPFLAGS_DEFAULT,
304 };
305
306 PyTypeObject PyLoadparmService = {
307         .tp_name = "LoadparmService",
308         .tp_dealloc = py_talloc_dealloc,
309         .tp_basicsize = sizeof(py_talloc_Object),
310         .tp_flags = Py_TPFLAGS_DEFAULT,
311 };
312
313 struct loadparm_context *lp_from_py_object(PyObject *py_obj)
314 {
315     struct loadparm_context *lp_ctx;
316     if (PyString_Check(py_obj)) {
317         lp_ctx = loadparm_init(NULL);
318         if (!lp_load(lp_ctx, PyString_AsString(py_obj))) {
319             talloc_free(lp_ctx);
320             return NULL;
321         }
322         return lp_ctx;
323     }
324
325     if (py_obj == Py_None) {
326         lp_ctx = loadparm_init(NULL);
327         if (!lp_load_default(lp_ctx)) {
328             talloc_free(lp_ctx);
329             return NULL;
330         }
331         return lp_ctx;
332     }
333
334     return PyLoadparmContext_AsLoadparmContext(py_obj);
335 }
336
337 struct loadparm_context *py_default_loadparm_context(TALLOC_CTX *mem_ctx)
338 {
339     struct loadparm_context *ret;
340     ret = loadparm_init(mem_ctx);
341     if (!lp_load_default(ret))
342         return NULL;
343     return ret;
344 }
345
346 void initparam(void)
347 {
348         PyObject *m;
349
350         if (PyType_Ready(&PyLoadparmContext) < 0)
351                 return;
352
353         m = Py_InitModule3("param", NULL, "Parsing and writing Samba configuration files.");
354         if (m == NULL)
355                 return;
356
357         Py_INCREF(&PyLoadparmContext);
358         PyModule_AddObject(m, "LoadParm", (PyObject *)&PyLoadparmContext);
359 }