PageRenderTime 27ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/source4/param/pyparam.c

https://github.com/lauria/Samba4
C | 484 lines | 393 code | 67 blank | 24 comment | 79 complexity | 2a972fc1229c45c6fd8e1baced503800 MD5 | raw file
  1. /*
  2. Unix SMB/CIFS implementation.
  3. Samba utility functions
  4. Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007-2008
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 3 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #include <Python.h>
  17. #include "includes.h"
  18. #include "param/param.h"
  19. #include "param/loadparm.h"
  20. #include <pytalloc.h>
  21. #include "dynconfig/dynconfig.h"
  22. void initparam(void);
  23. /* There's no Py_ssize_t in 2.4, apparently */
  24. #if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 5
  25. typedef int Py_ssize_t;
  26. typedef inquiry lenfunc;
  27. #endif
  28. #define PyLoadparmContext_AsLoadparmContext(obj) pytalloc_get_type(obj, struct loadparm_context)
  29. #define PyLoadparmService_AsLoadparmService(obj) pytalloc_get_type(obj, struct loadparm_service)
  30. extern PyTypeObject PyLoadparmContext;
  31. extern PyTypeObject PyLoadparmService;
  32. static PyObject *PyLoadparmService_FromService(struct loadparm_service *service)
  33. {
  34. return pytalloc_reference(&PyLoadparmService, service);
  35. }
  36. static PyObject *py_lp_ctx_get_helper(struct loadparm_context *lp_ctx, const char *service_name, const char *param_name)
  37. {
  38. struct parm_struct *parm = NULL;
  39. void *parm_ptr = NULL;
  40. int i;
  41. if (service_name != NULL && strwicmp(service_name, GLOBAL_NAME) &&
  42. strwicmp(service_name, GLOBAL_NAME2)) {
  43. struct loadparm_service *service;
  44. /* its a share parameter */
  45. service = lpcfg_service(lp_ctx, service_name);
  46. if (service == NULL) {
  47. return NULL;
  48. }
  49. if (strchr(param_name, ':')) {
  50. /* its a parametric option on a share */
  51. const char *type = talloc_strndup(lp_ctx, param_name,
  52. strcspn(param_name, ":"));
  53. const char *option = strchr(param_name, ':') + 1;
  54. const char *value;
  55. if (type == NULL || option == NULL) {
  56. return NULL;
  57. }
  58. value = lpcfg_get_parametric(lp_ctx, service, type, option);
  59. if (value == NULL) {
  60. return NULL;
  61. }
  62. return PyString_FromString(value);
  63. }
  64. parm = lpcfg_parm_struct(lp_ctx, param_name);
  65. if (parm == NULL || parm->p_class == P_GLOBAL) {
  66. return NULL;
  67. }
  68. parm_ptr = lpcfg_parm_ptr(lp_ctx, service, parm);
  69. } else if (strchr(param_name, ':')) {
  70. /* its a global parametric option */
  71. const char *type = talloc_strndup(lp_ctx,
  72. param_name, strcspn(param_name, ":"));
  73. const char *option = strchr(param_name, ':') + 1;
  74. const char *value;
  75. if (type == NULL || option == NULL) {
  76. return NULL;
  77. }
  78. value = lpcfg_get_parametric(lp_ctx, NULL, type, option);
  79. if (value == NULL)
  80. return NULL;
  81. return PyString_FromString(value);
  82. } else {
  83. /* its a global parameter */
  84. parm = lpcfg_parm_struct(lp_ctx, param_name);
  85. if (parm == NULL) {
  86. return NULL;
  87. }
  88. parm_ptr = lpcfg_parm_ptr(lp_ctx, NULL, parm);
  89. }
  90. if (parm == NULL || parm_ptr == NULL) {
  91. return NULL;
  92. }
  93. /* construct and return the right type of python object */
  94. switch (parm->type) {
  95. case P_CHAR:
  96. return PyString_FromFormat("%c", *(char *)parm_ptr);
  97. case P_STRING:
  98. case P_USTRING:
  99. return PyString_FromString(*(char **)parm_ptr);
  100. case P_BOOL:
  101. return PyBool_FromLong(*(bool *)parm_ptr);
  102. case P_BOOLREV:
  103. return PyBool_FromLong(!(*(bool *)parm_ptr));
  104. case P_INTEGER:
  105. case P_OCTAL:
  106. case P_BYTES:
  107. return PyLong_FromLong(*(int *)parm_ptr);
  108. case P_ENUM:
  109. for (i=0; parm->enum_list[i].name; i++) {
  110. if (*(int *)parm_ptr == parm->enum_list[i].value) {
  111. return PyString_FromString(parm->enum_list[i].name);
  112. }
  113. }
  114. return NULL;
  115. case P_CMDLIST:
  116. case P_LIST:
  117. {
  118. int j;
  119. const char **strlist = *(const char ***)parm_ptr;
  120. PyObject *pylist;
  121. if(strlist == NULL) {
  122. return PyList_New(0);
  123. }
  124. pylist = PyList_New(str_list_length(strlist));
  125. for (j = 0; strlist[j]; j++)
  126. PyList_SetItem(pylist, j,
  127. PyString_FromString(strlist[j]));
  128. return pylist;
  129. }
  130. case P_SEP:
  131. return NULL; /* this stands for a separator, can be ignored */
  132. }
  133. return NULL;
  134. }
  135. static PyObject *py_lp_ctx_load(pytalloc_Object *self, PyObject *args)
  136. {
  137. char *filename;
  138. bool ret;
  139. if (!PyArg_ParseTuple(args, "s", &filename))
  140. return NULL;
  141. ret = lpcfg_load(PyLoadparmContext_AsLoadparmContext(self), filename);
  142. if (!ret) {
  143. PyErr_Format(PyExc_RuntimeError, "Unable to load file %s", filename);
  144. return NULL;
  145. }
  146. Py_RETURN_NONE;
  147. }
  148. static PyObject *py_lp_ctx_load_default(pytalloc_Object *self)
  149. {
  150. bool ret;
  151. ret = lpcfg_load_default(PyLoadparmContext_AsLoadparmContext(self));
  152. if (!ret) {
  153. PyErr_SetString(PyExc_RuntimeError, "Unable to load default file");
  154. return NULL;
  155. }
  156. Py_RETURN_NONE;
  157. }
  158. static PyObject *py_lp_ctx_get(pytalloc_Object *self, PyObject *args)
  159. {
  160. char *param_name;
  161. char *section_name = NULL;
  162. PyObject *ret;
  163. if (!PyArg_ParseTuple(args, "s|z", &param_name, &section_name))
  164. return NULL;
  165. ret = py_lp_ctx_get_helper(PyLoadparmContext_AsLoadparmContext(self), section_name, param_name);
  166. if (ret == NULL)
  167. Py_RETURN_NONE;
  168. return ret;
  169. }
  170. static PyObject *py_lp_ctx_is_myname(pytalloc_Object *self, PyObject *args)
  171. {
  172. char *name;
  173. if (!PyArg_ParseTuple(args, "s", &name))
  174. return NULL;
  175. return PyBool_FromLong(lpcfg_is_myname(PyLoadparmContext_AsLoadparmContext(self), name));
  176. }
  177. static PyObject *py_lp_ctx_is_mydomain(pytalloc_Object *self, PyObject *args)
  178. {
  179. char *name;
  180. if (!PyArg_ParseTuple(args, "s", &name))
  181. return NULL;
  182. return PyBool_FromLong(lpcfg_is_mydomain(PyLoadparmContext_AsLoadparmContext(self), name));
  183. }
  184. static PyObject *py_lp_ctx_set(pytalloc_Object *self, PyObject *args)
  185. {
  186. char *name, *value;
  187. bool ret;
  188. if (!PyArg_ParseTuple(args, "ss", &name, &value))
  189. return NULL;
  190. ret = lpcfg_set_cmdline(PyLoadparmContext_AsLoadparmContext(self), name, value);
  191. if (!ret) {
  192. PyErr_SetString(PyExc_RuntimeError, "Unable to set parameter");
  193. return NULL;
  194. }
  195. Py_RETURN_NONE;
  196. }
  197. static PyObject *py_lp_ctx_private_path(pytalloc_Object *self, PyObject *args)
  198. {
  199. char *name, *path;
  200. PyObject *ret;
  201. if (!PyArg_ParseTuple(args, "s", &name))
  202. return NULL;
  203. path = lpcfg_private_path(NULL, PyLoadparmContext_AsLoadparmContext(self), name);
  204. ret = PyString_FromString(path);
  205. talloc_free(path);
  206. return ret;
  207. }
  208. static PyObject *py_lp_ctx_services(pytalloc_Object *self)
  209. {
  210. struct loadparm_context *lp_ctx = PyLoadparmContext_AsLoadparmContext(self);
  211. PyObject *ret;
  212. int i;
  213. ret = PyList_New(lpcfg_numservices(lp_ctx));
  214. for (i = 0; i < lpcfg_numservices(lp_ctx); i++) {
  215. struct loadparm_service *service = lpcfg_servicebynum(lp_ctx, i);
  216. if (service != NULL) {
  217. PyList_SetItem(ret, i, PyString_FromString(lpcfg_servicename(service)));
  218. }
  219. }
  220. return ret;
  221. }
  222. static PyObject *py_lp_dump(PyObject *self, PyObject *args)
  223. {
  224. PyObject *py_stream;
  225. bool show_defaults = false;
  226. FILE *f;
  227. struct loadparm_context *lp_ctx = PyLoadparmContext_AsLoadparmContext(self);
  228. if (!PyArg_ParseTuple(args, "O|b", &py_stream, &show_defaults))
  229. return NULL;
  230. f = PyFile_AsFile(py_stream);
  231. if (f == NULL) {
  232. PyErr_SetString(PyExc_TypeError, "Not a file stream");
  233. return NULL;
  234. }
  235. lpcfg_dump(lp_ctx, f, show_defaults, lpcfg_numservices(lp_ctx));
  236. Py_RETURN_NONE;
  237. }
  238. static PyObject *py_samdb_url(PyObject *self)
  239. {
  240. struct loadparm_context *lp_ctx = PyLoadparmContext_AsLoadparmContext(self);
  241. return PyString_FromFormat("tdb://%s/sam.ldb", lpcfg_private_dir(lp_ctx));
  242. }
  243. static PyMethodDef py_lp_ctx_methods[] = {
  244. { "load", (PyCFunction)py_lp_ctx_load, METH_VARARGS,
  245. "S.load(filename) -> None\n"
  246. "Load specified file." },
  247. { "load_default", (PyCFunction)py_lp_ctx_load_default, METH_NOARGS,
  248. "S.load_default() -> None\n"
  249. "Load default smb.conf file." },
  250. { "is_myname", (PyCFunction)py_lp_ctx_is_myname, METH_VARARGS,
  251. "S.is_myname(name) -> bool\n"
  252. "Check whether the specified name matches one of our netbios names." },
  253. { "is_mydomain", (PyCFunction)py_lp_ctx_is_mydomain, METH_VARARGS,
  254. "S.is_mydomain(name) -> bool\n"
  255. "Check whether the specified name matches our domain name." },
  256. { "get", (PyCFunction)py_lp_ctx_get, METH_VARARGS,
  257. "S.get(name, service_name) -> value\n"
  258. "Find specified parameter." },
  259. { "set", (PyCFunction)py_lp_ctx_set, METH_VARARGS,
  260. "S.set(name, value) -> bool\n"
  261. "Change a parameter." },
  262. { "private_path", (PyCFunction)py_lp_ctx_private_path, METH_VARARGS,
  263. "S.private_path(name) -> path\n" },
  264. { "services", (PyCFunction)py_lp_ctx_services, METH_NOARGS,
  265. "S.services() -> list" },
  266. { "dump", (PyCFunction)py_lp_dump, METH_VARARGS,
  267. "S.dump(stream, show_defaults=False)" },
  268. { "samdb_url", (PyCFunction)py_samdb_url, METH_NOARGS,
  269. "S.samdb_url() -> string\n"
  270. "Returns the current URL for sam.ldb." },
  271. { NULL }
  272. };
  273. static PyObject *py_lp_ctx_default_service(pytalloc_Object *self, void *closure)
  274. {
  275. return PyLoadparmService_FromService(lpcfg_default_service(PyLoadparmContext_AsLoadparmContext(self)));
  276. }
  277. static PyObject *py_lp_ctx_config_file(pytalloc_Object *self, void *closure)
  278. {
  279. const char *configfile = lpcfg_configfile(PyLoadparmContext_AsLoadparmContext(self));
  280. if (configfile == NULL)
  281. Py_RETURN_NONE;
  282. else
  283. return PyString_FromString(configfile);
  284. }
  285. static PyGetSetDef py_lp_ctx_getset[] = {
  286. { discard_const_p(char, "default_service"), (getter)py_lp_ctx_default_service, NULL, NULL },
  287. { discard_const_p(char, "configfile"), (getter)py_lp_ctx_config_file, NULL,
  288. discard_const_p(char, "Name of last config file that was loaded.") },
  289. { NULL }
  290. };
  291. static PyObject *py_lp_ctx_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
  292. {
  293. pytalloc_Object *ret = (pytalloc_Object *)type->tp_alloc(type, 0);
  294. if (ret == NULL) {
  295. PyErr_NoMemory();
  296. return NULL;
  297. }
  298. ret->talloc_ctx = talloc_new(NULL);
  299. if (ret->talloc_ctx == NULL) {
  300. PyErr_NoMemory();
  301. return NULL;
  302. }
  303. ret->ptr = loadparm_init_global(false);
  304. if (ret->ptr == NULL) {
  305. PyErr_NoMemory();
  306. return NULL;
  307. }
  308. return (PyObject *)ret;
  309. }
  310. static Py_ssize_t py_lp_ctx_len(pytalloc_Object *self)
  311. {
  312. return lpcfg_numservices(PyLoadparmContext_AsLoadparmContext(self));
  313. }
  314. static PyObject *py_lp_ctx_getitem(pytalloc_Object *self, PyObject *name)
  315. {
  316. struct loadparm_service *service;
  317. if (!PyString_Check(name)) {
  318. PyErr_SetString(PyExc_TypeError, "Only string subscripts are supported");
  319. return NULL;
  320. }
  321. service = lpcfg_service(PyLoadparmContext_AsLoadparmContext(self), PyString_AsString(name));
  322. if (service == NULL) {
  323. PyErr_SetString(PyExc_KeyError, "No such section");
  324. return NULL;
  325. }
  326. return PyLoadparmService_FromService(service);
  327. }
  328. static PyMappingMethods py_lp_ctx_mapping = {
  329. .mp_length = (lenfunc)py_lp_ctx_len,
  330. .mp_subscript = (binaryfunc)py_lp_ctx_getitem,
  331. };
  332. PyTypeObject PyLoadparmContext = {
  333. .tp_name = "param.LoadParm",
  334. .tp_basicsize = sizeof(pytalloc_Object),
  335. .tp_getset = py_lp_ctx_getset,
  336. .tp_methods = py_lp_ctx_methods,
  337. .tp_new = py_lp_ctx_new,
  338. .tp_as_mapping = &py_lp_ctx_mapping,
  339. .tp_flags = Py_TPFLAGS_DEFAULT,
  340. };
  341. static PyObject *py_lp_service_dump(PyObject *self, PyObject *args)
  342. {
  343. PyObject *py_stream;
  344. bool show_defaults = false;
  345. FILE *f;
  346. struct loadparm_service *service = PyLoadparmService_AsLoadparmService(self);
  347. struct loadparm_service *default_service;
  348. PyObject *py_default_service;
  349. if (!PyArg_ParseTuple(args, "OO|b", &py_stream, &py_default_service,
  350. &show_defaults))
  351. return NULL;
  352. f = PyFile_AsFile(py_stream);
  353. if (f == NULL) {
  354. PyErr_SetString(PyExc_TypeError, "Not a file stream");
  355. return NULL;
  356. }
  357. if (!PyObject_TypeCheck(py_default_service, &PyLoadparmService)) {
  358. PyErr_SetNone(PyExc_TypeError);
  359. return NULL;
  360. }
  361. default_service = PyLoadparmService_AsLoadparmService(py_default_service);
  362. lpcfg_dump_one(f, show_defaults, service, default_service);
  363. Py_RETURN_NONE;
  364. }
  365. static PyMethodDef py_lp_service_methods[] = {
  366. { "dump", (PyCFunction)py_lp_service_dump, METH_VARARGS,
  367. "S.dump(f, default_service, show_defaults=False)" },
  368. { NULL }
  369. };
  370. PyTypeObject PyLoadparmService = {
  371. .tp_name = "param.LoadparmService",
  372. .tp_basicsize = sizeof(pytalloc_Object),
  373. .tp_methods = py_lp_service_methods,
  374. .tp_flags = Py_TPFLAGS_DEFAULT,
  375. };
  376. static PyObject *py_default_path(PyObject *self)
  377. {
  378. return PyString_FromString(lp_default_path());
  379. }
  380. static PyObject *py_setup_dir(PyObject *self)
  381. {
  382. return PyString_FromString(dyn_SETUPDIR);
  383. }
  384. static PyObject *py_modules_dir(PyObject *self)
  385. {
  386. return PyString_FromString(dyn_MODULESDIR);
  387. }
  388. static PyMethodDef pyparam_methods[] = {
  389. { "default_path", (PyCFunction)py_default_path, METH_NOARGS,
  390. "Returns the default smb.conf path." },
  391. { "setup_dir", (PyCFunction)py_setup_dir, METH_NOARGS,
  392. "Returns the compiled in location of provision tempates." },
  393. { "modules_dir", (PyCFunction)py_modules_dir, METH_NOARGS,
  394. "Returns the compiled in location of modules." },
  395. { NULL }
  396. };
  397. void initparam(void)
  398. {
  399. PyObject *m;
  400. PyTypeObject *talloc_type = pytalloc_GetObjectType();
  401. if (talloc_type == NULL)
  402. return;
  403. PyLoadparmContext.tp_base = talloc_type;
  404. PyLoadparmService.tp_base = talloc_type;
  405. if (PyType_Ready(&PyLoadparmContext) < 0)
  406. return;
  407. if (PyType_Ready(&PyLoadparmService) < 0)
  408. return;
  409. m = Py_InitModule3("param", pyparam_methods, "Parsing and writing Samba configuration files.");
  410. if (m == NULL)
  411. return;
  412. Py_INCREF(&PyLoadparmContext);
  413. PyModule_AddObject(m, "LoadParm", (PyObject *)&PyLoadparmContext);
  414. }