diff options
Diffstat (limited to 'source4/utils/net/net.c')
-rw-r--r-- | source4/utils/net/net.c | 178 |
1 files changed, 169 insertions, 9 deletions
diff --git a/source4/utils/net/net.c b/source4/utils/net/net.c index 828e46889e..ba935b9986 100644 --- a/source4/utils/net/net.c +++ b/source4/utils/net/net.c @@ -6,6 +6,7 @@ Copyright (C) 2001 Andrew Tridgell (tridge@samba.org) Copyright (C) 2001 Andrew Bartlett (abartlet@samba.org) Copyright (C) 2004 Stefan Metzmacher (metze@samba.org) + Copyright (C) 2009 Jelmer Vernooij (jelmer@samba.org) Largely rewritten by metze in August 2004 @@ -48,6 +49,83 @@ #include "param/param.h" #include "lib/events/events.h" #include "auth/credentials/credentials.h" +#include <Python.h> +#include "scripting/python/modules.h" + +static PyObject *py_tuple_from_argv(int argc, const char *argv[]) +{ + PyObject *l; + Py_ssize_t i; + + l = PyTuple_New(argc); + if (l == NULL) { + return NULL; + } + + for (i = 0; i < argc; i++) { + PyTuple_SetItem(l, i, PyString_FromString(argv[i])); + } + + return l; +} + +static int py_call_with_string_args(PyObject *self, const char *method, int argc, const char *argv[]) +{ + PyObject *ret, *args, *py_method; + + args = py_tuple_from_argv(argc, argv); + if (args == NULL) { + PyErr_Print(); + return 1; + } + + py_method = PyObject_GetAttrString(self, method); + if (py_method == NULL) { + PyErr_Print(); + return 1; + } + + ret = PyObject_CallObject(py_method, args); + + Py_DECREF(args); + + if (ret == NULL) { + PyErr_Print(); + return 1; + } + + if (ret == Py_None) { + return 0; + } else if (PyInt_Check(ret)) { + return PyInt_AsLong(ret); + } else { + fprintf(stderr, "Function return value type unexpected.\n"); + return -1; + } +} + +static PyObject *py_commands(void) +{ + PyObject *netcmd_module, *py_cmds; + netcmd_module = PyImport_ImportModule("samba.netcmd"); + if (netcmd_module == NULL) { + PyErr_Print(); + return NULL; + } + + py_cmds = PyObject_GetAttrString(netcmd_module, "commands"); + if (py_cmds == NULL) { + PyErr_Print(); + return NULL; + } + + if (!PyDict_Check(py_cmds)) { + d_printf("Python net commands is not a dictionary\n"); + return NULL; + } + + return py_cmds; +} /* run a function from a function table. If not found then @@ -84,6 +162,7 @@ int net_run_usage(struct net_context *ctx, const struct net_functable *functable) { int i; + PyObject *py_cmds, *py_cmd; for (i=0; functable[i].name; i++) { if (strcasecmp_m(argv[0], functable[i].name) == 0) @@ -92,6 +171,17 @@ int net_run_usage(struct net_context *ctx, } } + py_cmds = py_commands(); + if (py_cmds == NULL) { + return 1; + } + + py_cmd = PyDict_GetItemString(py_cmds, argv[0]); + if (py_cmd != NULL) { + return py_call_with_string_args(py_cmd, "usage", argc-1, + argv+1); + } + d_printf("No usage information for command: %s\n", argv[0]); return 1; @@ -112,13 +202,12 @@ static const struct net_functable net_functable[] = { {NULL, NULL, NULL, NULL} }; -int net_help(struct net_context *ctx, const struct net_functable *ftable) +static int net_help_builtin(const struct net_functable *ftable) { int i = 0; const char *name = ftable[i].name; const char *desc = ftable[i].desc; - d_printf("Available commands:\n"); while (name && desc) { if (strlen(name) > 7) { d_printf("\t%s\t%s", name, desc); @@ -128,7 +217,53 @@ int net_help(struct net_context *ctx, const struct net_functable *ftable) name = ftable[++i].name; desc = ftable[i].desc; } + return 0; +} + +static int net_help_python(void) +{ + PyObject *py_cmds; + PyObject *key, *value; + Py_ssize_t pos = 0; + + py_cmds = py_commands(); + if (py_cmds == NULL) { + return 1; + } + + while (PyDict_Next(py_cmds, &pos, &key, &value)) { + char *name, *desc; + PyObject *py_desc; + if (!PyString_Check(key)) { + d_printf("Command name not a string\n"); + return 1; + } + name = PyString_AsString(key); + py_desc = PyObject_GetAttrString(value, "description"); + if (py_desc == NULL) { + PyErr_Print(); + return 1; + } + if (!PyString_Check(py_desc)) { + d_printf("Command description for %s not a string\n", + name); + return 1; + } + desc = PyString_AsString(py_desc); + if (strlen(name) > 7) { + d_printf("\t%s\t%s\n", name, desc); + } else { + d_printf("\t%s\t\t%s\n", name, desc); + } + } + return 0; +} +int net_help(struct net_context *ctx, const struct net_functable *ftable) +{ + d_printf("Available commands:\n"); + net_help_builtin(ftable); + net_help_python(); return 0; } @@ -148,6 +283,7 @@ static int binary_net(int argc, const char **argv) int opt,i; int rc; int argc_new; + PyObject *py_cmds, *py_cmd; const char **argv_new; struct tevent_context *ev; struct net_context *ctx = NULL; @@ -163,6 +299,33 @@ static int binary_net(int argc, const char **argv) setlinebuf(stdout); + dcerpc_init(cmdline_lp_ctx); + + ev = s4_event_context_init(NULL); + if (!ev) { + d_printf("Failed to create an event context\n"); + exit(1); + } + py_load_samba_modules(); + Py_Initialize(); + PySys_SetArgv(argc, argv); + py_update_path("bin"); /* FIXME: Can't assume this is always the case */ + + py_cmds = py_commands(); + if (py_cmds == NULL) { + return 1; + } + + if (argc > 1) { + py_cmd = PyDict_GetItemString(py_cmds, argv[1]); + if (py_cmd != NULL) { + rc = py_call_with_string_args(py_cmd, "_run", + argc-1, argv+1); + talloc_free(ev); + return rc; + } + } + pc = poptGetContext("net", argc, (const char **) argv, long_options, POPT_CONTEXT_KEEP_FIRST); @@ -190,13 +353,7 @@ static int binary_net(int argc, const char **argv) return net_usage(ctx, argc, argv); } - dcerpc_init(cmdline_lp_ctx); - ev = s4_event_context_init(NULL); - if (!ev) { - d_printf("Failed to create an event context\n"); - exit(1); - } ctx = talloc(ev, struct net_context); if (!ctx) { d_printf("Failed to talloc a net_context\n"); @@ -208,7 +365,10 @@ static int binary_net(int argc, const char **argv) ctx->credentials = cmdline_credentials; ctx->event_ctx = ev; - rc = net_run_function(ctx, argc_new-1, argv_new+1, net_functable, net_usage); + + + rc = net_run_function(ctx, argc_new-1, argv_new+1, net_functable, + net_usage); if (rc != 0) { DEBUG(0,("return code = %d\n", rc)); |