b432398065394e05349710f78561f25aec420b15
[ira/wip.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 #define PyLoadparmContext_Check(obj) PyObject_TypeCheck(obj, &PyLoadparmContext)
30
31 PyAPI_DATA(PyTypeObject) PyLoadparmContext;
32 PyAPI_DATA(PyTypeObject) PyLoadparmService;
33
34 PyObject *PyLoadparmService_FromService(struct loadparm_service *service)
35 {
36         return py_talloc_import(&PyLoadparmService, service);
37 }
38
39 static PyObject *py_lp_ctx_get_helper(struct loadparm_context *lp_ctx, const char *service_name, const char *param_name)
40 {
41     struct parm_struct *parm = NULL;
42     void *parm_ptr = NULL;
43     int i;
44
45     if (service_name != NULL) {
46         struct loadparm_service *service;
47         /* its a share parameter */
48         service = lp_service(lp_ctx, service_name);
49         if (service == NULL) {
50             return NULL;
51         }
52         if (strchr(param_name, ':')) {
53             /* its a parametric option on a share */
54             const char *type = talloc_strndup(lp_ctx, 
55                               param_name, 
56                               strcspn(param_name, ":"));
57             const char *option = strchr(param_name, ':') + 1;
58             const char *value;
59             if (type == NULL || option == NULL) {
60                 return NULL;
61             }
62             value = lp_get_parametric(lp_ctx, service, type, option);
63             if (value == NULL) {
64                 return NULL;
65             }
66             return PyString_FromString(value);
67         }
68
69         parm = lp_parm_struct(param_name);
70         if (parm == NULL || parm->class == P_GLOBAL) {
71             return NULL;
72         }
73         parm_ptr = lp_parm_ptr(lp_ctx, service, parm);
74     } else if (strchr(param_name, ':')) {
75         /* its a global parametric option */
76         const char *type = talloc_strndup(lp_ctx, 
77                           param_name, strcspn(param_name, ":"));
78         const char *option = strchr(param_name, ':') + 1;
79         const char *value;
80         if (type == NULL || option == NULL) {
81             return NULL;
82         }
83         value = lp_get_parametric(lp_ctx, NULL, type, option);
84         if (value == NULL)
85             return NULL;
86         return PyString_FromString(value);
87     } else {
88         /* its a global parameter */
89         parm = lp_parm_struct(param_name);
90         if (parm == NULL) {
91             return NULL;
92         }
93         parm_ptr = lp_parm_ptr(lp_ctx, NULL, parm);
94     }
95
96     if (parm == NULL || parm_ptr == NULL) {
97         return NULL;
98     }
99
100     /* construct and return the right type of python object */
101     switch (parm->type) {
102     case P_STRING:
103     case P_USTRING:
104         return PyString_FromString(*(char **)parm_ptr);
105     case P_BOOL:
106         return PyBool_FromLong(*(bool *)parm_ptr);
107     case P_INTEGER:
108     case P_OCTAL:
109     case P_BYTES:
110         return PyLong_FromLong(*(int *)parm_ptr);
111     case P_ENUM:
112         for (i=0; parm->enum_list[i].name; i++) {
113             if (*(int *)parm_ptr == parm->enum_list[i].value) {
114                 return PyString_FromString(parm->enum_list[i].name);
115             }
116         }
117         return NULL;
118     case P_LIST: 
119         {
120             int j;
121             const char **strlist = *(const char ***)parm_ptr;
122             PyObject *pylist = PyList_New(str_list_length(strlist));
123             for (j = 0; strlist[j]; j++) 
124                 PyList_SetItem(pylist, j, 
125                                PyString_FromString(strlist[j]));
126             return pylist;
127         }
128
129         break;
130     }
131     return NULL;
132
133 }
134
135 static PyObject *py_lp_ctx_load(py_talloc_Object *self, PyObject *args)
136 {
137         char *filename;
138         bool ret;
139         if (!PyArg_ParseTuple(args, "s", &filename))
140                 return NULL;
141
142         ret = lp_load((struct loadparm_context *)self->ptr, filename);
143
144         if (!ret) {
145                 PyErr_SetString(PyExc_RuntimeError, "Unable to load file");
146                 return NULL;
147         }
148         return Py_None;
149 }
150
151 static PyObject *py_lp_ctx_load_default(py_talloc_Object *self)
152 {
153         bool ret;
154         ret = lp_load_default(self->ptr);
155
156         if (!ret) {
157                 PyErr_SetString(PyExc_RuntimeError, "Unable to load file");
158                 return NULL;
159         }
160         return Py_None;
161 }
162
163 static PyObject *py_lp_ctx_get(py_talloc_Object *self, PyObject *args)
164 {
165         char *param_name;
166         char *section_name = NULL;
167         PyObject *ret;
168         if (!PyArg_ParseTuple(args, "s|s", &param_name, &section_name))
169                 return NULL;
170
171         ret = py_lp_ctx_get_helper(self->ptr, section_name, param_name);
172         if (ret == NULL)
173                 return Py_None;
174         return ret;
175 }
176
177 static PyObject *py_lp_ctx_is_myname(py_talloc_Object *self, PyObject *args)
178 {
179         char *name;
180         if (!PyArg_ParseTuple(args, "s", &name))
181                 return NULL;
182
183         return PyBool_FromLong(lp_is_myname(self->ptr, name));
184 }
185
186 static PyObject *py_lp_ctx_set(py_talloc_Object *self, PyObject *args)
187 {
188         char *name, *value;
189         bool ret;
190         if (!PyArg_ParseTuple(args, "ss", &name, &value))
191                 return NULL;
192
193         ret = lp_set_cmdline(self->ptr, name, value);
194         if (!ret) {
195                 PyErr_SetString(PyExc_RuntimeError, "Unable to set parameter");
196                 return NULL;
197         }
198
199         return Py_None;
200 }
201
202 static PyObject *py_lp_ctx_private_path(py_talloc_Object *self, PyObject *args)
203 {
204         char *name, *path;
205         PyObject *ret;
206         if (!PyArg_ParseTuple(args, "s", &name))
207                 return NULL;
208
209         path = private_path(NULL, self->ptr, name);
210         ret = PyString_FromString(path);
211         talloc_free(path);
212
213         return ret;
214 }
215
216 static PyMethodDef py_lp_ctx_methods[] = {
217         { "load", (PyCFunction)py_lp_ctx_load, METH_VARARGS, 
218                 "S.load(filename) -> None\n"
219                 "Load specified file." },
220         { "load_default", (PyCFunction)py_lp_ctx_load_default, METH_NOARGS,
221                 "S.load_default() -> None\n"
222                 "Load default smb.conf file." },
223         { "is_myname", (PyCFunction)py_lp_ctx_is_myname, METH_VARARGS,
224                 "S.is_myname(name) -> bool\n"
225                 "Check whether the specified name matches one of our netbios names." },
226         { "get", (PyCFunction)py_lp_ctx_get, METH_VARARGS,
227                 "S.get(name, service_name) -> value\n"
228                 "Find specified parameter." },
229         { "set", (PyCFunction)py_lp_ctx_set, METH_VARARGS,
230                 "S.set(name, value) -> bool\n"
231                 "Change a parameter." },
232         { "private_path", (PyCFunction)py_lp_ctx_private_path, METH_VARARGS,
233                 "S.private_path(name) -> path\n" },
234         { NULL }
235 };
236
237 static PyObject *py_lp_ctx_default_service(py_talloc_Object *self, void *closure)
238 {
239         return PyLoadparmService_FromService(lp_default_service((struct loadparm_context *)self->ptr));
240 }
241
242 static PyObject *py_lp_ctx_config_file(py_talloc_Object *self, void *closure)
243 {
244         return PyString_FromString(lp_configfile(self->ptr));
245 }
246
247 static PyGetSetDef py_lp_ctx_getset[] = {
248         { (char *)"default_service", (getter)py_lp_ctx_default_service, NULL, NULL },
249         { (char *)"config_file", (getter)py_lp_ctx_config_file, NULL, 
250                 (char *)"Name of last config file that was loaded." },
251         { NULL }
252 };
253
254 static PyObject *py_lp_ctx_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
255 {
256         return py_talloc_import(type, loadparm_init(NULL));
257 }
258
259 static Py_ssize_t py_lp_ctx_len(py_talloc_Object *self)
260 {
261         return lp_numservices(self->ptr);
262 }
263
264 static PyObject *py_lp_ctx_getitem(py_talloc_Object *self, PyObject *name)
265 {
266         struct loadparm_service *service;
267         if (!PyString_Check(name)) {
268                 PyErr_SetString(PyExc_TypeError, "Only string subscripts are supported");
269                 return NULL;
270         }
271         service = lp_service(self->ptr, PyString_AsString(name));
272         if (service == NULL) {
273                 PyErr_SetString(PyExc_KeyError, "No such section");
274                 return NULL;
275         }
276         return PyLoadparmService_FromService(service);
277 }
278
279 static PyMappingMethods py_lp_ctx_mapping = {
280         .mp_length = (lenfunc)py_lp_ctx_len,
281         .mp_subscript = (binaryfunc)py_lp_ctx_getitem,
282 };
283
284 PyTypeObject PyLoadparmContext = {
285         .tp_name = "LoadparmContext",
286         .tp_basicsize = sizeof(py_talloc_Object),
287         .tp_dealloc = py_talloc_dealloc,
288         .tp_getset = py_lp_ctx_getset,
289         .tp_methods = py_lp_ctx_methods,
290         .tp_new = py_lp_ctx_new,
291         .tp_as_mapping = &py_lp_ctx_mapping,
292         .tp_flags = Py_TPFLAGS_DEFAULT,
293 };
294
295 PyTypeObject PyLoadparmService = {
296         .tp_name = "LoadparmService",
297         .tp_dealloc = py_talloc_dealloc,
298         .tp_basicsize = sizeof(py_talloc_Object),
299         .tp_flags = Py_TPFLAGS_DEFAULT,
300 };
301
302 struct loadparm_context *lp_from_py_object(PyObject *py_obj)
303 {
304     struct loadparm_context *lp_ctx;
305     if (PyString_Check(py_obj)) {
306         lp_ctx = loadparm_init(NULL);
307         if (!lp_load(lp_ctx, PyString_AsString(py_obj))) {
308             talloc_free(lp_ctx);
309             return NULL;
310         }
311         return lp_ctx;
312     }
313
314     if (py_obj == Py_None) {
315         lp_ctx = loadparm_init(NULL);
316         if (!lp_load_default(lp_ctx)) {
317             talloc_free(lp_ctx);
318             return NULL;
319         }
320         return lp_ctx;
321     }
322
323     if (PyLoadparmContext_Check(py_obj))
324             return PyLoadparmContext_AsLoadparmContext(py_obj);
325
326     return NULL;
327 }
328
329 struct loadparm_context *py_default_loadparm_context(TALLOC_CTX *mem_ctx)
330 {
331     struct loadparm_context *ret;
332     ret = loadparm_init(mem_ctx);
333     if (!lp_load_default(ret))
334         return NULL;
335     return ret;
336 }
337
338 void initparam(void)
339 {
340         PyObject *m;
341
342         if (PyType_Ready(&PyLoadparmContext) < 0)
343                 return;
344
345         m = Py_InitModule3("param", NULL, "Parsing and writing Samba configuration files.");
346         if (m == NULL)
347                 return;
348
349         Py_INCREF(&PyLoadparmContext);
350         PyModule_AddObject(m, "LoadparmContext", (PyObject *)&PyLoadparmContext);
351 }
352
353 /*
354 typedef struct loadparm_context {
355     %extend {
356         int use(struct param_context *param_ctx) { return param_use($self, param_ctx); }
357     }
358 } loadparm_context;
359
360 typedef struct loadparm_service {
361     %extend { 
362         const char *volume_label(struct loadparm_service *sDefault) { return volume_label($self, sDefault); }
363         const char *printername(struct loadparm_service *sDefault) { return lp_printername($self, sDefault); }
364         int maxprintjobs(struct loadparm_service *sDefault) { return lp_maxprintjobs($self, sDefault); } 
365     }
366 } loadparm_service;
367
368 %rename(ParamFile) param_context;
369
370 %talloctype(param_context);
371 typedef struct param_context {
372     %extend { 
373         param(TALLOC_CTX *mem_ctx) { return param_init(mem_ctx); }
374         %feature("docstring") add_section "S.get_section(name) -> section\n"
375                                           "Get an existing section.";
376         struct param_section *get_section(const char *name);
377         %feature("docstring") add_section "S.add_section(name) -> section\n"
378                                           "Add a new section.";
379         struct param_section *add_section(const char *name);
380         struct param_opt *get(const char *name, const char *section_name="global");
381         const char *get_string(const char *name, const char *section_name="global");
382         int set_string(const char *param, const char *value, const char *section="global");
383 #ifdef SWIGPYTHON
384         int set(const char *parameter, PyObject *ob, const char *section_name="global")
385         {
386             struct param_opt *opt = param_get_add($self, parameter, section_name);
387
388             talloc_free(opt->value);
389             opt->value = talloc_strdup(opt, PyString_AsString(PyObject_Str(ob)));
390
391             return 0;
392         }
393         
394 #endif
395
396         %feature("docstring") first_section "S.first_section() -> section\n"
397                                           "Find first section";
398         struct param_section *first_section() { return $self->sections; }
399         %feature("docstring") next_section "S.next_section(prev) -> section\n"
400                                           "Find next section";
401         struct param_section *next_section(struct param_section *s) { return s->next; }
402
403         %feature("docstring") read "S.read(filename) -> bool\n"
404                                           "Read a filename.";
405         int read(const char *fn);
406         %feature("docstring") read "S.write(filename) -> bool\n"
407                                           "Write this object to a file.";
408         int write(const char *fn);
409     }
410     %pythoncode {
411         def __getitem__(self, name):
412             ret = self.get_section(name)
413             if ret is None:
414                 raise KeyError("No such section %s" % name)
415             return ret
416
417         class SectionIterator:
418             def __init__(self, param):
419                 self.param = param
420                 self.key = None
421
422             def __iter__(self):
423                 return self
424                 
425             def next(self):
426                 if self.key is None:
427                     self.key = self.param.first_section()
428                     if self.key is None:
429                         raise StopIteration
430                     return self.key
431                 else:
432                     self.key = self.param.next_section(self.key)
433                     if self.key is None:
434                         raise StopIteration
435                     return self.key
436
437         def __iter__(self):
438             return self.SectionIterator(self)
439     }
440 } param;
441
442 %talloctype(param_opt);
443
444 typedef struct param_opt {
445     %immutable key;
446     %immutable value;
447     const char *key, *value;
448     %extend {
449 #ifdef SWIGPYTHON
450         const char *__str__() { return $self->value; }
451 #endif
452     }
453 } param_opt;
454
455 %talloctype(param);
456 typedef struct param_section {
457     %immutable name;
458     const char *name;
459     %extend {
460         struct param_opt *get(const char *name);
461         struct param_opt *first_parameter() { return $self->parameters; }
462         struct param_opt *next_parameter(struct param_opt *s) { return s->next; }
463     }
464     %pythoncode {
465         def __getitem__(self, name):
466             ret = self.get(name)
467             if ret is None:
468                 raise KeyError("No such option %s" % name)
469             return ret
470
471         class ParamIterator:
472             def __init__(self, section):
473                 self.section = section
474                 self.key = None
475
476             def __iter__(self):
477                 return self
478                 
479             def next(self):
480                 if self.key is None:
481                     self.key = self.section.first_parameter()
482                     if self.key is None:
483                         raise StopIteration
484                     return self.key
485                 else:
486                     self.key = self.section.next_parameter(self.key)
487                     if self.key is None:
488                         raise StopIteration
489                     return self.key
490
491         def __iter__(self):
492             return self.ParamIterator(self)
493     }
494 } param_section;
495 */