s4:net utility - add a notice for the "help" operation and format it's output of...
[ira/wip.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
10    Largely rewritten by metze in August 2004
11
12    Originally written by Steve and Jim. Largely rewritten by tridge in
13    November 2001.
14
15    Reworked again by abartlet in December 2001
16
17    This program is free software; you can redistribute it and/or modify
18    it under the terms of the GNU General Public License as published by
19    the Free Software Foundation; either version 3 of the License, or
20    (at your option) any later version.
21    
22    This program is distributed in the hope that it will be useful,
23    but WITHOUT ANY WARRANTY; without even the implied warranty of
24    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25    GNU General Public License for more details.
26    
27    You should have received a copy of the GNU General Public License
28    along with this program.  If not, see <http://www.gnu.org/licenses/>.
29 */
30  
31 /*****************************************************/
32 /*                                                   */
33 /*   Distributed SMB/CIFS Server Management Utility  */
34 /*                                                   */
35 /*   The intent was to make the syntax similar       */
36 /*   to the NET utility (first developed in DOS      */
37 /*   with additional interesting & useful functions  */
38 /*   added in later SMB server network operating     */
39 /*   systems).                                       */
40 /*                                                   */
41 /*****************************************************/
42
43 #include "includes.h"
44 #include "utils/net/net.h"
45 #include "lib/cmdline/popt_common.h"
46 #include "lib/ldb/include/ldb.h"
47 #include "librpc/rpc/dcerpc.h"
48 #include "param/param.h"
49 #include "lib/events/events.h"
50 #include "auth/credentials/credentials.h"
51
52 /*
53   run a function from a function table. If not found then
54   call the specified usage function 
55 */
56 int net_run_function(struct net_context *ctx,
57                         int argc, const char **argv,
58                         const struct net_functable *functable, 
59                         int (*usage_fn)(struct net_context *ctx, int argc, const char **argv))
60 {
61         int i;
62
63         if (argc == 0) {
64                 return usage_fn(ctx, argc, argv);
65
66         } else if (argc == 1 && strequal(argv[0], "help")) {
67                 return net_help(ctx, functable);
68         }
69
70         for (i=0; functable[i].name; i++) {
71                 if (strcasecmp_m(argv[0], functable[i].name) == 0)
72                         return functable[i].fn(ctx, argc-1, argv+1);
73         }
74
75         d_printf("No command: %s\n", argv[0]);
76         return usage_fn(ctx, argc, argv);
77 }
78
79 /*
80   run a usage function from a function table. If not found then fail
81 */
82 int net_run_usage(struct net_context *ctx,
83                         int argc, const char **argv,
84                         const struct net_functable *functable)
85 {
86         int i;
87
88         for (i=0; functable[i].name; i++) {
89                 if (strcasecmp_m(argv[0], functable[i].name) == 0)
90                         if (functable[i].usage) {
91                                 return functable[i].usage(ctx, argc-1, argv+1);
92                         }
93         }
94
95         d_printf("No usage information for command: %s\n", argv[0]);
96
97         return 1;
98 }
99
100
101 /* main function table */
102 static const struct net_functable net_functable[] = {
103         {"password", "change password\n", net_password, net_password_usage},
104         {"time", "get remote server's time\n", net_time, net_time_usage},
105         {"join", "join a domain\n", net_join, net_join_usage},
106         {"samdump", "dump the sam of a domain\n", net_samdump, net_samdump_usage},
107         {"export", "dump the sam of this domain\n", net_export, net_export_usage},
108         {"vampire", "join and syncronise an AD domain onto the local server\n", net_vampire, net_vampire_usage},
109         {"samsync", "synchronise into the local ldb the sam of an NT4 domain\n", net_samsync_ldb, net_samsync_ldb_usage},
110         {"user", "manage user accounts\n", net_user, net_user_usage},
111         {"machinepw", "Get a machine password out of our SAM\n", net_machinepw, net_machinepw_usage},
112         {NULL, NULL, NULL, NULL}
113 };
114
115 int net_help(struct net_context *ctx, const struct net_functable *ftable)
116 {
117         int i = 0;
118         const char *name = ftable[i].name;
119         const char *desc = ftable[i].desc;
120
121         d_printf("Available commands:\n");
122         while (name && desc) {
123                 if (strlen(name) > 7) {
124                         d_printf("\t%s\t%s", name, desc);
125                 } else {
126                         d_printf("\t%s\t\t%s", name, desc);
127                 }
128                 name = ftable[++i].name;
129                 desc = ftable[i].desc;
130         }
131
132         return 0;
133 }
134
135 static int net_usage(struct net_context *ctx, int argc, const char **argv)
136 {
137         d_printf("Usage:\n");
138         d_printf("net <command> [options]\n");
139         d_printf("Type 'net help' for all available commands\n");
140         return 0;
141 }
142
143 /****************************************************************************
144   main program
145 ****************************************************************************/
146 static int binary_net(int argc, const char **argv)
147 {
148         int opt,i;
149         int rc;
150         int argc_new;
151         const char **argv_new;
152         struct tevent_context *ev;
153         struct net_context *ctx = NULL;
154         poptContext pc;
155         struct poptOption long_options[] = {
156                 POPT_AUTOHELP
157                 POPT_COMMON_SAMBA
158                 POPT_COMMON_CONNECTION
159                 POPT_COMMON_CREDENTIALS
160                 POPT_COMMON_VERSION
161                 { NULL }
162         };
163
164         setlinebuf(stdout);
165
166         pc = poptGetContext("net", argc, (const char **) argv, long_options, 
167                             POPT_CONTEXT_KEEP_FIRST);
168
169         while((opt = poptGetNextOpt(pc)) != -1) {
170                 switch (opt) {
171                 default:
172                         d_printf("Invalid option %s: %s\n", 
173                                  poptBadOption(pc, 0), poptStrerror(opt));
174                         net_usage(ctx, argc, argv);
175                         exit(1);
176                 }
177         }
178
179         argv_new = (const char **)poptGetArgs(pc);
180
181         argc_new = argc;
182         for (i=0; i<argc; i++) {
183                 if (argv_new[i] == NULL) {
184                         argc_new = i;
185                         break;
186                 }
187         }
188
189         if (argc_new < 2) {
190                 return net_usage(ctx, argc, argv);
191         }
192
193         dcerpc_init(cmdline_lp_ctx);
194
195         ev = s4_event_context_init(NULL);
196         if (!ev) {
197                 d_printf("Failed to create an event context\n");
198                 exit(1);
199         }
200         ctx = talloc(ev, struct net_context);
201         if (!ctx) {
202                 d_printf("Failed to talloc a net_context\n");
203                 exit(1);
204         }
205
206         ZERO_STRUCTP(ctx);
207         ctx->lp_ctx = cmdline_lp_ctx;
208         ctx->credentials = cmdline_credentials;
209         ctx->event_ctx = ev;
210
211         rc = net_run_function(ctx, argc_new-1, argv_new+1, net_functable, net_usage);
212
213         if (rc != 0) {
214                 DEBUG(0,("return code = %d\n", rc));
215         }
216
217         talloc_free(ev);
218         return rc;
219 }
220
221  int main(int argc, const char **argv)
222 {
223         return binary_net(argc, argv);
224 }