net: Support usage/help of subcommands implemented in Python.
[Samba/fernandojvsilva.git] / source4 / utils / net / net.c
blob298204b01f01bae0b514680032a96076a87bf630
1 /*
2 Samba Unix/Linux SMB client library
3 Distributed SMB/CIFS Server Management Utility
4 Copyright (C) 2001 Steve French (sfrench@us.ibm.com)
5 Copyright (C) 2001 Jim McDonough (jmcd@us.ibm.com)
6 Copyright (C) 2001 Andrew Tridgell (tridge@samba.org)
7 Copyright (C) 2001 Andrew Bartlett (abartlet@samba.org)
8 Copyright (C) 2004 Stefan Metzmacher (metze@samba.org)
9 Copyright (C) 2009 Jelmer Vernooij (jelmer@samba.org)
11 Largely rewritten by metze in August 2004
13 Originally written by Steve and Jim. Largely rewritten by tridge in
14 November 2001.
16 Reworked again by abartlet in December 2001
18 This program is free software; you can redistribute it and/or modify
19 it under the terms of the GNU General Public License as published by
20 the Free Software Foundation; either version 3 of the License, or
21 (at your option) any later version.
23 This program is distributed in the hope that it will be useful,
24 but WITHOUT ANY WARRANTY; without even the implied warranty of
25 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 GNU General Public License for more details.
28 You should have received a copy of the GNU General Public License
29 along with this program. If not, see <http://www.gnu.org/licenses/>.
32 /*****************************************************/
33 /* */
34 /* Distributed SMB/CIFS Server Management Utility */
35 /* */
36 /* The intent was to make the syntax similar */
37 /* to the NET utility (first developed in DOS */
38 /* with additional interesting & useful functions */
39 /* added in later SMB server network operating */
40 /* systems). */
41 /* */
42 /*****************************************************/
44 #include "includes.h"
45 #include "utils/net/net.h"
46 #include "lib/cmdline/popt_common.h"
47 #include "lib/ldb/include/ldb.h"
48 #include "librpc/rpc/dcerpc.h"
49 #include "param/param.h"
50 #include "lib/events/events.h"
51 #include "auth/credentials/credentials.h"
52 #include <Python.h>
53 #include "scripting/python/modules.h"
55 static PyObject *py_commands(void)
57 PyObject *netcmd_module, *py_cmds;
58 netcmd_module = PyImport_ImportModule("samba.netcmd");
59 if (netcmd_module == NULL) {
60 PyErr_Print();
61 return NULL;
64 py_cmds = PyObject_GetAttrString(netcmd_module, "commands");
65 if (py_cmds == NULL) {
66 PyErr_Print();
67 return NULL;
70 if (!PyDict_Check(py_cmds)) {
71 fprintf(stderr, "Python net commands is not a dictionary\n");
72 return NULL;
75 return py_cmds;
79 run a function from a function table. If not found then
80 call the specified usage function
82 int net_run_function(struct net_context *ctx,
83 int argc, const char **argv,
84 const struct net_functable *functable,
85 int (*usage_fn)(struct net_context *ctx, int argc, const char **argv))
87 int i;
88 PyObject *py_cmds, *py_cmd;
90 if (argc == 0) {
91 return usage_fn(ctx, argc, argv);
93 } else if (argc == 1 && strequal(argv[0], "help")) {
94 return net_help(ctx, functable);
97 for (i=0; functable[i].name; i++) {
98 if (strcasecmp_m(argv[0], functable[i].name) == 0)
99 return functable[i].fn(ctx, argc-1, argv+1);
102 py_cmds = py_commands();
103 if (py_cmds == NULL) {
104 return 1;
107 py_cmd = PyDict_GetItemString(py_cmds, argv[0]);
108 if (py_cmd != NULL) {
109 PyObject *ret = PyObject_CallMethod(py_cmd, "run", "");
110 if (ret == NULL) {
111 PyErr_Print();
112 return 1;
114 return PyInt_AsLong(ret);
117 d_printf("No command: %s\n", argv[0]);
118 return usage_fn(ctx, argc, argv);
122 run a usage function from a function table. If not found then fail
124 int net_run_usage(struct net_context *ctx,
125 int argc, const char **argv,
126 const struct net_functable *functable)
128 int i;
129 PyObject *py_cmds, *py_cmd;
131 for (i=0; functable[i].name; i++) {
132 if (strcasecmp_m(argv[0], functable[i].name) == 0)
133 if (functable[i].usage) {
134 return functable[i].usage(ctx, argc-1, argv+1);
138 py_cmds = py_commands();
139 if (py_cmds == NULL) {
140 return 1;
143 py_cmd = PyDict_GetItemString(py_cmds, argv[0]);
144 if (py_cmd != NULL) {
145 PyObject *ret = PyObject_CallMethod(py_cmd, "usage", "");
146 if (ret == NULL) {
147 PyErr_Print();
148 return 1;
150 return PyInt_AsLong(ret);
153 d_printf("No usage information for command: %s\n", argv[0]);
155 return 1;
159 /* main function table */
160 static const struct net_functable net_functable[] = {
161 {"password", "change password\n", net_password, net_password_usage},
162 {"time", "get remote server's time\n", net_time, net_time_usage},
163 {"join", "join a domain\n", net_join, net_join_usage},
164 {"samdump", "dump the sam of a domain\n", net_samdump, net_samdump_usage},
165 {"export", "dump the sam of this domain\n", net_export, net_export_usage},
166 {"vampire", "join and syncronise an AD domain onto the local server\n", net_vampire, net_vampire_usage},
167 {"samsync", "synchronise into the local ldb the sam of an NT4 domain\n", net_samsync_ldb, net_samsync_ldb_usage},
168 {"user", "manage user accounts\n", net_user, net_user_usage},
169 {"machinepw", "Get a machine password out of our SAM\n", net_machinepw, net_machinepw_usage},
170 {NULL, NULL, NULL, NULL}
173 static int net_help_builtin(const struct net_functable *ftable)
175 int i = 0;
176 const char *name = ftable[i].name;
177 const char *desc = ftable[i].desc;
179 while (name && desc) {
180 if (strlen(name) > 7) {
181 d_printf("\t%s\t%s", name, desc);
182 } else {
183 d_printf("\t%s\t\t%s", name, desc);
185 name = ftable[++i].name;
186 desc = ftable[i].desc;
188 return 0;
191 static int net_help_python(void)
193 PyObject *py_cmds;
194 PyObject *key, *value;
195 Py_ssize_t pos = 0;
197 py_cmds = py_commands();
198 if (py_cmds == NULL) {
199 return 1;
202 while (PyDict_Next(py_cmds, &pos, &key, &value)) {
203 char *name, *desc;
204 PyObject *py_desc;
205 if (!PyString_Check(key)) {
206 fprintf(stderr, "Command name not a string\n");
207 return 1;
209 name = PyString_AsString(key);
210 py_desc = PyObject_GetAttrString(value, "description");
211 if (py_desc == NULL) {
212 PyErr_Print();
213 return 1;
215 if (!PyString_Check(py_desc)) {
216 fprintf(stderr, "Command description for %s not a string\n", name);
217 return 1;
219 desc = PyString_AsString(py_desc);
220 if (strlen(name) > 7) {
221 d_printf("\t%s\t%s", name, desc);
222 } else {
223 d_printf("\t%s\t\t%s", name, desc);
226 return 0;
229 int net_help(struct net_context *ctx, const struct net_functable *ftable)
231 d_printf("Available commands:\n");
232 net_help_builtin(ftable);
233 net_help_python();
234 return 0;
237 static int net_usage(struct net_context *ctx, int argc, const char **argv)
239 d_printf("Usage:\n");
240 d_printf("net <command> [options]\n");
241 d_printf("Type 'net help' for all available commands\n");
242 return 0;
245 /****************************************************************************
246 main program
247 ****************************************************************************/
248 static int binary_net(int argc, const char **argv)
250 int opt,i;
251 int rc;
252 int argc_new;
253 const char **argv_new;
254 struct tevent_context *ev;
255 struct net_context *ctx = NULL;
256 poptContext pc;
257 struct poptOption long_options[] = {
258 POPT_AUTOHELP
259 POPT_COMMON_SAMBA
260 POPT_COMMON_CONNECTION
261 POPT_COMMON_CREDENTIALS
262 POPT_COMMON_VERSION
263 { NULL }
266 setlinebuf(stdout);
268 pc = poptGetContext("net", argc, (const char **) argv, long_options,
269 POPT_CONTEXT_KEEP_FIRST);
271 while((opt = poptGetNextOpt(pc)) != -1) {
272 switch (opt) {
273 default:
274 d_printf("Invalid option %s: %s\n",
275 poptBadOption(pc, 0), poptStrerror(opt));
276 net_usage(ctx, argc, argv);
277 exit(1);
281 argv_new = (const char **)poptGetArgs(pc);
283 argc_new = argc;
284 for (i=0; i<argc; i++) {
285 if (argv_new[i] == NULL) {
286 argc_new = i;
287 break;
291 if (argc_new < 2) {
292 return net_usage(ctx, argc, argv);
295 dcerpc_init(cmdline_lp_ctx);
297 ev = s4_event_context_init(NULL);
298 if (!ev) {
299 d_printf("Failed to create an event context\n");
300 exit(1);
302 ctx = talloc(ev, struct net_context);
303 if (!ctx) {
304 d_printf("Failed to talloc a net_context\n");
305 exit(1);
308 ZERO_STRUCTP(ctx);
309 ctx->lp_ctx = cmdline_lp_ctx;
310 ctx->credentials = cmdline_credentials;
311 ctx->event_ctx = ev;
313 py_load_samba_modules();
314 Py_Initialize();
315 py_update_path("bin"); /* FIXME: Can't assume this is always the case */
317 rc = net_run_function(ctx, argc_new-1, argv_new+1, net_functable,
318 net_usage);
320 if (rc != 0) {
321 DEBUG(0,("return code = %d\n", rc));
324 talloc_free(ev);
325 return rc;
328 int main(int argc, const char **argv)
330 return binary_net(argc, argv);