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