224de31ebf5578ca62e244435e2a8d9580c5e64b
[ira/wip.git] / source3 / utils / net.c
1 /* 
2    Samba Unix/Linux SMB client library 
3    Version 3.0
4    Distributed SMB/CIFS Server Management Utility 
5    Copyright (C) 2001 Steve French  (sfrench@us.ibm.com)
6    Copyright (C) 2001 Jim McDonough (jmcd@us.ibm.com)
7    Copyright (C) 2001 Andrew Tridgell (tridge@samba.org)
8
9    Originally written by Steve and Jim. Largely rewritten by tridge in
10    November 2001.
11
12    This program is free software; you can redistribute it and/or modify
13    it under the terms of the GNU General Public License as published by
14    the Free Software Foundation; either version 2 of the License, or
15    (at your option) any later version.
16    
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20    GNU General Public License for more details.
21    
22    You should have received a copy of the GNU General Public License
23    along with this program; if not, write to the Free Software
24    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
25  
26 /*****************************************************/
27 /*                                                   */
28 /*   Distributed SMB/CIFS Server Management Utility  */
29 /*                                                   */
30 /*   The intent was to make the syntax similar       */
31 /*   to the NET utility (first developed in DOS      */
32 /*   with additional interesting & useful functions  */
33 /*   added in later SMB server network operating     */
34 /*   systems).                                       */
35 /*                                                   */
36 /*****************************************************/
37
38 #include "includes.h"
39
40 /***********************************************************************/
41 /* Beginning of internationalization section.  Translatable constants  */
42 /* should be kept in this area and referenced in the rest of the code. */
43 /*                                                                     */
44 /* No functions, outside of Samba or LSB (Linux Standards Base) should */
45 /* be used (if possible).                                              */
46 /***********************************************************************/
47
48 #define PASSWORD_PROMPT         "Password: "
49 #define YES_STRING              "Yes"
50 #define NO_STRING               "No"
51
52 #define NET_USAGE \
53     "\nUsage: \n"\
54     "  net domain \tto list domains \n"\
55     "  net file \tto list open files on a server \n"\
56     "  net group \tto list user groups  \n"\
57     "  net groupmember to list users in a group \n"\
58     "  net password\t to change the password of a user\n"\
59     "  net printq \tto list the print queues on a server\n"\
60     "  net server \tto list servers in a domain\n"\
61     "  net session \tto list clients with open sessions to a server\n"\
62     "  net share \tto list shares exported by a server\n"\
63     "  net user \tto list users\n"\
64     "  net validate \tto check whether a user and the corresponding password are valid\n"\
65     "  net help\n"\
66     "\nType \"net help <option>\" to get more information on that option\n"
67
68 #define NET_FILE_USAGE \
69     "\nnet file [misc. options] [targets]"\
70     "\n\tenumerates all open files on file server\n"\
71     "\nnet file USER <username> [misc. options] [targets]"\
72     "\n\tenumerates all files opened by username on file server\n"\
73     "\nnet file CLOSE <id> [misc. options] [targets]"\
74     "\n\tcloses specified file on target server\n"
75
76 #define FILE_INFO_DISPLAY \
77     "File ID          %d\n"\
78     "User name        %s\n"\
79     "Locks            0x%-4.2x\n"\
80     "Path             %s\n"\
81     "Permissions      0x%x\n"
82 #define FILE_ENUM_DISPLAY \
83     "\nEnumerating open files on remote server:\n\n"\
84     "\n\tFileId  Opened by            Perms  Locks  Path \n"\
85     "\t------  ---------            -----  -----  ---- \n"
86
87 #define NET_SHARE_USAGE \
88     "\nnet share [misc. options] [targets] \n"\
89     "\tenumerates all exported resources (network shares) on target server\n"\
90     "\nnet share ADD <name=serverpath> [misc. options] [targets]"\
91     "\n\tAdd a share from a server (makes the export active)\n"\
92     "\nnet share DELETE <sharename> [misc. options] [targets]\n"\
93     "\tor"\
94     "\nnet share CLOSE <sharename> [misc. options] [targets]"\
95     "\n\tDeletes a share from a server (makes the export inactive)\n"
96     
97 #define SHARE_ENUM_DISPLAY \
98     "\nEnumerating shared resources (exports) on remote server:\n\n"\
99     "\nShare name   Type     Description\n"\
100     "----------   ----     -----------\n"
101
102
103 #define NET_SESSION_USAGE \
104     "\nnet session [misc. options] [targets]"\
105     "\n\tenumerates all active SMB/CIFS sessions on target server\n"\
106     "\nnet session DELETE <client_name> [misc. options] [targets] \n"\
107     "\tor"\
108     "\nnet session CLOSE <client_name> [misc. options] [targets]"\
109     "\n\tDeletes (closes) a session from specified client to server\n"
110
111 #define SESSION_ENUM_DISPLAY \
112     "Computer             User name            Client Type        Opens Idle time\n\n"\
113     "------------------------------------------------------------------------------\n"
114
115
116 #define SESSION_DISPLAY_ONE \
117     "User name       %-20.20s\n"\
118     "Computer        %-20.20s\n"\
119     "Guest logon     %-20.20s\n"\
120     "Client Type     %-40.40s\n"\
121     "Sess time       %2.2d:%2.2d:%2.2d\n"\
122     "Idle time       %2.2d:%2.2d:%2.2d\n"
123
124 #define SESSION_DISPLAY_CONNS \
125     "Share name     Type     # Opens\n"\
126     "------------------------------------------------------------------------------\n"
127
128 #define NET_SERVER_USAGE \
129     "\nUsage:\n"\
130     "  net server [domain]\tlists the servers in the specified domain or workgroup.\n"\
131     "    If domain is not specified, it uses the current domain or workgroup as\n"\
132     "    the default.\n"
133
134 #define SERVER_ENUM_DISPLAY "\nEnumerating servers in this domain or workgroup: \n\n"  \
135     "\n\tServer name          Server description\n"\
136     "\t-------------        ----------------------------\n"
137
138
139 #define NET_DOMAIN_USAGE \
140     "\nUsage:\n"\
141     "  net domain [misc. options] [target]\n\tlists the domains "\
142     "or workgroups visible on the current network\n"
143
144 #define DOMAIN_ENUM_DISPLAY \
145     "\nEnumerating domains:\n\n"\
146     "\n\tDomain name          Server name of Browse Master\n"\
147     "\t-------------        ----------------------------\n"
148
149 #define NET_PRINTQ_USAGE \
150     "\nUsage:\n"\
151     " net printq [misc. options] [targets]\n"\
152     "\tor\n"\
153     " net printq list [<queue_name>] [misc. options] [targets]\n"\
154     "\tlists the specified queue and jobs on the target server.\n"\
155     "\tIf the queue name is not specified, all queues are listed.\n\n"\
156     " net printq delete [<queue name>] [misc. options] [targets]\n"\
157     "\tdeletes the specified job number on the target server, or the\n"\
158     "\tprinter queue if no job number is specified\n"
159 #define PRINTQ_ENUM_DISPLAY \
160     "Print queues at \\\\%s\n\n"\
161     "Name                         Job #      Size            Status\n\n"\
162     "------------------------------------------------------------------"\
163     "-------------\n"
164 #define PRINTQ_DISPLAY_ONE "%-23.23s %5d jobs                      %-22.22s\n"
165 #define PRINTQ_PRINTER_ACTIVE "*Printer Active*"
166 #define PRINTQ_PRINTER_PAUSED "*Printer Paused*"
167 #define PRINTQ_PRINTER_ERROR "*Printer error*"
168 #define PRINTQ_PRINTER_DELPEND "*Delete Pending*"
169 #define PRINTQ_PRINTER_STATUNK "**UNKNOWN STATUS**"
170 #define PRINTQ_DISPLAY_JOB "     %-23.23s %5d %9d            %-22.22s\n"
171 #define PRINTQ_JOB_PRINTING "Printing"
172 #define PRINTQ_JOB_QUEUED "Waiting"
173 #define PRINTQ_JOB_PAUSED "Held in queue"
174 #define PRINTQ_JOB_SPOOLING "Spooling"
175 #define PRINTQ_QUEUE_WORD " Queue"
176
177 #define NET_USER_USAGE \
178     "\nnet user [misc. options] [targets]\n\tEnumerate users\n"\
179     "\nnet user DELETE <name> [misc. options] [targets]"\
180     "\n\tDelete specified user\n"\
181     "\nnet user INFO <name> [misc. options] [targets]"\
182     "\n\tList the domain groups of the specified user\n"\
183     "\nnet user ADD <name> [-F user flags] [misc. options] [targets]"\
184     "\n\tAdd specified user\n"
185
186 #define USER_ENUM_DISPLAY \
187     "\nEnumerating shared resources (exports) on remote server:\n\n"\
188     "\nUser name             Description                                     Home Directory                          Profile Directory\n"\
189     "---------             -----------                                     --------------                          -----------------\n"
190
191 #define NET_GROUP_USAGE \
192     "\nnet group [misc. options] [targets]"\
193     "\n\tEnumerate user groups\n"\
194     "\nnet group DELETE <name> [misc. options] [targets]"\
195     "\n\tDelete specified group\n"\
196     "\nnet group ADD <name> [-C comment] [misc. options] [targets]"\
197     "\n\tCreate specified group\n"
198
199 #define NET_GROUPMEMBER_USAGE \
200     "\nnet groupmember LIST <group name> [misc. options] [targets]"\
201     "\n\t Enumerate users in a group\n"\
202     "\nnet groupmember DELETE <group name> <user name> [misc. options] "\
203     "[targets]\n\t Delete sepcified user from specified group\n"\
204     "\nnet groupmember ADD <group name> <user name> [misc. options] [targets]"\
205     "\n\t Add specified user to specified group\n"
206
207             
208 #define NET_ADMIN_USAGE \
209     "\nnet admin <remote command to execute> [cmd arguments [environment]] [misc_options] [targets]\n"\
210     "\texecutes a remote command on an os/2 target server\n"
211     
212 #define NET_PASSWORD_USAGE \
213     "\nnet password <user> <old password> <new password> [misc_options] [targets]\n"\
214     "\tchanges the password for the specified user on a remote server\n"
215
216 #define NET_SERVICE_USAGE \
217     "\nnet service [misc. options] [targets] \n"\
218     "\tenumerates all running service daemons on target server\n"\
219     "\nnet service ADD <name> [service startup arguments] [misc. options] [targets]"\
220     "\n\tStart named service on remote server\n"\
221     "\nnet service DELETE <name> [misc. options] [targets]\n"\
222     "\n\tStop named service on remote server\n"
223     
224
225 #define NET_VALIDATE_USAGE \
226     "\nnet validate <username> [password]\n"\
227     "\tValidate user and password to check whether they can access target server or domain\n"
228
229 #define TARGET_USAGE      "\nValid targets: choose one (none defaults to using the %s)\n"
230 #define GLBL_LCL_MASTER   "global browsemaster or local browse master if that is not found"
231 #define DOMAIN_MASTER     "local domain browse master"
232 #define LOCAL_HOST        "localhost"
233 #define MISC_OPT_USAGE    "\nValid miscellaneous options are:\n"
234 #define SERVER_USAGE      "\t-S or --server=<server>\t\tserver name\n"
235 #define IPADDRESS_USAGE   "\t-I or --ipaddress=<ipaddr>\tip address of target server\n"
236 #define PORT_USAGE        "\t-p or --port=<port number>\tconnection port on target server\n"
237 #define WORKGROUP_USAGE   "\t-w or --workgroup=<wg>\t\ttarget workgroup or domain name\n"
238 #define COMMENT_USAGE     "\t-C or --comment=<comment>\tdescriptive comment (for add only)\n"
239 #define MYWORKGROUP_USAGE "\t-W or --myworkgroup=<wg>\tclient workgroup\n"
240 #define DEBUG_USAGE       "\t-d or --debug=<level>\t\tdebug level (0-10)\n"
241 #define MYNAME_USAGE      "\t-n or --myname=<name>\t\tclient name\n"
242 #define USER_USAGE        "\t-U or --user=<name>\t\tuser name\n"
243 #define CONF_USAGE        "\t-s or --conf=<path>\t\tpathname of smb.conf file\n"
244 #define JOBID_USAGE       "\t-j or --jobid=<job id>\t\tjob id\n"
245 #define MAXUSERS_USAGE    "\t-M or --maxusers=<num>\t\tmax users allowed for share\n"
246 #define LONG_USAGE        "\t-l or --long\t\t\tDisplay full information\n"
247
248 #define ERRMSG_NOCONN_TARGET_SRVR       "\nUnable to connect to target server\n"
249 #define ERRMSG_NOCONN_BROWSE_MSTR       "\nUnable to connect to browse master\n"
250 #define ERRMSG_NOT_IMPLEMENTED          "\nNot implemented\n"
251 #define ERRMSG_FILEID_MISSING           "\nMissing fileid of file to close\n\n"
252 #define ERRMSG_GROUPNAME_MISSING        "\n\nGroup name not specified\n"
253 #define ERRMSG_USERNAME_MISSING        "\n\nUser name not specified\n"
254 #define ERRMSG_SHARENAME_MISSING        "\n\nShare name not specified\n"
255 #define ERRMSG_TARGET_WG_NOT_VALID      "\nTarget workgroup option not valid "\
256                                         "except on net server command, ignored"
257 #define ERRMSG_INVALID_HELP_OPTION      "\nInvalid help option\n"
258 #define ERRMSG_INVALID_OPTION           "\nInvalid option %c (%d)\n"
259 #define ERRMSG_INVALID_IPADDRESS        "\nInvalid ip address specified\n"
260 #define ERRMSG_SPURIOUS_PARM            "\nInvalid paramater ignored: %s\n"
261 #define ERRMSG_BOTH_SERVER_IPADDRESS    "\nTarget server and IP address both "\
262   "specified. Do not set both at the same time.  The target IP address was used\n"
263 #define ERRMSG_INVALID_DOMAIN_ACTION    "\nInvalid action for NET DOMAIN command"\
264   " ignored. Only listing domains permitted.\n"
265
266 /* Column headers */
267 #define COMMENT_STR   "Comment "
268 #define USER_STR      "User name "
269 #define GROUP_STR     "Group name "  
270 #define SERVICE_STR   "Service name"
271 #define HOMED_STR     "Home directory "
272 #define LOGONS_STR    "Logon script "
273
274 #define FLAGS_MASTER 1
275 #define FLAGS_DMB 2
276
277 static const char *share_type[] = {
278   "Disk",
279   "Print",
280   "Dev",
281   "IPC"
282 };
283
284 /************************************************************************************/
285 /*                       end of internationalization section                        */
286 /************************************************************************************/
287
288 extern int optind, opterr, optopt;
289 extern struct in_addr ipzero;
290
291 static struct cli_state *cli;
292 static char *opt_requester_name;
293 static char *opt_host; 
294 static char *opt_password;
295 static char *opt_user_name;
296 static char *opt_workgroup;
297 static int opt_long_list_entries;
298 static int opt_port;
299 static int opt_maxusers = -1;
300 static char *opt_comment = "";
301 static int opt_flags = -1;
302 static int opt_jobid;
303 static char *opt_target_workgroup;
304
305 static BOOL got_pass = False;
306 static BOOL have_ip = False;
307 static struct in_addr dest_ip;
308
309 /*
310   run a function from a function table. If not found then
311   call the specified usage function 
312 */
313 int net_run_function(int argc, const char **argv, struct functable *table, 
314                      int (*usage_fn)(void))
315 {
316         int i;
317         if (argc < 1) {
318                 return usage_fn();
319         }
320         for (i=0; table[i].funcname; i++) {
321                 if (StrCaseCmp(argv[0], table[i].funcname) == 0) {
322                         return table[i].fn(argc-1, argv+1);
323                 }
324         }
325         d_printf("No command: %s\n", argv[0]);
326         return usage_fn();
327 }
328
329
330 /****************************************************************************
331 connect to \\server\ipc$  
332 ****************************************************************************/
333 static struct cli_state *connect_to_ipc(char *server)
334 {
335         struct cli_state *c;
336         struct nmb_name called, calling;
337         struct in_addr ip;
338         char *server_n;
339         fstring servicename;
340         char *sharename;
341
342         /* make a copy so we don't modify the global string 'service' */
343         safe_strcpy(servicename, "IPC$", sizeof(servicename)-1);
344         sharename = servicename;
345         if (*sharename == '\\') {
346                 server = sharename+2;
347                 sharename = strchr(server,'\\');
348                 if (!sharename) return NULL;
349                 *sharename = 0;
350                 sharename++;
351         }
352         
353         if(server == NULL)
354                 return NULL;  /* if ip addr specified, ascii version of ip address is used as host name */
355         
356         server_n = server; 
357         
358         ip = ipzero;
359         make_nmb_name(&calling, opt_requester_name, 0x0);
360         make_nmb_name(&called , server, 0x20);
361         
362 again:
363         if (have_ip)
364                 ip = dest_ip;
365         else ip = ipzero;
366         
367         DEBUG(3,("Connecting to host=%s\\share=%s\n\n", 
368                  server, "IPC$"));
369         
370         /* have to open a new connection */
371         if (!(c=cli_initialise(NULL)) || cli_set_port(c, opt_port) != opt_port ||
372             !cli_connect(c, server_n, &ip)) {
373                 DEBUG(1,("Connection to %s failed\n", server_n));
374                 return NULL;
375         }
376         
377         c->protocol = PROTOCOL_NT1;
378         
379         if (!cli_session_request(c, &calling, &called)) {
380                 char *p;
381                 DEBUG(1,("session request to %s failed (%s)\n", 
382                          called.name, cli_errstr(c)));
383                 cli_shutdown(c);
384                 SAFE_FREE(c);
385                 if ((p=strchr(called.name, '.'))) {
386                         *p = 0;
387                         goto again;
388                 }
389                 if (strcmp(called.name, "*SMBSERVER")) {
390                         make_nmb_name(&called , "*SMBSERVER", 0x20);
391                         goto again;
392                 }
393                 return NULL;
394         }
395         
396         DEBUG(4,(" session request ok\n"));
397         
398         if (!cli_negprot(c)) {
399                 DEBUG(1,("protocol negotiation failed\n"));
400                 cli_shutdown(c);
401                 SAFE_FREE(c);
402                 return NULL;
403         }
404         
405         if (!got_pass) {
406                 char *pass = getpass(PASSWORD_PROMPT);
407                 if (pass) {
408                         opt_password = strdup(pass);
409                 }
410         }
411         
412         if (!cli_session_setup(c, opt_user_name, 
413                                opt_password, strlen(opt_password),
414                                opt_password, strlen(opt_password),
415                                opt_workgroup)) {
416                 /*  try again with a null username */
417                 if (!cli_session_setup(c, "", "", 0, "", 0, opt_workgroup)) { 
418                         DEBUG(1,("session setup failed: %s\n", cli_errstr(c)));
419                         cli_shutdown(c);
420                         SAFE_FREE(c);
421                         return NULL;
422                 }
423                 DEBUG(3,("Anonymous login successful\n"));
424         }
425         
426         DEBUG(4,(" session setup ok\n"));
427         if (!cli_send_tconX(c, sharename, "?????",
428                             opt_password, strlen(opt_password)+1)) {
429                 DEBUG(1,("tree connect failed: %s\n", cli_errstr(c)));
430                 cli_shutdown(c);
431                 SAFE_FREE(c);
432                 return NULL;
433         }
434         
435         DEBUG(4,(" tconx ok\n"));
436         
437         return c;
438 }
439
440 static BOOL make_ipc_connection(unsigned flags)
441 {
442         if (!opt_host && have_ip) {
443                 opt_host = strdup(inet_ntoa(dest_ip));
444         } else if (!opt_host && (flags & FLAGS_DMB)) {
445                 struct in_addr *ip_list;
446                 int addr_count;
447                 char *our_workgroup = lp_workgroup();
448                 struct in_addr msbrow_ip;
449                 /*  if (!resolve_name(MSBROWSE, &msbrow_ip, 1)) */
450                 if (!get_dmb_list(&ip_list,&addr_count)){
451                         DEBUG(1,("Unable to resolve global master browser via name lookup"));
452                         if (!resolve_name(our_workgroup, &msbrow_ip, 0x1D))  {
453                                 DEBUG(1,("Unable to resolve domain browser via name lookup\n"));
454                                 return False;
455                         } else {
456                                 have_ip = True;
457                                 dest_ip = msbrow_ip;
458                         }
459                 } else {
460                         have_ip = True;
461                         dest_ip = *ip_list;
462                 }
463         } else if (!opt_host && (flags & FLAGS_MASTER)) {
464                 char *temp_workgroup = lp_workgroup();
465                 char our_workgroup[16];
466                 struct in_addr brow_ips;
467
468                 /* find target server based on workgroup or domain */
469                 if((temp_workgroup == 0) || (temp_workgroup[0] == 0)) 
470                         temp_workgroup = lp_workgroup();  /* by default enum our local workgroup or domain */
471                 
472                 safe_strcpy(our_workgroup, temp_workgroup,15);
473                 
474                 if (!resolve_name(our_workgroup, &brow_ips, 0x1D))  {
475                                 /* go looking for workgroups */
476                         DEBUG(1,("Unable to resolve master browser via name lookup\n"));
477                         return False;
478                 } else {
479                         have_ip = True;
480                         dest_ip = brow_ips;
481                 }
482         } else {
483                 extern struct in_addr loopback_ip;
484                 dest_ip = loopback_ip;
485                 have_ip = True;
486         }
487
488         if (!opt_host && !have_ip) {
489                 DEBUG(1,("no server to connect to\n"));
490                 return False;
491         }
492         if (!opt_host) {
493                 opt_host = strdup(inet_ntoa(dest_ip));
494         }
495         
496         cli = connect_to_ipc(opt_host);
497         if(!cli) {
498                 d_printf(ERRMSG_NOCONN_TARGET_SRVR);
499                 return False;
500         }
501         return True;
502 }
503
504
505 static int general_usage(void)
506 {
507         d_printf(TARGET_USAGE, LOCAL_HOST); /* target options */
508         d_printf(SERVER_USAGE);
509         d_printf(IPADDRESS_USAGE);
510         
511         d_printf(MISC_OPT_USAGE); /* misc options */
512         d_printf(PORT_USAGE);
513         d_printf(MYWORKGROUP_USAGE);
514         d_printf(DEBUG_USAGE);
515         d_printf(MYNAME_USAGE);
516         d_printf(USER_USAGE);
517         d_printf(CONF_USAGE);
518         return -1;
519 }
520
521 static int net_usage(void)
522 {
523         d_printf(NET_USAGE);
524         return -1;
525 }
526
527 static int file_usage(void)
528 {
529         d_printf(NET_FILE_USAGE); /* command syntax */
530
531         general_usage();
532         return -1;
533 }
534
535
536
537
538 /***************************************************************************
539   list info on an open file
540 ***************************************************************************/
541 static void file_fn(const char * pPath, const char * pUser, uint16 perms, 
542                     uint16 locks, uint32 id)
543 {
544         d_printf("\t%-7.1d %-20.20s 0x%-4.2x %-6.1d %s\n",
545                  id, pUser, perms, locks, pPath);
546 }
547
548 static void one_file_fn(const char *pPath, const char *pUser, uint16 perms, 
549                         uint16 locks, uint32 id)
550 {
551         d_printf(FILE_INFO_DISPLAY, id, pUser, locks, pPath, perms);
552 }
553
554
555 static int net_file_close(int argc, const char **argv)
556 {
557         if (argc == 0) {
558                 return file_usage();
559         }
560         if (!make_ipc_connection(0)) return -1;
561         return cli_NetFileClose(cli, atoi(argv[0]));
562 }
563
564 static int net_file_info(int argc, const char **argv)
565 {
566         if (argc == 0) {
567                 return file_usage();
568         }
569         if (!make_ipc_connection(0)) return -1;
570         return cli_NetFileGetInfo(cli, atoi(argv[0]), one_file_fn);
571 }
572
573 static int net_file_user(int argc, const char **argv)
574 {
575         if (argc == 0) {
576                 return file_usage();
577         }
578         d_printf("net file user not implemented yet\n");
579         return -1;
580 }
581
582 static int net_file(int argc, const char **argv)
583 {
584         struct functable func[] = {
585                 {"CLOSE", net_file_close},
586                 {"USER", net_file_user},
587                 {"INFO", net_file_info},
588                 {NULL, NULL}
589         };
590         
591         if (argc == 0) {
592                 if (!make_ipc_connection(0)) return -1;
593
594                 /* list open files */
595                 d_printf(FILE_ENUM_DISPLAY); /* file list header */
596                 return cli_NetFileEnum(cli, NULL, NULL, file_fn);
597         }
598
599         return net_run_function(argc, argv, func, file_usage);
600 }
601                        
602 static int share_usage(void)
603 {
604         d_printf(NET_SHARE_USAGE); /* command syntax */
605         general_usage();
606         return -1;
607 }
608
609 static void long_share_fn(const char *share_name, uint32 type, const char *comment, void *state)
610 {
611         d_printf("%-12.12s %-8.8s %-50.50s\n", share_name, share_type[type], comment);
612 }
613
614 static void share_fn(const char *share_name, uint32 type, const char *comment, void *state)
615 {
616         d_printf("%-12.12s\n", share_name);
617 }
618
619 static int net_share_delete(int argc, const char **argv)
620 {
621         if (argc == 0) {
622                 d_printf(ERRMSG_SHARENAME_MISSING);
623                 return -1;
624         }
625         if (!make_ipc_connection(0)) return -1;
626         return cli_NetShareDelete(cli, argv[0]);
627 }
628
629 static int net_share_add(int argc, const char **argv)
630 {
631         RAP_SHARE_INFO_2 sinfo;
632         char *p;
633         char *sharename;
634
635         if (argc == 0) {
636                 d_printf(ERRMSG_SHARENAME_MISSING);
637                 return -1;
638         }
639                         
640         if (!make_ipc_connection(0)) return -1;
641
642         sharename = strdup(argv[0]);
643         p = strchr(sharename, '=');
644         *p = 0;
645         strlcpy(sinfo.share_name, sharename, sizeof(sinfo.share_name));
646         sinfo.reserved1 = '\0';
647         sinfo.share_type = 0;
648         sinfo.comment = opt_comment;
649         sinfo.perms = 0;
650         sinfo.maximum_users = opt_maxusers;
651         sinfo.active_users = 0;
652         sinfo.path = p+1;
653         memset(sinfo.password, '\0', sizeof(sinfo.password));
654         sinfo.reserved2 = '\0';
655         
656         return cli_NetShareAdd(cli, &sinfo);
657 }
658
659
660 static int net_share(int argc, const char **argv)
661 {
662         struct functable func[] = {
663                 {"DELETE", net_share_delete},
664                 {"CLOSE", net_share_delete},
665                 {"ADD", net_share_add},
666                 {NULL, NULL}
667         };
668
669         if (argc == 0) {
670                 if (!make_ipc_connection(0)) return -1;
671                 if (opt_long_list_entries) {
672                         d_printf(SHARE_ENUM_DISPLAY);
673                         return cli_RNetShareEnum(cli, long_share_fn, NULL);
674                 }
675                 return cli_RNetShareEnum(cli, share_fn, NULL);
676         }
677
678         return net_run_function(argc, argv, func, share_usage);
679 }
680                     
681                 
682 static int session_usage(void)
683 {
684         d_printf(NET_SESSION_USAGE); /* command syntax */
685         
686         general_usage();
687         return -1;
688 }
689     
690 static void list_sessions_func(char *wsname, char *username, uint16 conns,
691                         uint16 opens, uint16 users, uint32 sess_time,
692                         uint32 idle_time, uint32 user_flags, char *clitype)
693 {
694         int hrs = idle_time / 3600;
695         int min = (idle_time / 60) % 60;
696         int sec = idle_time % 60;
697         
698         d_printf("\\\\%-18.18s %-20.20s %-18.18s %5d %2.2d:%2.2d:%2.2d\n",
699                  wsname, username, clitype, opens, hrs, min, sec);
700 }
701
702 static void display_session_func(const char *wsname, const char *username, uint16 conns,
703                                  uint16 opens, uint16 users, uint32 sess_time,
704                                  uint32 idle_time, uint32 user_flags, const char *clitype)
705 {
706         int ihrs = idle_time / 3600;
707         int imin = (idle_time / 60) % 60;
708         int isec = idle_time % 60;
709         int shrs = sess_time / 3600;
710         int smin = (sess_time / 60) % 60;
711         int ssec = sess_time % 60;
712         d_printf(SESSION_DISPLAY_ONE, username, wsname, 
713                  (user_flags&0x0)?YES_STRING:NO_STRING, clitype,
714                  shrs, smin, ssec, ihrs, imin, isec);
715 }
716
717 static void display_conns_func(uint16 conn_id, uint16 conn_type, uint16 opens, uint16 users, uint32 conn_time, const char *username, const char *netname)
718 {
719         d_printf("%-14.14s %-8.8s %5d\n", netname, share_type[conn_type], opens);
720 }
721
722 static int net_session_info(int argc, const char **argv)
723 {
724         int res;
725         const char *sessname;
726
727         if (!make_ipc_connection(0)) return -1;
728
729         if (argc == 0) return session_usage();
730
731         sessname = argv[0];
732
733         res = cli_NetSessionGetInfo(cli, sessname, display_session_func);
734         if (res < 0) return res;
735
736         d_printf(SESSION_DISPLAY_CONNS);
737         return cli_NetConnectionEnum(cli, sessname, display_conns_func);
738 }
739
740 static int net_session_delete(int argc, const char **argv)
741 {
742         if (!make_ipc_connection(0)) return -1;
743
744         if (argc == 0) return session_usage();
745
746         return cli_NetSessionDel(cli, argv[0]);
747 }
748
749 static int net_session(int argc, const char **argv)
750 {
751         struct functable func[] = {
752                 {"INFO", net_session_info},
753                 {"DELETE", net_session_delete},
754                 {"CLOSE", net_session_delete},
755                 {NULL, NULL}
756         };
757
758         if (argc == 0) {
759                 if (!make_ipc_connection(0)) return -1;
760                 return cli_NetSessionEnum(cli, list_sessions_func);
761         }
762
763         return net_run_function(argc, argv, func, session_usage);
764 }
765         
766 /****************************************************************************
767 list a server name
768 ****************************************************************************/
769 static void display_server_func(const char *name, uint32 m, const char *comment, void * reserved)
770 {
771         d_printf("\t%-16.16s     %s\n", name, comment);
772 }
773
774
775 static int server_usage(void)
776 {
777         d_printf(NET_SERVER_USAGE); /* command syntax */
778         
779         general_usage();
780         return -1;
781 }
782                     
783 static int net_server(int argc, const char **argv)
784 {
785         if (!make_ipc_connection(FLAGS_MASTER)) return -1;
786         d_printf(SERVER_ENUM_DISPLAY); /* header for list of servers */
787         return cli_NetServerEnum(cli, cli->server_domain, SV_TYPE_ALL, display_server_func,NULL); 
788 }
789                       
790 static int domain_usage(void)
791 {
792         d_printf(NET_DOMAIN_USAGE); /* command syntax */
793         
794         general_usage();
795         return -1;
796 }
797
798                   
799 static int net_domain(int argc, const char **argv)
800 {
801         if (!make_ipc_connection(FLAGS_DMB)) return -1;
802         d_printf(DOMAIN_ENUM_DISPLAY); /* header for list of domains */
803         return cli_NetServerEnum(cli, cli->server_domain, SV_TYPE_DOMAIN_ENUM, display_server_func,NULL);       
804 }
805                       
806 static int printq_usage(void)
807 {
808         d_printf(NET_PRINTQ_USAGE);
809         
810         general_usage();
811         return -1;
812 }       
813
814 static void enum_queue(const char *queuename, uint16 pri, uint16 start, uint16 until, 
815                        const char *sep, const char *pproc, const char *dest, 
816                        const char *qparms, const char *qcomment, uint16 status, 
817                        uint16 jobcount) {
818         pstring queuecol;
819         pstring statcol;
820
821         pstrcpy(queuecol, queuename);
822         pstrcat(queuecol, PRINTQ_QUEUE_WORD);
823         
824         switch (status) {
825         case 0:
826                 pstrcpy(statcol, PRINTQ_PRINTER_ACTIVE);
827                 break;
828         case 1:
829                 pstrcpy(statcol, PRINTQ_PRINTER_PAUSED);
830                 break;
831         case 2:
832                 pstrcpy(statcol, PRINTQ_PRINTER_ERROR);
833                 break;
834         case 3:
835                 pstrcpy(statcol, PRINTQ_PRINTER_DELPEND);
836                 break;
837         default:
838                 pstrcpy(statcol, PRINTQ_PRINTER_STATUNK);
839         }
840         d_printf(PRINTQ_DISPLAY_ONE, queuecol, jobcount, statcol);
841 }
842
843 static void enum_jobs(uint16 jobid, const char *ownername, const char *notifyname, 
844                       const char *datatype, const char *jparms, uint16 pos, 
845                       uint16 status, const char *jstatus, uint submitted, uint jobsize, 
846                       const char *comment) {
847         pstring statcol;
848
849         switch (status) {
850         case 0:
851                 pstrcpy(statcol, PRINTQ_JOB_QUEUED);
852                 break;
853         case 1:
854                 pstrcpy(statcol, PRINTQ_JOB_PAUSED);
855                 break;
856         case 2:
857                 pstrcpy(statcol, PRINTQ_JOB_SPOOLING);
858                 break;
859         case 3:
860                 pstrcpy(statcol, PRINTQ_JOB_PRINTING);
861                 break;
862         default:
863                 pstrcpy(statcol, PRINTQ_PRINTER_STATUNK);
864         }
865         d_printf(PRINTQ_DISPLAY_JOB, ownername, jobid, jobsize, statcol);
866 }
867
868 static int net_printq_info(int argc, const char **argv)
869 {
870         if (argc == 0) return printq_usage();
871
872         if (!make_ipc_connection(0)) return -1;
873
874         return cli_NetPrintQGetInfo(cli, argv[0], enum_queue, enum_jobs);
875 }
876
877 static int net_printq_delete(int argc, const char **argv)
878 {
879         if (argc == 0) return printq_usage();
880
881         if (!make_ipc_connection(0)) return -1;
882
883         return cli_printjob_del(cli, atoi(argv[0]));
884 }
885
886 static int net_printq(int argc, const char **argv)
887 {
888         struct functable func[] = {
889                 {"INFO", net_printq_info},
890                 {"DELETE", net_printq_delete},
891                 {NULL, NULL}
892         };
893
894         if (argc == 0) {
895                 if (!make_ipc_connection(0)) return -1;
896                 return cli_NetPrintQEnum(cli, enum_queue, enum_jobs);
897         }
898
899         return net_run_function(argc, argv, func, printq_usage);
900 }
901
902         
903 static int user_usage(void)
904 {
905         d_printf(NET_USER_USAGE); /* command syntax */
906         
907         general_usage();
908         return -1;
909
910         
911 static void user_fn(const char *user_name, const char *comment, const char * home_dir, 
912                     const char * logon_script, void *state)
913 {
914         d_printf("%-21.21s\n", user_name);
915 }
916
917 void long_user_fn(const char *user_name, const char *comment, const char * home_dir, const char * logon_script, void *state)
918 {
919         d_printf("%-21.21s %-47.47s %-35.35s %35.35s\n", user_name, comment, home_dir, logon_script);
920 }
921                   
922 void group_member_fn(const char *user_name, void *state)
923 {
924         d_printf("%-21.21s\n", user_name);
925 }
926
927 static int net_user_delete(int argc, const char **argv)
928 {
929         if (argc == 0) return user_usage();
930
931         if (!make_ipc_connection(0)) return -1;
932
933         return cli_NetUserDelete(cli, argv[0]);
934 }
935
936 static int net_user_add(int argc, const char **argv)
937 {
938         RAP_USER_INFO_1 userinfo;
939
940         if (argc == 0) return user_usage();
941
942         if (!make_ipc_connection(0)) return -1;
943                         
944         safe_strcpy(userinfo.user_name, argv[0], sizeof(userinfo.user_name));
945         if (opt_flags == -1) opt_flags = 0x21; 
946                         
947         userinfo.userflags = opt_flags;
948         userinfo.reserved1 = '\0';
949         userinfo.comment = opt_comment;
950         userinfo.priv = 1; 
951         userinfo.home_dir = NULL;
952         userinfo.logon_script = NULL;
953         
954         return cli_NetUserAdd(cli, &userinfo);
955 }
956
957 static int net_user_info(int argc, const char **argv)
958 {
959         if (argc == 0) return user_usage();
960
961         if (!make_ipc_connection(0)) return -1;
962
963         return cli_NetUserGetGroups(cli, argv[0], group_member_fn, NULL);
964 }
965
966 int net_user(int argc, const char **argv)
967 {
968         struct functable func[] = {
969                 {"ADD", net_user_add},
970                 {"INFO", net_user_info},
971                 {"DELETE", net_user_delete},
972                 {NULL, NULL}
973         };
974
975         if (argc == 0) {
976                 if (!make_ipc_connection(0)) return -1;
977                 if (opt_long_list_entries) {
978                         d_printf(USER_ENUM_DISPLAY);
979                         return cli_RNetUserEnum(cli, long_user_fn, NULL);
980                 }
981                 return cli_RNetUserEnum(cli, user_fn, NULL); 
982         }
983
984         return net_run_function(argc, argv, func, user_usage);
985 }
986
987
988 static int group_usage(void)
989 {
990         d_printf(NET_GROUP_USAGE); /* command syntax */
991         
992         general_usage();
993         return -1;
994 }
995
996 static void long_group_fn(const char *group_name, const char *comment, void *state)
997 {
998         d_printf("%-21.21s %-50.50s\n", group_name, comment);
999 }
1000
1001 static void group_fn(const char *group_name, const char *comment, void *state)
1002 {
1003         d_printf("%-21.21s\n", group_name);
1004 }
1005
1006 static int net_group_delete(int argc, const char **argv)
1007 {
1008         if (argc == 0) return group_usage();
1009         if (!make_ipc_connection(0)) return -1;
1010         return cli_NetGroupDelete(cli, argv[0]);
1011 }
1012
1013 static int net_group_add(int argc, const char **argv)
1014 {
1015         RAP_GROUP_INFO_1 grinfo;
1016
1017         if (argc == 0) return group_usage();
1018         if (!make_ipc_connection(0)) return -1;
1019                         
1020         /* BB check for length 21 or smaller explicitly ? BB */
1021         safe_strcpy(grinfo.group_name, argv[0], sizeof(grinfo.group_name));
1022         grinfo.reserved1 = '\0';
1023         grinfo.comment = opt_comment;
1024         
1025         return cli_NetGroupAdd(cli, &grinfo);
1026 }
1027
1028 static int net_group(int argc, const char **argv)
1029 {
1030         struct functable func[] = {
1031                 {"ADD", net_group_add},
1032                 {"DELETE", net_group_delete},
1033                 {NULL, NULL}
1034         };
1035
1036         if (argc == 0) {
1037                 if (!make_ipc_connection(0)) return -1;
1038                 if (opt_long_list_entries) {
1039                         d_printf("%-21.21s %-50.50s\n", GROUP_STR, COMMENT_STR); 
1040                         d_printf("-----------------------------\n");
1041                         return cli_RNetGroupEnum(cli, long_group_fn, NULL);
1042                 }
1043                 return cli_RNetGroupEnum(cli, group_fn, NULL); 
1044         }
1045
1046         return net_run_function(argc, argv, func, group_usage);
1047 }
1048
1049 static int groupmember_usage(void)
1050 {
1051         d_printf(NET_GROUPMEMBER_USAGE); /* command syntax */
1052         
1053         general_usage();
1054         return -1;
1055 }
1056
1057
1058 static int net_groupmember_add(int argc, const char **argv)
1059 {
1060         if (argc != 2) return groupmember_usage();
1061
1062         if (!make_ipc_connection(0)) return -1;
1063
1064         return cli_NetGroupAddUser(cli, argv[0], argv[1]);
1065 }
1066
1067 static int net_groupmember_delete(int argc, const char **argv)
1068 {
1069         if (argc != 2) return groupmember_usage();
1070
1071         if (!make_ipc_connection(0)) return -1;
1072
1073         return cli_NetGroupDelUser(cli, argv[0], argv[1]);
1074 }
1075
1076 static int net_groupmember_list(int argc, const char **argv)
1077 {
1078         if (argc == 0) return groupmember_usage();
1079
1080         if (!make_ipc_connection(0)) return -1;
1081
1082         return cli_NetGroupGetUsers(cli, argv[0], group_member_fn, NULL ); 
1083 }
1084
1085 static int net_groupmember(int argc, const char **argv)
1086 {
1087         struct functable func[] = {
1088                 {"ADD", net_groupmember_add},
1089                 {"LIST", net_groupmember_list},
1090                 {"DELETE", net_groupmember_delete},
1091                 {NULL, NULL}
1092         };
1093         
1094         return net_run_function(argc, argv, func, groupmember_usage);
1095 }
1096
1097 static int validate_usage(void)
1098 {
1099         d_printf(NET_VALIDATE_USAGE); /* command syntax */
1100         
1101         general_usage();
1102         return -1;
1103 }
1104
1105 static int net_validate(int argc, const char **argv)
1106 {
1107         d_printf(ERRMSG_NOT_IMPLEMENTED);
1108         return 0;
1109 }
1110
1111 static int service_usage(void)
1112 {
1113         d_printf(NET_SERVICE_USAGE); /* command syntax */
1114         
1115         general_usage();
1116         return -1;
1117 }
1118
1119 static int net_service_add(int argc, const char **argv)
1120 {
1121         d_printf(ERRMSG_NOT_IMPLEMENTED);
1122         return 0;
1123 }
1124
1125 static int net_service_delete(int argc, const char **argv)
1126 {
1127         d_printf(ERRMSG_NOT_IMPLEMENTED);
1128         return 0;
1129 }
1130
1131 static int net_service(int argc, const char **argv)
1132 {
1133         struct functable func[] = {
1134                 {"ADD", net_service_add},
1135                 {"DELETE", net_service_delete},
1136                 {NULL, NULL}
1137         };
1138
1139         if (argc == 0) {
1140                 if (!make_ipc_connection(0)) return -1;
1141                 if (opt_long_list_entries) {
1142                         d_printf("%-15.15s %-50.50s\n", SERVICE_STR, COMMENT_STR); 
1143                         d_printf("-----------------------------\n");
1144                         return cli_RNetServiceEnum(cli, long_group_fn, NULL);
1145                 }
1146                 return cli_RNetServiceEnum(cli, group_fn, NULL); 
1147         }
1148
1149         return net_run_function(argc, argv, func, service_usage);
1150 }
1151
1152 static int password_usage(void)
1153 {
1154         d_printf(NET_PASSWORD_USAGE); /* command syntax */
1155         
1156         general_usage();
1157         return -1;
1158 }
1159
1160
1161 static int net_password(int argc, const char **argv)
1162 {
1163         if (argc < 3) return password_usage();
1164
1165         if (!make_ipc_connection(0)) return -1;
1166         
1167         /* BB Add check for password lengths? */
1168         return cli_oem_change_password(cli, argv[0], argv[2], argv[1]);
1169 }
1170
1171 static int admin_usage(void)
1172 {
1173         d_printf(NET_ADMIN_USAGE); /* command syntax */
1174         
1175         general_usage();
1176         return -1;
1177 }
1178
1179
1180 static int net_admin(int argc, const char **argv)
1181 {
1182         d_printf(ERRMSG_NOT_IMPLEMENTED);
1183         return 0;
1184 }
1185
1186 static int help_usage(void)
1187 {
1188         d_printf("\n"\
1189 "Usage: net help <function>\n"\
1190 "\n"\
1191 "Valid functions are:\n"\
1192 "  FILE SHARE SESSION SERVER DOMAIN PRINTQ USER GROUP\n"\
1193 "  VALIDATE GROUPMEMBER ADMIN SERVICE PASSWORD ADS\n");
1194         return -1;
1195 }
1196
1197 /*
1198   handle "net help *" subcommands
1199 */
1200 static int net_help(int argc, const char **argv)
1201 {
1202         struct functable func[] = {
1203                 {"FILE", file_usage},
1204                 {"SHARE", share_usage},
1205                 {"SESSION", session_usage},
1206                 {"SERVER", server_usage},
1207                 {"DOMAIN", domain_usage},
1208                 {"PRINTQ", printq_usage},
1209                 {"USER", user_usage},
1210                 {"GROUP", group_usage},
1211                 {"VALIDATE", validate_usage},
1212                 {"GROUPMEMBER", groupmember_usage},
1213                 {"ADMIN", admin_usage},
1214                 {"SERVICE", service_usage},
1215                 {"PASSWORD", password_usage},
1216                 {"ADS", net_ads_usage},
1217                 {NULL, NULL}};
1218
1219         return net_run_function(argc, argv, func, help_usage);
1220 }
1221
1222 /* main function table */
1223 static struct functable net_func[] = {
1224         {"FILE", net_file},
1225         {"SHARE", net_share},
1226         {"SESSION", net_session},
1227         {"SERVER", net_server},
1228         {"DOMAIN", net_domain},
1229         {"PRINTQ", net_printq},
1230         {"USER", net_user},
1231         {"GROUP", net_group},
1232         {"VALIDATE", net_validate},
1233         {"GROUPMEMBER", net_groupmember},
1234         {"ADMIN", net_admin},
1235         {"SERVICE", net_service},
1236         {"PASSWORD", net_password},
1237         {"ADS", net_ads},
1238         {"HELP", net_help},
1239         {NULL, NULL}
1240 };
1241
1242
1243 /****************************************************************************
1244   main program
1245 ****************************************************************************/
1246 int main(int argc,char *argv[])
1247 {
1248         int opt,i;
1249         char *p;
1250         int rc = 0;
1251         int argc_new = 0;
1252         const char ** argv_new;
1253         poptContext pc;
1254         static char *servicesf = dyn_CONFIGFILE;
1255         extern pstring global_myname;
1256         static int debuglevel;
1257
1258         struct poptOption long_options[] = {
1259                 {"help",        'h', POPT_ARG_NONE,   0,     'h'},
1260                 {"workgroup",   'w', POPT_ARG_STRING, &opt_target_workgroup},
1261                 {"myworkgroup", 'W', POPT_ARG_STRING, &opt_workgroup},
1262                 {"user",        'U', POPT_ARG_STRING, &opt_user_name, 'U'},
1263                 {"ipaddress",   'I', POPT_ARG_STRING, 0,     'I'},
1264                 {"port",        'p', POPT_ARG_INT,    &opt_port},
1265                 {"myname",      'n', POPT_ARG_STRING, &opt_requester_name},
1266                 {"conf",        's', POPT_ARG_STRING, &servicesf},
1267                 {"debug",       'd', POPT_ARG_INT,    &debuglevel, 'd'},
1268                 {"debuglevel",  'd', POPT_ARG_INT,    &debuglevel, 'd'},
1269                 {"server",      'S', POPT_ARG_STRING, &opt_host},
1270                 {"comment",     'C', POPT_ARG_STRING, &opt_comment},
1271                 {"maxusers",    'M', POPT_ARG_INT,    &opt_maxusers},
1272                 {"flags",       'F', POPT_ARG_INT,    &opt_flags},
1273                 {"jobid",       'j', POPT_ARG_INT,    &opt_jobid},
1274                 {"long",        'l', POPT_ARG_NONE,   &opt_long_list_entries},
1275                 { 0, 0, 0, 0}
1276         };
1277
1278         got_pass = 0;
1279         dest_ip = ipzero;
1280
1281         dbf = x_stdout;
1282         
1283         pc = poptGetContext(NULL, argc, (const char **) argv, long_options, 
1284                             POPT_CONTEXT_KEEP_FIRST);
1285         
1286         while((opt = poptGetNextOpt(pc)) != -1) {
1287                 switch (opt) {
1288                 case 'h':
1289                         net_usage();
1290                         exit(0);
1291                         break;
1292                 case 'I':
1293                         dest_ip = *interpret_addr2(poptGetOptArg(pc));
1294                         if (zero_ip(dest_ip))
1295                                 d_printf(ERRMSG_INVALID_IPADDRESS);
1296                         else
1297                                 have_ip = True;
1298                         break;
1299                 case 'U':
1300                         opt_user_name = strdup(opt_user_name);
1301                         p = strchr(opt_user_name,'%');
1302                         if (p) {
1303                                 *p = 0;
1304                                 opt_password = p+1;
1305                                 got_pass = 1;
1306                         }
1307                         break;
1308                 default:
1309                         d_printf(ERRMSG_INVALID_OPTION, (char)opt, opt);
1310                         net_usage();
1311                 }
1312         }
1313
1314         DEBUGLEVEL = debuglevel;
1315
1316         lp_load(servicesf,True,False,False);       
1317
1318         argv_new = (const char **)poptGetArgs(pc);
1319
1320         argc_new = argc;
1321         for (i=0; i<argc; i++) {
1322                 if (argv_new[i] == NULL) {
1323                         argc_new = i;
1324                         break;
1325                 }
1326         }
1327          
1328         if (!opt_requester_name) {
1329                 static fstring myname;
1330                 get_myname(myname);
1331                 opt_requester_name = myname;
1332         }
1333
1334         if (!opt_user_name && getenv("LOGNAME")) {
1335                 opt_user_name = getenv("LOGNAME");
1336         }
1337
1338         if (!opt_workgroup) {
1339                 opt_workgroup = lp_workgroup();
1340         }
1341
1342         if (!*global_myname) {
1343                 char *p;
1344                 fstrcpy(global_myname, myhostname());
1345                 p = strchr_m(global_myname, '.');
1346                 if (p) *p = 0;
1347         }
1348         
1349         load_interfaces();
1350
1351         rc = net_run_function(argc_new-1, argv_new+1, net_func, net_usage);
1352         
1353         DEBUG(2,("return code = %d\n", rc));
1354         return rc;
1355 }