source: trunk/server/source4/samba_tool/samba_tool.c

Last change on this file was 745, checked in by Silvan Scherrer, 13 years ago

Samba Server: updated trunk to 3.6.0

File size: 9.5 KB
Line 
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)
10
11 Largely rewritten by metze in August 2004
12
13 Originally written by Steve and Jim. Largely rewritten by tridge in
14 November 2001.
15
16 Reworked again by abartlet in December 2001
17
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.
22
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.
27
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/>.
30*/
31
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/*****************************************************/
43
44#include <Python.h>
45#include "includes.h"
46#include "samba_tool/samba_tool.h"
47#include "lib/cmdline/popt_common.h"
48#include <ldb.h>
49#include "librpc/rpc/dcerpc.h"
50#include "param/param.h"
51#include "lib/events/events.h"
52#include "auth/credentials/credentials.h"
53#include "scripting/python/modules.h"
54
55/* There's no Py_ssize_t in 2.4, apparently */
56#if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 5
57typedef int Py_ssize_t;
58#endif
59
60static PyObject *py_tuple_from_argv(int argc, const char *argv[])
61{
62 PyObject *l;
63 Py_ssize_t i;
64
65 l = PyTuple_New(argc);
66 if (l == NULL) {
67 return NULL;
68 }
69
70 for (i = 0; i < argc; i++) {
71 PyTuple_SetItem(l, i, PyString_FromString(argv[i]));
72 }
73
74 return l;
75}
76
77static int py_call_with_string_args(PyObject *self, const char *method, int argc, const char *argv[])
78{
79 PyObject *ret, *args, *py_method;
80
81 args = py_tuple_from_argv(argc, argv);
82 if (args == NULL) {
83 PyErr_Print();
84 return 1;
85 }
86
87 py_method = PyObject_GetAttrString(self, method);
88 if (py_method == NULL) {
89 PyErr_Print();
90 return 1;
91 }
92
93 ret = PyObject_CallObject(py_method, args);
94
95 Py_DECREF(args);
96
97 if (ret == NULL) {
98 PyErr_Print();
99 return 1;
100 }
101
102 if (ret == Py_None) {
103 return 0;
104 } else if (PyInt_Check(ret)) {
105 return PyInt_AsLong(ret);
106 } else {
107 fprintf(stderr, "Function return value type unexpected.\n");
108 return -1;
109 }
110}
111
112static PyObject *py_commands(void)
113{
114 PyObject *netcmd_module, *py_cmds;
115 netcmd_module = PyImport_ImportModule("samba.netcmd");
116 if (netcmd_module == NULL) {
117 PyErr_Print();
118 return NULL;
119 }
120
121 py_cmds = PyObject_GetAttrString(netcmd_module, "commands");
122 if (py_cmds == NULL) {
123 PyErr_Print();
124 return NULL;
125 }
126
127 if (!PyDict_Check(py_cmds)) {
128 d_printf("Python net commands is not a dictionary\n");
129 return NULL;
130 }
131
132 return py_cmds;
133}
134
135/*
136 run a function from a function table. If not found then
137 call the specified usage function
138*/
139int net_run_function(struct net_context *ctx,
140 int argc, const char **argv,
141 const struct net_functable *functable,
142 int (*usage_fn)(struct net_context *ctx, int argc, const char **argv))
143{
144 int i;
145
146 if (argc == 0) {
147 return usage_fn(ctx, argc, argv);
148
149 } else if (argc == 1 && strequal(argv[0], "help")) {
150 return net_help(ctx, functable);
151 }
152
153 for (i=0; functable[i].name; i++) {
154 if (strcasecmp_m(argv[0], functable[i].name) == 0)
155 return functable[i].fn(ctx, argc-1, argv+1);
156 }
157
158 d_printf("No command: '%s'\n", argv[0]);
159 return usage_fn(ctx, argc, argv);
160}
161
162/*
163 run a usage function from a function table. If not found then fail
164*/
165int net_run_usage(struct net_context *ctx,
166 int argc, const char **argv,
167 const struct net_functable *functable)
168{
169 int i;
170 PyObject *py_cmds, *py_cmd;
171
172 for (i=0; functable[i].name; i++) {
173 if (strcasecmp_m(argv[0], functable[i].name) == 0)
174 if (functable[i].usage) {
175 return functable[i].usage(ctx, argc-1, argv+1);
176 }
177 }
178
179 py_cmds = py_commands();
180 if (py_cmds == NULL) {
181 return 1;
182 }
183
184 py_cmd = PyDict_GetItemString(py_cmds, argv[0]);
185 if (py_cmd != NULL) {
186 return py_call_with_string_args(py_cmd, "usage", argc-1,
187 argv+1);
188 }
189
190 d_printf("No usage information for command: %s\n", argv[0]);
191
192 return 1;
193}
194
195
196/* main function table */
197static const struct net_functable net_functable[] = {
198 {"password", "Changes/Sets the password on a user account [server connection needed]\n", net_password, net_password_usage},
199 {"samdump", "dump the sam of a domain\n", net_samdump, net_samdump_usage},
200 {"samsync", "synchronise into the local ldb the sam of an NT4 domain\n", net_samsync_ldb, net_samsync_ldb_usage},
201 {"gpo", "Administer group policies\n", net_gpo, net_gpo_usage},
202 {NULL, NULL, NULL, NULL}
203};
204
205static int net_help_builtin(const struct net_functable *ftable)
206{
207 int i = 0;
208 const char *name = ftable[i].name;
209 const char *desc = ftable[i].desc;
210
211 while (name && desc) {
212 if (strlen(name) > 7) {
213 d_printf("\t%s\t%s", name, desc);
214 } else {
215 d_printf("\t%s\t\t%s", name, desc);
216 }
217 name = ftable[++i].name;
218 desc = ftable[i].desc;
219 }
220 return 0;
221}
222
223static int net_help_python(void)
224{
225 PyObject *py_cmds;
226 PyObject *key, *value;
227 Py_ssize_t pos = 0;
228
229 py_cmds = py_commands();
230 if (py_cmds == NULL) {
231 return 1;
232 }
233
234 while (PyDict_Next(py_cmds, &pos, &key, &value)) {
235 char *name, *desc;
236 PyObject *py_desc;
237 if (!PyString_Check(key)) {
238 d_printf("Command name not a string\n");
239 return 1;
240 }
241 name = PyString_AsString(key);
242 py_desc = PyObject_GetAttrString(value, "description");
243 if (py_desc == NULL) {
244 PyErr_Print();
245 return 1;
246 }
247 if (!PyString_Check(py_desc)) {
248 d_printf("Command description for %s not a string\n",
249 name);
250 return 1;
251 }
252 desc = PyString_AsString(py_desc);
253 if (strlen(name) > 7) {
254 d_printf("\t%s\t%s\n", name, desc);
255 } else {
256 d_printf("\t%s\t\t%s\n", name, desc);
257 }
258 }
259 return 0;
260}
261
262int net_help(struct net_context *ctx, const struct net_functable *ftable)
263{
264 d_printf("Available commands:\n");
265 net_help_builtin(ftable);
266 net_help_python();
267 return 0;
268}
269
270static int net_usage(struct net_context *ctx, int argc, const char **argv)
271{
272 d_printf("Usage:\n");
273 d_printf("samba-tool <command> [options]\n");
274 net_help(ctx, net_functable);
275 return -1;
276}
277
278/****************************************************************************
279 main program
280****************************************************************************/
281static int binary_net(int argc, const char **argv)
282{
283 int opt,i;
284 int rc;
285 int argc_new;
286 PyObject *py_cmds, *py_cmd;
287 const char **argv_new;
288 struct tevent_context *ev;
289 struct net_context *ctx = NULL;
290 poptContext pc;
291 struct poptOption long_options[] = {
292 POPT_AUTOHELP
293 POPT_COMMON_SAMBA
294 POPT_COMMON_CONNECTION
295 POPT_COMMON_CREDENTIALS
296 POPT_COMMON_VERSION
297 { NULL }
298 };
299
300 setlinebuf(stdout);
301
302 dcerpc_init(cmdline_lp_ctx);
303
304 ev = s4_event_context_init(NULL);
305 if (!ev) {
306 d_printf("Failed to create an event context\n");
307 exit(1);
308 }
309 Py_Initialize();
310 PySys_SetArgv(argc, discard_const_p(char *, argv));
311 py_update_path(); /* Put the Samba path at the start of sys.path */
312
313 py_cmds = py_commands();
314 if (py_cmds == NULL) {
315 return 1;
316 }
317
318 for (i=1; i<argc; i++) {
319 if (argv[i][0] != '-') {
320 py_cmd = PyDict_GetItemString(py_cmds, argv[i]);
321 if (py_cmd != NULL) {
322 rc = py_call_with_string_args(py_cmd, "_run",
323 argc-1, argv+1);
324 talloc_free(ev);
325 return rc;
326 }
327 }
328 }
329
330 pc = poptGetContext("net", argc, (const char **) argv, long_options,
331 POPT_CONTEXT_KEEP_FIRST);
332
333 while((opt = poptGetNextOpt(pc)) != -1) {
334 switch (opt) {
335 default:
336 d_printf("Invalid option %s: %s\n",
337 poptBadOption(pc, 0), poptStrerror(opt));
338 net_usage(ctx, argc, argv);
339 exit(1);
340 }
341 }
342
343 argv_new = (const char **)poptGetArgs(pc);
344
345 argc_new = argc;
346 for (i=0; i<argc; i++) {
347 if (argv_new[i] == NULL) {
348 argc_new = i;
349 break;
350 }
351 }
352
353 if (argc_new < 2) {
354 return net_usage(ctx, argc, argv);
355 }
356
357
358 ctx = talloc(ev, struct net_context);
359 if (!ctx) {
360 d_printf("Failed to talloc a net_context\n");
361 exit(1);
362 }
363
364 ZERO_STRUCTP(ctx);
365 ctx->lp_ctx = cmdline_lp_ctx;
366 ctx->credentials = cmdline_credentials;
367 ctx->event_ctx = ev;
368
369
370
371 rc = net_run_function(ctx, argc_new-1, argv_new+1, net_functable,
372 net_usage);
373
374 if (rc != 0) {
375 DEBUG(0,("return code = %d\n", rc));
376 }
377
378 talloc_free(ev);
379 return rc;
380}
381
382 int main(int argc, const char **argv)
383{
384 return binary_net(argc, argv);
385}
Note: See TracBrowser for help on using the repository browser.