53075965b55d0ceefaca5fb25b6fb2f8b25dec8d
[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
8    connect_to_ipc based on similar routine
9    Copyright (C) Andrew Tridgell 1994-1998
10
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 2 of the License, or
14    (at your option) any later version.
15    
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20    
21    You should have received a copy of the GNU General Public License
22    along with this program; if not, write to the Free Software
23    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 */
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 typedef struct _functable {
49   int func;
50   char funcname[12];
51 } functable;
52
53 /* functions available */
54 #define FILEF     1
55 #define SHAREF    2
56 #define SESSIONF  3
57 #define SERVERF   4
58 #define DOMAINF   5
59 #define PRINTQF   6 
60 #define USERF     7
61 #define GROUPF    8
62 #define VALIDATEF 9
63 #define GROUPMEMBERF 10
64 #define ADMINF    11
65 #define SERVICEF  12
66 #define PASSWORDF 13
67 #define DOMJOINF  14
68 #define HELPF     15
69
70 const functable net_func[] = {
71   { FILEF, "FILE"},
72   { SHAREF, "SHARE"},
73   { SESSIONF, "SESSION"},
74   { SERVERF, "SERVER"},
75   { DOMAINF, "DOMAIN"},
76   { PRINTQF, "PRINTQ"},
77   { USERF, "USER"},
78   { GROUPF, "GROUP"},
79   { VALIDATEF, "VALIDATE"},
80   { GROUPMEMBERF, "GROUPMEMBER"},
81   { ADMINF, "ADMIN"},
82   { SERVICEF, "SERVICE"},
83   { PASSWORDF, "PASSWORD"},
84   { DOMJOINF, "JOIN"},
85   { DOMJOINF, "DOMAINMEMBER"},
86   { HELPF, "HELP"}
87 };
88
89 /* subfunctions available */
90 #define OTHER_SF  0
91 #define LIST_SF   1  /* enumerate */
92 #define ADD_SF    2  /* also used for create and start */
93 #define DELETE_SF 3  /* also used for close and stop */
94 #define INFO_SF   4  /* get information */
95
96 const functable net_subfunc[] = {
97   { LIST_SF, "LIST" },
98   { LIST_SF, "ENUMERATE" },
99   { ADD_SF, "ADD" },
100   { ADD_SF, "CREATE" },
101   { DELETE_SF, "CLOSE" },
102   { DELETE_SF, "DELETE" },
103   { INFO_SF, "INFO"}
104 };
105
106 const char share_type[][6] = {
107   "Disk",
108   "Print",
109   "Dev",
110   "IPC"
111 };
112
113 #define PASSWORD_PROMPT         "Password: "
114 #define YES_STRING              "Yes"
115 #define NO_STRING               "No"
116
117 #define NET_USAGE \
118     "\nUsage: \n"\
119     "  net domain \tto list domains \n"\
120     "  net file \tto list open files on a server \n"\
121     "  net group \tto list user groups  \n"\
122     "  net groupmember to list users in a group \n"\
123     "  net password\t to change the password of a user\n"\
124     "  net printq \tto list the print queues on a server\n"\
125     "  net server \tto list servers in a domain\n"\
126     "  net session \tto list clients with open sessions to a server\n"\
127     "  net share \tto list shares exported by a server\n"\
128     "  net user \tto list users\n"\
129     "  net validate \tto check whether a user and the corresponding password are valid\n"\
130     "  net help\n"\
131     "\nType \"net help <option>\" to get more information on that option\n"
132
133 #define NET_FILE_USAGE \
134     "\nnet file [misc. options] [targets]"\
135     "\n\tenumerates all open files on file server\n"\
136     "\nnet file <username> [misc. options] [targets]"\
137     "\n\tenumerates all files opened by username on file server\n"\
138     "\nnet file CLOSE <id> [misc. options] [targets]"\
139     "\n\tcloses specified file on target server\n"
140
141 #define FILE_INFO_DISPLAY \
142     "File ID          %d\n"\
143     "User name        %s\n"\
144     "Locks            0x%-4.2x\n"\
145     "Path             %s\n"\
146     "Permissions      0x%x\n"
147 #define FILE_ENUM_DISPLAY \
148     "\nEnumerating open files on remote server:\n\n"\
149     "\n\tFileId  Opened by            Perms  Locks  Path \n"\
150     "\t------  ---------            -----  -----  ---- \n"
151
152 #define NET_SHARE_USAGE \
153     "\nnet share [misc. options] [targets] \n"\
154     "\tenumerates all exported resources (network shares) on target server\n"\
155     "\nnet share ADD <name=serverpath> [misc. options] [targets]"\
156     "\n\tAdd a share from a server (makes the export active)\n"\
157     "\nnet share DELETE <sharename> [misc. options] [targets]\n"\
158     "\tor"\
159     "\nnet share CLOSE <sharename> [misc. options] [targets]"\
160     "\n\tDeletes a share from a server (makes the export inactive)\n"
161     
162 #define SHARE_ENUM_DISPLAY \
163     "\nEnumerating shared resources (exports) on remote server:\n\n"\
164     "\nShare name   Type     Description\n"\
165     "----------   ----     -----------\n"
166
167
168 #define NET_SESSION_USAGE \
169     "\nnet session [misc. options] [targets]"\
170     "\n\tenumerates all active SMB/CIFS sessions on target server\n"\
171     "\nnet session DELETE <client_name> [misc. options] [targets] \n"\
172     "\tor"\
173     "\nnet session CLOSE <client_name> [misc. options] [targets]"\
174     "\n\tDeletes (closes) a session from specified client to server\n"
175
176 #define SESSION_ENUM_DISPLAY \
177     "Computer             User name            Client Type        Opens Idle time\n\n"\
178     "------------------------------------------------------------------------------\n"
179
180
181 #define SESSION_DISPLAY_ONE \
182     "User name       %-20.20s\n"\
183     "Computer        %-20.20s\n"\
184     "Guest logon     %-20.20s\n"\
185     "Client Type     %-40.40s\n"\
186     "Sess time       %2.2d:%2.2d:%2.2d\n"\
187     "Idle time       %2.2d:%2.2d:%2.2d\n"
188
189 #define SESSION_DISPLAY_CONNS \
190     "Share name     Type     # Opens\n"\
191     "------------------------------------------------------------------------------\n"
192
193 #define NET_SERVER_USAGE \
194     "\nUsage:\n"\
195     "  net server [domain]\tlists the servers in the specified domain or workgroup.\n"\
196     "    If domain is not specified, it uses the current domain or workgroup as\n"\
197     "    the default.\n"
198
199 #define SERVER_ENUM_DISPLAY "\nEnumerating servers in this domain or workgroup: \n\n"  \
200     "\n\tServer name          Server description\n"\
201     "\t-------------        ----------------------------\n"
202
203
204 #define NET_DOMAIN_USAGE \
205     "\nUsage:\n"\
206     "  net domain [misc. options] [target]\n\tlists the domains "\
207     "or workgroups visible on the current network\n"
208
209 #define DOMAIN_ENUM_DISPLAY \
210     "\nEnumerating domains:\n\n"\
211     "\n\tDomain name          Server name of Browse Master\n"\
212     "\t-------------        ----------------------------\n"
213
214 #define NET_PRINTQ_USAGE \
215     "\nUsage:\n"\
216     " net printq [misc. options] [targets]\n"\
217     "\tor\n"\
218     " net printq list [<queue_name>] [misc. options] [targets]\n"\
219     "\tlists the specified queue and jobs on the target server.\n"\
220     "\tIf the queue name is not specified, all queues are listed.\n\n"\
221     " net printq delete [<queue name>] [misc. options] [targets]\n"\
222     "\tdeletes the specified job number on the target server, or the\n"\
223     "\tprinter queue if no job number is specified\n"
224 #define PRINTQ_ENUM_DISPLAY \
225     "Print queues at \\\\%s\n\n"\
226     "Name                         Job #      Size            Status\n\n"\
227     "------------------------------------------------------------------"\
228     "-------------\n"
229 #define PRINTQ_DISPLAY_ONE "%-23.23s %5d jobs                      %-22.22s\n"
230 #define PRINTQ_PRINTER_ACTIVE "*Printer Active*"
231 #define PRINTQ_PRINTER_PAUSED "*Printer Paused*"
232 #define PRINTQ_PRINTER_ERROR "*Printer error*"
233 #define PRINTQ_PRINTER_DELPEND "*Delete Pending*"
234 #define PRINTQ_PRINTER_STATUNK "**UNKNOWN STATUS**"
235 #define PRINTQ_DISPLAY_JOB "     %-23.23s %5d %9d            %-22.22s\n"
236 #define PRINTQ_JOB_PRINTING "Printing"
237 #define PRINTQ_JOB_QUEUED "Waiting"
238 #define PRINTQ_JOB_PAUSED "Held in queue"
239 #define PRINTQ_JOB_SPOOLING "Spooling"
240 #define PRINTQ_QUEUE_WORD " Queue"
241
242 #define NET_USER_USAGE \
243     "\nnet user [misc. options] [targets]\n\tEnumerate users\n"\
244     "\nnet user DELETE <name> [misc. options] [targets]"\
245     "\n\tDelete specified user\n"\
246     "\nnet user INFO <name> [misc. options] [targets]"\
247     "\n\tList the domain groups of the specified user\n"\
248     "\nnet user ADD <name> [-F user flags] [misc. options] [targets]"\
249     "\n\tAdd specified user\n"
250
251 #define USER_ENUM_DISPLAY \
252     "\nEnumerating shared resources (exports) on remote server:\n\n"\
253     "\nUser name             Description                                     Home Directory                          Profile Directory\n"\
254     "---------             -----------                                     --------------                          -----------------\n"
255
256 #define NET_GROUP_USAGE \
257     "\nnet group [misc. options] [targets]"\
258     "\n\tEnumerate user groups\n"\
259     "\nnet group DELETE <name> [misc. options] [targets]"\
260     "\n\tDelete specified group\n"\
261     "\nnet group ADD <name> [-C comment] [misc. options] [targets]"\
262     "\n\tCreate specified group\n"
263
264 #define NET_GROUPMEMBER_USAGE \
265     "\nnet groupmember LIST <group name> [misc. options] [targets]"\
266     "\n\t Enumerate users in a group\n"\
267     "\nnet groupmember DELETE <group name> <user name> [misc. options] "\
268     "[targets]\n\t Delete sepcified user from specified group\n"\
269     "\nnet groupmember ADD <group name> <user name> [misc. options] [targets]"\
270     "\n\t Add specified user to specified group\n"
271
272             
273 #define NET_ADMIN_USAGE \
274     "\nnet admin <remote command to execute> [cmd arguments [environment]] [misc_options] [targets]\n"\
275     "\texecutes a remote command on an os/2 target server\n"
276     
277 #define NET_PASSWORD_USAGE \
278     "\nnet password <user> <old password> <new password> [misc_options] [targets]\n"\
279     "\tchanges the password for the specified user on a remote server\n"
280
281 #define NET_SERVICE_USAGE \
282     "\nnet service [misc. options] [targets] \n"\
283     "\tenumerates all running service daemons on target server\n"\
284     "\nnet service ADD <name> [service startup arguments] [misc. options] [targets]"\
285     "\n\tStart named service on remote server\n"\
286     "\nnet service DELETE <name> [misc. options] [targets]\n"\
287     "\n\tStop named service on remote server\n"
288     
289
290 #define NET_VALIDATE_USAGE \
291     "\nnet validate <username> [password]\n"\
292     "\tValidate user and password to check whether they can access target server or domain\n"
293
294 #define TARGET_USAGE      "\nValid targets: choose one (none defaults to using the %s)\n"
295 #define GLBL_LCL_MASTER   "global browsemaster or local browse master if that is not found"
296 #define DOMAIN_MASTER     "local domain browse master"
297 #define LOCAL_HOST        "localhost"
298 #define MISC_OPT_USAGE    "\nValid miscellaneous options are:\n"
299 #define SERVER_USAGE      "\t-S or --server=<server>\t\tserver name\n"
300 #define IPADDRESS_USAGE   "\t-I or --ipaddress=<ipaddr>\tip address of target server\n"
301 #define PORT_USAGE        "\t-p or --port=<port number>\tconnection port on target server\n"
302 #define WORKGROUP_USAGE   "\t-w or --workgroup=<wg>\t\ttarget workgroup or domain name\n"
303 #define COMMENT_USAGE     "\t-C or --comment=<comment>\tdescriptive comment (for add only)\n"
304 #define MYWORKGROUP_USAGE "\t-W or --myworkgroup=<wg>\tclient workgroup\n"
305 #define DEBUG_USAGE       "\t-d or --debug=<level>\t\tdebug level (0-10)\n"
306 #define MYNAME_USAGE      "\t-n or --myname=<name>\t\tclient name\n"
307 #define USER_USAGE        "\t-U or --user=<name>\t\tuser name\n"
308 #define CONF_USAGE        "\t-s or --conf=<path>\t\tpathname of smb.conf file\n"
309 #define JOBID_USAGE       "\t-j or --jobid=<job id>\t\tjob id\n"
310 #define MAXUSERS_USAGE    "\t-M or --maxusers=<num>\t\tmax users allowed for share\n"
311 #define LONG_USAGE        "\t-l or --long\t\t\tDisplay full information\n"
312
313 #define ERRMSG_NOCONN_TARGET_SRVR       "\nUnable to connect to target server\n"
314 #define ERRMSG_NOCONN_BROWSE_MSTR       "\nUnable to connect to browse master\n"
315 #define ERRMSG_NOT_IMPLEMENTED          "\nNot implemented\n"
316 #define ERRMSG_FILEID_MISSING           "\nMissing fileid of file to close\n\n"
317 #define ERRMSG_GROUPNAME_MISSING        "\n\nGroup name not specified\n"
318 #define ERRMSG_USERNAME_MISSING        "\n\nUser name not specified\n"
319 #define ERRMSG_SHARENAME_MISSING        "\n\nShare name not specified\n"
320 #define ERRMSG_TARGET_WG_NOT_VALID      "\nTarget workgroup option not valid "\
321                                         "except on net server command, ignored"
322 #define ERRMSG_INVALID_HELP_OPTION      "\nInvalid help option\n"
323 #define ERRMSG_INVALID_OPTION           "\nInvalid option %c (%d)\n"
324 #define ERRMSG_INVALID_IPADDRESS        "\nInvalid ip address specified\n"
325 #define ERRMSG_SPURIOUS_PARM            "\nInvalid paramater ignored: %s\n"
326 #define ERRMSG_BOTH_SERVER_IPADDRESS    "\nTarget server and IP address both "\
327   "specified. Do not set both at the same time.  The target IP address was used\n"
328 #define ERRMSG_INVALID_DOMAIN_ACTION    "\nInvalid action for NET DOMAIN command"\
329   " ignored. Only listing domains permitted.\n"
330
331 /* Column headers */
332 #define COMMENT_STR   "Comment "
333 #define USER_STR      "User name "
334 #define GROUP_STR     "Group name "  
335 #define SERVICE_STR   "Service name"
336 #define HOMED_STR     "Home directory "
337 #define LOGONS_STR    "Logon script "
338 /************************************************************************************/
339 /*                       end of internationalization section                        */
340 /************************************************************************************/
341
342 extern int optind, opterr, optopt;
343 extern struct in_addr ipzero;
344
345 struct cli_state *cli;
346 static pstring global_requester_name;
347 static pstring host; /* target server */
348 static pstring password;
349 static pstring global_user_name;
350 static pstring global_workgroup;
351 static int port = SMB_PORT;
352 static int long_list_entries = 0;
353 static BOOL got_pass = False;
354 static BOOL have_ip = False;
355 struct in_addr dest_ip;
356
357 int get_func(const char *parm)
358 {
359   int i;
360
361   for (i=0;i<=sizeof(net_func);i++)
362     if (StrnCaseCmp(parm, net_func[i].funcname,10) == 0)
363       return net_func[i].func;
364   return 0;
365 }
366
367 int get_subfunc(const char *parm)
368 {
369   int i;
370
371   for (i=0;i<=sizeof(net_subfunc);i++)
372     if (StrnCaseCmp(parm, net_subfunc[i].funcname,10) == 0)
373       return net_subfunc[i].func;
374   return 0;
375 }
376
377 /****************************************************************************
378   
379 ****************************************************************************/
380 struct cli_state *connect_to_ipc(char *server)
381 {
382   struct cli_state *c;
383   struct nmb_name called, calling;
384   struct in_addr ip;
385   char *server_n;
386   fstring servicename;
387   char *sharename;
388         
389         
390   /* make a copy so we don't modify the global string 'service' */
391   safe_strcpy(servicename, "IPC$", sizeof(servicename)-1);
392   sharename = servicename;
393   if (*sharename == '\\') {
394     server = sharename+2;
395     sharename = strchr(server,'\\');
396     if (!sharename) return NULL;
397     *sharename = 0;
398     sharename++;
399   }
400
401   if(server == NULL)
402     return NULL;  /* if ip addr specified, ascii version of ip address is used as host name */
403
404   server_n = server; 
405         
406   ip = ipzero;
407   make_nmb_name(&calling, global_requester_name, 0x0);
408   make_nmb_name(&called , server, 0x20);
409
410  again:
411   if (have_ip)
412     ip = dest_ip;
413   else ip = ipzero;
414
415   DEBUG(3,("Connecting to host=%s\\share=%s\n\n", 
416            server, "IPC$"));
417
418   /* have to open a new connection */
419   if (!(c=cli_initialise(NULL)) || (cli_set_port(c, port) == 0) ||
420       !cli_connect(c, server_n, &ip)) {
421     DEBUG(1,("Connection to %s failed\n", server_n));
422     return NULL;
423   }
424
425   c->protocol = PROTOCOL_NT1;
426
427   if (!cli_session_request(c, &calling, &called)) {
428     char *p;
429     DEBUG(1,("session request to %s failed (%s)\n", 
430              called.name, cli_errstr(c)));
431     cli_shutdown(c);
432     SAFE_FREE(c);
433     if ((p=strchr(called.name, '.'))) {
434       *p = 0;
435       goto again;
436     }
437     if (strcmp(called.name, "*SMBSERVER")) {
438       make_nmb_name(&called , "*SMBSERVER", 0x20);
439       goto again;
440     }
441     return NULL;
442   }
443
444   DEBUG(4,(" session request ok\n"));
445
446   if (!cli_negprot(c)) {
447     DEBUG(1,("protocol negotiation failed\n"));
448     cli_shutdown(c);
449     SAFE_FREE(c);
450     return NULL;
451   }
452
453   if (!got_pass) {
454     char *pass = getpass(PASSWORD_PROMPT);
455     if (pass) {
456       pstrcpy(password, pass);
457     }
458   }
459
460   if (!cli_session_setup(c, global_user_name, 
461                          password, strlen(password),
462                          password, strlen(password),
463                          global_workgroup)) {
464     /*  try again with a null username */
465     if (!cli_session_setup(c, "", "", 0, "", 0, global_workgroup)) { 
466       DEBUG(1,("session setup failed: %s\n", cli_errstr(c)));
467       cli_shutdown(c);
468       SAFE_FREE(c);
469       return NULL;
470     }
471     DEBUG(3,("Anonymous login successful\n"));
472   }
473         
474   DEBUG(4,(" session setup ok\n"));
475   if (!cli_send_tconX(c, sharename, "?????",
476                       password, strlen(password)+1)) {
477     DEBUG(1,("tree connect failed: %s\n", cli_errstr(c)));
478     cli_shutdown(c);
479     SAFE_FREE(c);
480     return NULL;
481   }
482
483   DEBUG(4,(" tconx ok\n"));
484
485   return c;
486 }
487
488
489 void usage(void)
490 {
491   d_printf(NET_USAGE);
492 }
493
494 void file_usage(void)
495 {
496   d_printf(NET_FILE_USAGE); /* command syntax */
497   
498   d_printf(TARGET_USAGE, LOCAL_HOST); /* target options */
499   d_printf(SERVER_USAGE);
500   d_printf(IPADDRESS_USAGE);
501
502   d_printf(MISC_OPT_USAGE); /* misc options */
503   d_printf(PORT_USAGE);
504   d_printf(MYWORKGROUP_USAGE);
505   d_printf(DEBUG_USAGE);
506   d_printf(MYNAME_USAGE);
507   d_printf(USER_USAGE);
508   d_printf(CONF_USAGE);
509 }
510
511 /***************************************************************************
512   list info on an open file
513 ***************************************************************************/
514 static void file_fn(const char * pPath, const char * pUser, uint16 perms, uint16 locks, uint32 id)
515 {
516   d_printf("\t%-7.1d %-20.20s 0x%-4.2x %-6.1d %s\n",
517          id, pUser, perms, locks, pPath);
518 }
519
520 static void one_file_fn(const char *pPath, const char *pUser, uint16 perms, uint16 locks, uint32 id)
521 {
522   d_printf(FILE_INFO_DISPLAY, id, pUser, locks, pPath, perms);
523 }
524
525 int net_file(int subfunct, const char * id)
526 {
527   struct in_addr target_ip;
528         
529   if((have_ip == 0) && (host[0] == 0)) {
530     if (!resolve_name("localhost", &target_ip, 0x20)) {
531       DEBUG(1,("No remote server specified, unable to resolve connection to localhost via name lookup"));
532       return -1;
533     } else {
534       have_ip = True;
535       dest_ip = target_ip;
536     }
537   }
538   if(host[0] == 0) strncpy(host, inet_ntoa(dest_ip),16);
539   cli = connect_to_ipc(host);
540   if(!cli) {
541     d_printf(ERRMSG_NOCONN_TARGET_SRVR);
542     return -2;
543   }
544
545   if(subfunct == DELETE_SF) { /* close open file on remote server */
546     if(id == NULL) {
547       d_printf(ERRMSG_FILEID_MISSING);
548       return -1;
549     } else 
550       return cli_NetFileClose(cli, atoi(id));
551   } else if(subfunct == LIST_SF) {
552     d_printf(FILE_ENUM_DISPLAY); /* file list header */
553     return cli_NetFileEnum(cli, NULL, NULL, file_fn);
554   } else if ((subfunct == OTHER_SF) && id) {
555     return cli_NetFileGetInfo(cli, atoi(id), one_file_fn);
556   } else file_usage();
557   return -1;
558 }
559                        
560 void share_usage(void)
561 {
562   d_printf(NET_SHARE_USAGE); /* command syntax */
563
564   d_printf(TARGET_USAGE, LOCAL_HOST); /* target options */
565   d_printf(SERVER_USAGE);
566   d_printf(IPADDRESS_USAGE);
567
568   d_printf(MISC_OPT_USAGE); /* misc options */
569   d_printf(PORT_USAGE);
570   d_printf(COMMENT_USAGE);
571   d_printf(MAXUSERS_USAGE);
572   d_printf(MYWORKGROUP_USAGE);
573   d_printf(DEBUG_USAGE);
574   d_printf(MYNAME_USAGE);
575   d_printf(USER_USAGE);
576   d_printf(CONF_USAGE);
577 }
578
579 void long_share_fn(const char *share_name, uint32 type, const char *comment, void *state)
580 {
581    d_printf("%-12.12s %-8.8s %-50.50s\n", share_name, share_type[type], comment);
582 }
583
584 void share_fn(const char *share_name, uint32 type, const char *comment, void *state)
585 {
586    d_printf("%-12.12s\n", share_name);
587 }
588
589 int net_share(int subfunct, const char * sharename, const char * comment, int maxusers)
590 {
591   struct in_addr target_ip;
592  
593   if((have_ip == 0) && (host[0] == 0)) {
594     if (!resolve_name("localhost", &target_ip, 0x20)) {
595       DEBUG(1,("No remote server specified, unable to resolve connection to localhost via name lookup"));
596       return -1;
597
598     } else {
599       have_ip = True;
600       dest_ip = target_ip;
601     }
602   }
603   if(host[0] == 0) 
604     strncpy(host, inet_ntoa(dest_ip),16);
605   cli = connect_to_ipc(host);
606   if(!cli) {
607     d_printf(ERRMSG_NOCONN_TARGET_SRVR);
608     return -2;
609   }
610   if (subfunct == DELETE_SF) {
611     if (sharename == NULL) {
612       d_printf(ERRMSG_SHARENAME_MISSING);
613       return -1;
614     } else
615       return cli_NetShareDelete(cli, sharename);
616   } else if (subfunct == LIST_SF) {
617       if(long_list_entries) {
618        d_printf(SHARE_ENUM_DISPLAY);
619        return cli_RNetShareEnum(cli, long_share_fn, NULL);
620       } else {      
621        return cli_RNetShareEnum(cli, share_fn, NULL);
622       }
623   } else if (subfunct == ADD_SF) {
624     if (sharename == NULL) {
625       d_printf(ERRMSG_SHARENAME_MISSING);
626       return -1;
627     } else {
628       RAP_SHARE_INFO_2 sinfo;
629       char *p;
630
631       p = strchr(sharename, '=');
632       strncpy(sinfo.share_name, sharename, PTR_DIFF(p,sharename));
633       sinfo.reserved1 = '\0';
634       sinfo.share_type = 0;
635       sinfo.comment = comment;
636       sinfo.perms = 0;
637       sinfo.maximum_users = maxusers;
638       sinfo.active_users = 0;
639       sinfo.path = p+1;
640       memset(sinfo.password, '\0', sizeof(sinfo.password));
641       sinfo.reserved2 = '\0';
642
643       return cli_NetShareAdd(cli, &sinfo);
644     }
645   } else
646     d_printf(ERRMSG_NOT_IMPLEMENTED);
647   return -1;
648 }
649                     
650                 
651 void session_usage(void)
652 {
653   d_printf(NET_SESSION_USAGE); /* command syntax */
654
655   d_printf(TARGET_USAGE, LOCAL_HOST); /* Target options */
656   d_printf(SERVER_USAGE);
657   d_printf(IPADDRESS_USAGE);
658
659   d_printf(MISC_OPT_USAGE); /* Misc options */
660   d_printf(PORT_USAGE);
661   d_printf(MYWORKGROUP_USAGE);
662   d_printf(DEBUG_USAGE);
663   d_printf(MYNAME_USAGE);
664   d_printf(USER_USAGE);
665   d_printf(CONF_USAGE);
666 }
667     
668 void list_sessions_func(char *wsname, char *username, uint16 conns,
669                         uint16 opens, uint16 users, uint32 sess_time,
670                         uint32 idle_time, uint32 user_flags, char *clitype)
671 {
672   int hrs = idle_time / 3600;
673   int min = (idle_time / 60) % 60;
674   int sec = idle_time % 60;
675
676   d_printf("\\\\%-18.18s %-20.20s %-18.18s %5d %2.2d:%2.2d:%2.2d\n",
677          wsname, username, clitype, opens, hrs, min, sec);
678 }
679
680 void display_session_func(const char *wsname, const char *username, uint16 conns,
681                           uint16 opens, uint16 users, uint32 sess_time,
682                           uint32 idle_time, uint32 user_flags, const char *clitype)
683 {
684   int ihrs = idle_time / 3600;
685   int imin = (idle_time / 60) % 60;
686   int isec = idle_time % 60;
687   int shrs = sess_time / 3600;
688   int smin = (sess_time / 60) % 60;
689   int ssec = sess_time % 60;
690   d_printf(SESSION_DISPLAY_ONE, username, wsname, 
691          (user_flags&0x0)?YES_STRING:NO_STRING, clitype,
692          shrs, smin, ssec, ihrs, imin, isec);
693 }
694
695 void display_conns_func(uint16 conn_id, uint16 conn_type, uint16 opens, uint16 users, uint32 conn_time, const char *username, const char *netname)
696 {
697   d_printf("%-14.14s %-8.8s %5d\n", netname, share_type[conn_type], opens);
698 }
699
700 int net_session(int subfunct, const char * sessname)
701 {
702   struct in_addr target_ip;
703   int res;
704  
705   if((have_ip == 0) && (host[0] == 0)) {
706     if (!resolve_name("localhost", &target_ip, 0x20)) {
707       DEBUG(1,("No remote server specified, unable to resolve connection to localhost via name lookup"));
708       return -1;
709
710     } else {
711       have_ip = True;
712       dest_ip = target_ip;
713     }
714   }
715   if(host[0] == 0)  
716     strncpy(host, inet_ntoa(dest_ip),16);
717   cli = connect_to_ipc(host);
718   if(!cli) {
719     d_printf(ERRMSG_NOCONN_TARGET_SRVR);
720     return -2;
721   }
722   switch(subfunct){
723     case LIST_SF:
724       if (sessname) {
725         res = cli_NetSessionGetInfo(cli, sessname, display_session_func);
726         if (res >= 0) {
727           d_printf(SESSION_DISPLAY_CONNS);
728           return cli_NetConnectionEnum(cli, sessname, display_conns_func);
729         } else 
730           return res;
731       } else {
732         d_printf(SESSION_ENUM_DISPLAY);
733         return cli_NetSessionEnum(cli, list_sessions_func);
734       }
735     case DELETE_SF:
736       return cli_NetSessionDel(cli, sessname);
737     default:
738       d_printf(ERRMSG_NOT_IMPLEMENTED);
739       session_usage();
740   }
741   return -1;
742 }
743         
744 /****************************************************************************
745 list a server name
746 ****************************************************************************/
747 static void display_server_func(const char *name, uint32 m, const char *comment, void * reserved)
748 {
749   d_printf("\t%-16.16s     %s\n", name, comment);
750 }
751
752
753 void server_usage(void)
754 {
755   d_printf(NET_SERVER_USAGE); /* command syntax */
756
757   d_printf(TARGET_USAGE, DOMAIN_MASTER); /* Target options */
758   d_printf(SERVER_USAGE);
759   d_printf(IPADDRESS_USAGE);
760   d_printf(WORKGROUP_USAGE);
761
762   d_printf(MISC_OPT_USAGE); /* Misc options */
763   d_printf(PORT_USAGE);
764   d_printf(MYWORKGROUP_USAGE);
765   d_printf(DEBUG_USAGE);
766   d_printf(MYNAME_USAGE);
767   d_printf(USER_USAGE);
768   d_printf(CONF_USAGE);
769 }
770                     
771 int net_server(char * temp_workgroup, int subfunct)
772 {
773   /* try to find master browser for our domain - if we fail try to find pdc */
774   char our_workgroup[16];
775   struct in_addr brow_ips;
776
777   if((have_ip == 0) && (host[0] == 0)) {
778     /* find target server based on workgroup or domain */
779     if((temp_workgroup == 0) || (temp_workgroup[0] == 0)) 
780       temp_workgroup = lp_workgroup();  /* by default enum our local workgroup or domain */
781         
782     safe_strcpy(our_workgroup, temp_workgroup,15);
783         
784     if (!resolve_name(our_workgroup, &brow_ips, 0x1D))  {
785       /* go looking for workgroups */
786       DEBUG(1,("Unable to resolve master browser via name lookup\n"));
787       return -2;
788     } else {
789       have_ip = True;
790       dest_ip = brow_ips;
791     }
792   }
793   if(host[0] == 0) strncpy(host, inet_ntoa(dest_ip),16);
794   cli = connect_to_ipc(host);
795   if(!cli) {
796     d_printf(ERRMSG_NOCONN_BROWSE_MSTR);
797     return -2;
798   }
799   d_printf(SERVER_ENUM_DISPLAY); /* header for list of servers */
800   return cli_NetServerEnum(cli, cli->server_domain, SV_TYPE_ALL, display_server_func,NULL); 
801         
802   /* BB add mechanism to find PDC for our domain and send enum to it in the error case */          
803 }
804                       
805 void domain_usage(void)
806 {
807   d_printf(NET_DOMAIN_USAGE); /* command syntax */
808
809   d_printf(TARGET_USAGE, GLBL_LCL_MASTER); /* target options */
810   d_printf(SERVER_USAGE);
811   d_printf(IPADDRESS_USAGE);
812     
813   d_printf(MISC_OPT_USAGE); /* misc options */
814   d_printf(PORT_USAGE);
815   d_printf(MYWORKGROUP_USAGE);
816   d_printf(DEBUG_USAGE);
817   d_printf(MYNAME_USAGE);
818   d_printf(USER_USAGE);
819   d_printf(CONF_USAGE);
820 }
821
822                   
823 int net_domain(void)
824 {
825   char *our_workgroup;
826   struct in_addr msbrow_ip;
827   struct in_addr * ip_list = NULL;
828   int addr_count;
829         
830
831   our_workgroup = lp_workgroup();
832   if((have_ip == 0) && (host[0] == 0)) {
833   /*  if (!resolve_name(MSBROWSE, &msbrow_ip, 1)) */
834       if (!get_dmb_list(&ip_list,&addr_count)){
835         DEBUG(1,("Unable to resolve global master browser via name lookup"));
836         if (!resolve_name(our_workgroup, &msbrow_ip, 0x1D))  {
837           DEBUG(1,("Unable to resolve domain browser via name lookup\n"));
838           return -2;
839         } else {
840           have_ip = True;
841           dest_ip = msbrow_ip;
842         }
843     } else {
844       have_ip = True;
845       dest_ip = *ip_list;                                                         
846     }
847   }
848   if(host[0] == 0)
849     strncpy(host, inet_ntoa(dest_ip),16);
850   cli = connect_to_ipc(host);  /* BB fix two common failures i.e. to os2 due to *SMBSERVER and also due to access denied by picking wrong starting DMB */
851   if(!cli) {
852     d_printf(ERRMSG_NOCONN_BROWSE_MSTR);
853     return -2;
854   }
855   d_printf(DOMAIN_ENUM_DISPLAY); /* header for list of domains */
856   return cli_NetServerEnum(cli, cli->server_domain, SV_TYPE_DOMAIN_ENUM, display_server_func,NULL);     
857            
858 }
859                       
860 void printq_usage(void)
861 {
862   d_printf(NET_PRINTQ_USAGE);
863
864   d_printf(TARGET_USAGE, LOCAL_HOST);
865   d_printf(SERVER_USAGE);
866   d_printf(IPADDRESS_USAGE);
867
868   d_printf(MISC_OPT_USAGE);
869   d_printf(PORT_USAGE);
870   d_printf(JOBID_USAGE);
871   d_printf(MYWORKGROUP_USAGE);
872   d_printf(DEBUG_USAGE);
873   d_printf(MYNAME_USAGE);
874   d_printf(USER_USAGE);
875   d_printf(CONF_USAGE);
876 }       
877
878 void enum_queue(const char *queuename, uint16 pri, uint16 start, uint16 until, const char *sep, const char *pproc, const char *dest, const char *qparms, const char *qcomment, uint16 status, uint16 jobcount) {
879   pstring queuecol;
880   pstring statcol;
881
882   pstrcpy(queuecol, queuename);
883   pstrcat(queuecol, PRINTQ_QUEUE_WORD);
884
885   switch (status) {
886     case 0:
887       pstrcpy(statcol, PRINTQ_PRINTER_ACTIVE);
888       break;
889     case 1:
890       pstrcpy(statcol, PRINTQ_PRINTER_PAUSED);
891       break;
892     case 2:
893       pstrcpy(statcol, PRINTQ_PRINTER_ERROR);
894       break;
895     case 3:
896       pstrcpy(statcol, PRINTQ_PRINTER_DELPEND);
897       break;
898     default:
899       pstrcpy(statcol, PRINTQ_PRINTER_STATUNK);
900   }
901   d_printf(PRINTQ_DISPLAY_ONE, queuecol, jobcount, statcol);
902 }
903
904 void enum_jobs(uint16 jobid, const char *ownername, const char *notifyname, const char *datatype, const char *jparms, uint16 pos, uint16 status, const char *jstatus, uint submitted, uint jobsize, const char *comment) {
905   pstring statcol;
906
907   switch (status) {
908     case 0:
909       pstrcpy(statcol, PRINTQ_JOB_QUEUED);
910       break;
911     case 1:
912       pstrcpy(statcol, PRINTQ_JOB_PAUSED);
913       break;
914     case 2:
915       pstrcpy(statcol, PRINTQ_JOB_SPOOLING);
916       break;
917     case 3:
918       pstrcpy(statcol, PRINTQ_JOB_PRINTING);
919       break;
920     default:
921       pstrcpy(statcol, PRINTQ_PRINTER_STATUNK);
922   }
923   d_printf(PRINTQ_DISPLAY_JOB, ownername, jobid, jobsize, statcol);
924 }
925
926 int net_printq(int subfunct, const char *printq, int jobid)
927 {
928   struct in_addr target_ip;
929  
930   if((have_ip == 0) && (host[0] == 0)) {
931     if (!resolve_name("localhost", &target_ip, 0x20)) {
932       DEBUG(1,("No remote server specified, unable to resolve connection to localhost via name lookup"));
933       return -1;
934
935     } else {
936       have_ip = True;
937       dest_ip = target_ip;
938     }
939   }
940   if(host[0] == 0) 
941     strncpy(host, inet_ntoa(dest_ip),16);
942   cli = connect_to_ipc(host);
943   if(!cli) {
944     d_printf(ERRMSG_NOCONN_TARGET_SRVR);
945     return -2;
946   }
947   switch(subfunct) {
948     case LIST_SF:
949         d_printf(PRINTQ_ENUM_DISPLAY, host);
950       if (printq)
951         return cli_NetPrintQGetInfo(cli, printq, enum_queue, enum_jobs);
952       else
953         return cli_NetPrintQEnum(cli, enum_queue, enum_jobs);
954     case DELETE_SF:
955       return cli_printjob_del(cli, jobid);
956     default:
957       d_printf(ERRMSG_NOT_IMPLEMENTED);
958       return -1;
959   }
960 }
961
962
963         
964 void user_usage(void)
965 {
966   d_printf(NET_USER_USAGE); /* command syntax */
967
968   d_printf(TARGET_USAGE, LOCAL_HOST); /* target options */
969   d_printf(SERVER_USAGE);
970   d_printf(IPADDRESS_USAGE);
971   d_printf(WORKGROUP_USAGE);
972     
973   d_printf(MISC_OPT_USAGE); /* misc options */
974   d_printf(PORT_USAGE);
975   d_printf(COMMENT_USAGE);
976   d_printf(MYWORKGROUP_USAGE);
977   d_printf(DEBUG_USAGE);
978   d_printf(MYNAME_USAGE);
979   d_printf(USER_USAGE);
980   d_printf(CONF_USAGE);
981   d_printf(LONG_USAGE);
982
983         
984 void user_fn(const char *user_name, const char *comment, const char * home_dir, const char * logon_script, void *state)
985 {
986    d_printf("%-21.21s\n", user_name);
987 }
988
989 void long_user_fn(const char *user_name, const char *comment, const char * home_dir, const char * logon_script, void *state)
990 {
991    d_printf("%-21.21s %-47.47s %-35.35s %35.35s\n", user_name, comment, home_dir, logon_script);
992 }
993                   
994 void group_member_fn(const char *user_name, void *state)
995 {
996    d_printf("%-21.21s\n", user_name);
997 }
998
999 int net_user(int subfunct, const char * username, const char * comment, int flags)
1000 {
1001   struct in_addr target_ip;
1002  
1003   if((have_ip == 0) && (host[0] == 0)) {
1004     if (!resolve_name("localhost", &target_ip, 0x20)) {
1005       DEBUG(1,("No remote server specified, unable to resolve connection to localhost via name lookup"));
1006       return -1;
1007
1008     } else {
1009       have_ip = True;
1010       dest_ip = target_ip;
1011     }
1012   }
1013   if(host[0] == 0)  
1014     strncpy(host, inet_ntoa(dest_ip),16);
1015   cli = connect_to_ipc(host);
1016   if(!cli) {
1017     d_printf(ERRMSG_NOCONN_TARGET_SRVR);
1018     return -2;
1019   }
1020   if (subfunct == DELETE_SF) {
1021     if (username == NULL) {
1022       d_printf(ERRMSG_USERNAME_MISSING);
1023       return -1;
1024     } else
1025       return cli_NetUserDelete(cli, username);
1026   } else if (subfunct == LIST_SF) {
1027       if(long_list_entries) {
1028         d_printf(USER_ENUM_DISPLAY);
1029             return cli_RNetUserEnum(cli, long_user_fn, NULL);
1030       }
1031       else
1032             return cli_RNetUserEnum(cli, user_fn, NULL); 
1033   } else if (subfunct == ADD_SF) {
1034     if (username == NULL) {
1035       d_printf(ERRMSG_USERNAME_MISSING);
1036       return -1;
1037     } else {
1038       RAP_USER_INFO_1 userinfo;
1039       
1040       safe_strcpy(userinfo.user_name, username, sizeof(userinfo.user_name));
1041       if(flags == -1) flags = 0x21; 
1042
1043       userinfo.userflags = flags;
1044       userinfo.reserved1 = '\0';
1045       userinfo.comment = comment;
1046       userinfo.priv = 1; 
1047       userinfo.home_dir = NULL;
1048       userinfo.logon_script = NULL;
1049
1050       return cli_NetUserAdd(cli, &userinfo);
1051     }
1052   } else if (subfunct == INFO_SF) {
1053     if (username == NULL) {
1054       d_printf(ERRMSG_USERNAME_MISSING);
1055       return -1;
1056     } else {
1057       /*  RAP_USER_INFO_1 userinfo;
1058           cli_NetUserInfo (cli, &userinfo);     */  /* BB need to add call to get user info level 3 or 4 */
1059         return  cli_NetUserGetGroups(cli, username, group_member_fn, NULL ); 
1060     }
1061   }
1062   else
1063     d_printf(ERRMSG_NOT_IMPLEMENTED);
1064   return -1;
1065
1066 }
1067
1068
1069 void group_usage(void)
1070 {
1071   d_printf(NET_GROUP_USAGE); /* command syntax */
1072
1073   d_printf(TARGET_USAGE, LOCAL_HOST); /* target options */
1074   d_printf(SERVER_USAGE);
1075   d_printf(IPADDRESS_USAGE);
1076
1077   d_printf(MISC_OPT_USAGE); /* misc options */
1078   d_printf(PORT_USAGE);
1079   d_printf(COMMENT_USAGE);
1080   d_printf(MYWORKGROUP_USAGE);
1081   d_printf(DEBUG_USAGE);
1082   d_printf(MYNAME_USAGE);
1083   d_printf(USER_USAGE);
1084   d_printf(WORKGROUP_USAGE);
1085   d_printf(CONF_USAGE);
1086   d_printf(LONG_USAGE);
1087 }
1088
1089 void long_group_fn(const char *group_name, const char *comment, void *state)
1090 {
1091    d_printf("%-21.21s %-50.50s\n", group_name, comment);
1092 }
1093
1094 void group_fn(const char *group_name, const char *comment, void *state)
1095 {
1096    d_printf("%-21.21s\n", group_name);
1097 }
1098
1099 int net_group(int subfunct, const char * groupname, const char * comment)
1100 {
1101   struct in_addr target_ip;
1102  
1103   if((have_ip == 0) && (host[0] == 0)) {
1104     if (!resolve_name("localhost", &target_ip, 0x20)) {
1105       DEBUG(1,("No remote server specified, unable to resolve connection to localhost via name lookup"));
1106       return -1;
1107
1108     } else {
1109       have_ip = True;
1110       dest_ip = target_ip;
1111     }
1112   }
1113   if(host[0] == 0)  
1114     strncpy(host, inet_ntoa(dest_ip),16);
1115   cli = connect_to_ipc(host);
1116   if(!cli) {
1117     d_printf(ERRMSG_NOCONN_TARGET_SRVR);
1118     return -2;
1119   }
1120   if (subfunct == DELETE_SF) {
1121     if (groupname == NULL) {
1122       d_printf(ERRMSG_GROUPNAME_MISSING);
1123       return -1;
1124     } else
1125       return cli_NetGroupDelete(cli, groupname);
1126   } else if (subfunct == LIST_SF) {
1127     if(long_list_entries) {
1128           d_printf("%-21.21s %-50.50s\n", GROUP_STR, COMMENT_STR); 
1129       d_printf("-----------------------------\n");
1130           return cli_RNetGroupEnum(cli, long_group_fn, NULL);
1131     }
1132     else
1133       return cli_RNetGroupEnum(cli, group_fn, NULL); 
1134   } else if (subfunct == ADD_SF) {
1135     if (groupname == NULL) {
1136       d_printf(ERRMSG_GROUPNAME_MISSING);
1137       return -1;
1138     } else {
1139       RAP_GROUP_INFO_1 grinfo;
1140
1141   /* BB check for length 21 or smaller explicitly ? BB */
1142       safe_strcpy(grinfo.group_name, groupname, sizeof(grinfo.group_name));
1143       grinfo.reserved1 = '\0';
1144       grinfo.comment = comment;
1145
1146       return cli_NetGroupAdd(cli, &grinfo);
1147     }
1148   } else
1149     d_printf(ERRMSG_NOT_IMPLEMENTED);
1150   return -1;
1151 }
1152
1153 void groupmember_usage(void)
1154 {
1155   d_printf(NET_GROUPMEMBER_USAGE); /* command syntax */
1156
1157   d_printf(TARGET_USAGE, LOCAL_HOST); /* target options */
1158   d_printf(SERVER_USAGE);
1159   d_printf(IPADDRESS_USAGE);
1160
1161   d_printf(MISC_OPT_USAGE); /* misc options */
1162   d_printf(PORT_USAGE);
1163   d_printf(MYWORKGROUP_USAGE);
1164   d_printf(DEBUG_USAGE);
1165   d_printf(MYNAME_USAGE);
1166   d_printf(USER_USAGE);
1167   d_printf(WORKGROUP_USAGE);
1168   d_printf(CONF_USAGE);
1169 }
1170
1171
1172 int net_groupmember(int subfunct, const char * groupname, const char * username)
1173 {
1174     struct in_addr target_ip;
1175
1176     if((have_ip == 0) && (host[0] == 0)) {
1177         if (!resolve_name("localhost", &target_ip, 0x20)) {
1178             DEBUG(1,("No remote server specified, unable to resolve connection to localhost via name lookup"));
1179             return -1;
1180         } else {
1181             have_ip = True;
1182             dest_ip = target_ip;
1183         }
1184     }
1185     if(host[0] == 0)  
1186         strncpy(host, inet_ntoa(dest_ip),16);
1187     cli = connect_to_ipc(host);
1188     if(!cli) {
1189         d_printf(ERRMSG_NOCONN_TARGET_SRVR);
1190         return -2;
1191     }
1192     if (groupname == NULL) {
1193       d_printf(ERRMSG_GROUPNAME_MISSING);
1194       return -1;
1195     }
1196
1197     if (subfunct == LIST_SF)
1198       return cli_NetGroupGetUsers(cli, groupname, group_member_fn, NULL ); 
1199
1200     if (username == NULL) {
1201       d_printf(ERRMSG_USERNAME_MISSING);
1202       return -1;
1203     }
1204
1205     if (subfunct == DELETE_SF)
1206       return cli_NetGroupDelUser(cli, groupname, username);
1207     else if (subfunct == ADD_SF)
1208       return cli_NetGroupAddUser(cli, groupname, username);
1209     else
1210       d_printf(ERRMSG_NOT_IMPLEMENTED);
1211     return -1;
1212
1213 }
1214
1215 void validate_usage(void)
1216 {
1217   d_printf(NET_VALIDATE_USAGE); /* command syntax */
1218   
1219   d_printf(TARGET_USAGE, GLBL_LCL_MASTER); /* target options */
1220   d_printf(SERVER_USAGE);
1221   d_printf(IPADDRESS_USAGE);
1222   d_printf(WORKGROUP_USAGE);
1223     
1224   d_printf(MISC_OPT_USAGE); /* misc options */
1225   d_printf(PORT_USAGE);
1226   d_printf(MYWORKGROUP_USAGE);
1227   d_printf(DEBUG_USAGE);
1228   d_printf(MYNAME_USAGE);
1229   d_printf(USER_USAGE);
1230   d_printf(CONF_USAGE);
1231 }
1232
1233 int net_validate(char * username)
1234 {
1235   d_printf(ERRMSG_NOT_IMPLEMENTED);
1236   return 0;
1237 }
1238
1239 void service_usage(void)
1240 {
1241   d_printf(NET_SERVICE_USAGE); /* command syntax */
1242   
1243   d_printf(TARGET_USAGE, GLBL_LCL_MASTER); /* target options */
1244   d_printf(SERVER_USAGE);
1245   d_printf(IPADDRESS_USAGE);
1246     
1247   d_printf(MISC_OPT_USAGE); /* misc options */
1248   d_printf(PORT_USAGE);
1249   d_printf(MYWORKGROUP_USAGE);
1250   d_printf(DEBUG_USAGE);
1251   d_printf(MYNAME_USAGE);
1252   d_printf(USER_USAGE);
1253   d_printf(CONF_USAGE);
1254 }
1255
1256
1257 int net_service(int subfunct, const char * servicename, const char * srvc_args)
1258 {
1259 struct in_addr target_ip;
1260
1261 if((have_ip == 0) && (host[0] == 0)) {
1262   if (!resolve_name("localhost", &target_ip, 0x20)) {
1263     DEBUG(1,("No remote server specified, unable to resolve connection to localhost via name lookup"));
1264     return -1;
1265   } else {
1266     have_ip = True;
1267     dest_ip = target_ip;
1268   }
1269 }
1270 if(host[0] == 0)  
1271   strncpy(host, inet_ntoa(dest_ip),16);
1272 cli = connect_to_ipc(host);
1273 if(!cli) {
1274   d_printf(ERRMSG_NOCONN_TARGET_SRVR);
1275   return -2;
1276 }
1277
1278 if (subfunct == LIST_SF) {
1279   if(long_list_entries) {
1280     d_printf("%-15.15s %-50.50s\n", SERVICE_STR, COMMENT_STR); 
1281     d_printf("-----------------------------\n");
1282     return cli_RNetServiceEnum(cli, long_group_fn, NULL);
1283   }
1284   else
1285     return cli_RNetServiceEnum(cli, group_fn, NULL); 
1286 } else
1287   d_printf(ERRMSG_NOT_IMPLEMENTED);
1288 return -1;
1289
1290 }
1291
1292 int net_password(const char * username, const char * old_password, const char * new_password)
1293 {
1294     struct in_addr target_ip;
1295
1296     if((have_ip == 0) && (host[0] == 0)) {
1297       if (!resolve_name("localhost", &target_ip, 0x20)) {
1298         DEBUG(1,("No remote server specified, unable to resolve connection to localhost via name lookup"));
1299         return -1;
1300
1301       } else {
1302         have_ip = True;
1303         dest_ip = target_ip;
1304       }
1305     }
1306     if(host[0] == 0)  
1307       strncpy(host, inet_ntoa(dest_ip),16);
1308     cli = connect_to_ipc(host);
1309     if(!cli) {
1310       d_printf(ERRMSG_NOCONN_TARGET_SRVR);
1311       return -2;
1312     }
1313
1314     /* BB Add check for password lengths? */
1315     return cli_oem_change_password(cli, username, new_password, old_password);
1316 }
1317
1318 void password_usage(void)
1319 {
1320   d_printf(NET_PASSWORD_USAGE); /* command syntax */
1321   
1322   d_printf(TARGET_USAGE, GLBL_LCL_MASTER); /* target options */
1323   d_printf(SERVER_USAGE);
1324   d_printf(IPADDRESS_USAGE);
1325   d_printf(WORKGROUP_USAGE);
1326     
1327   d_printf(MISC_OPT_USAGE); /* misc options */
1328   d_printf(PORT_USAGE);
1329   d_printf(MYWORKGROUP_USAGE);
1330   d_printf(DEBUG_USAGE);
1331   d_printf(MYNAME_USAGE);
1332   d_printf(USER_USAGE);
1333   d_printf(CONF_USAGE);
1334 }
1335
1336
1337 void admin_usage(void)
1338 {
1339   d_printf(NET_ADMIN_USAGE); /* command syntax */
1340   
1341   d_printf(TARGET_USAGE, GLBL_LCL_MASTER); /* target options */
1342   d_printf(SERVER_USAGE);
1343   d_printf(IPADDRESS_USAGE);
1344   d_printf(WORKGROUP_USAGE);
1345     
1346   d_printf(MISC_OPT_USAGE); /* misc options */
1347   d_printf(PORT_USAGE);
1348   d_printf(MYWORKGROUP_USAGE);
1349   d_printf(DEBUG_USAGE);
1350   d_printf(MYNAME_USAGE);
1351   d_printf(USER_USAGE);
1352   d_printf(CONF_USAGE);
1353 }
1354
1355
1356 int net_admin(const char * command, const char * cmd_args, const char * environment)
1357 {
1358   d_printf(ERRMSG_NOT_IMPLEMENTED);
1359   return 0;
1360
1361 }
1362
1363 void join_usage(void)
1364 {
1365         d_printf(ERRMSG_NOT_IMPLEMENTED);
1366 }
1367
1368
1369 /****************************************************************************
1370   main program
1371 ****************************************************************************/
1372 int main(int argc,char *argv[])
1373 {
1374   int opt,i;
1375   char *p;
1376   int rc = 0;
1377   int func = 0;
1378   int subfunc = LIST_SF;
1379   int argc_new = 0;
1380   const char ** argv_new;
1381   poptContext pc;
1382   static char *servicesf = CONFIGFILE;
1383   static char *target_workgroup = NULL;
1384   static char *comment = "";
1385   static char *user_name = NULL;
1386   static char *my_workgroup = NULL;
1387   static char *requester_name = NULL;
1388   static char *dest_host = NULL;
1389   static int maxusers = -1;
1390   static int flagsarg = -1;
1391   static int jobid = 0;
1392   static int debuglevel;
1393   
1394   static struct poptOption long_options[] = {
1395     {"help",        'h', POPT_ARG_NONE,   0,     'h'},
1396     {"workgroup",   'w', POPT_ARG_STRING, &target_workgroup},
1397     {"myworkgroup", 'W', POPT_ARG_STRING, &my_workgroup},
1398     {"user",        'U', POPT_ARG_STRING, &user_name, 'U'},
1399     {"ipaddress",   'I', POPT_ARG_STRING, 0,     'I'},
1400     {"port",        'p', POPT_ARG_INT,    &port},
1401     {"myname",      'n', POPT_ARG_STRING, &requester_name},
1402     {"conf",        's', POPT_ARG_STRING, &servicesf},
1403     {"debug",       'd', POPT_ARG_INT,    &debuglevel, 'd'},
1404     {"debuglevel",  'd', POPT_ARG_INT,    &debuglevel, 'd'},
1405     {"server",      'S', POPT_ARG_STRING, &dest_host},
1406     {"comment",     'C', POPT_ARG_STRING, &comment},
1407     {"maxusers",    'M', POPT_ARG_INT,    &maxusers},
1408     {"flags",       'F', POPT_ARG_INT,    &flagsarg},
1409     {"jobid",       'j', POPT_ARG_INT,    &jobid},
1410     {"long",        'l', POPT_ARG_NONE,   &long_list_entries},
1411     { 0, 0, 0, 0}
1412   };
1413
1414   got_pass = 0;
1415   dest_ip = ipzero;
1416   host[0] = 0;
1417
1418   dbf = x_stdout;
1419
1420   pc = poptGetContext(NULL, argc, (const char **) argv, long_options, 
1421                       POPT_CONTEXT_KEEP_FIRST);
1422
1423   while((opt = poptGetNextOpt(pc)) != -1) {
1424     switch (opt) {
1425       case 'h':
1426         usage();
1427         exit(0);
1428         break;
1429       case 'd':
1430         DEBUGLEVEL=debuglevel;
1431         break;
1432       case 'I':
1433         dest_ip = *interpret_addr2(poptGetOptArg(pc));
1434         if(zero_ip(dest_ip))
1435           d_printf(ERRMSG_INVALID_IPADDRESS);
1436         else
1437           have_ip = True;
1438         break;
1439       case 'U':
1440         p = strchr(user_name,'%');
1441         pstrcpy(global_user_name, user_name);
1442         if (p) {
1443           *p = 0;
1444           pstrcpy(password,p+1);
1445           got_pass = 1;
1446         }
1447         break;
1448       default:
1449         d_printf(ERRMSG_INVALID_OPTION, (char)opt, opt);
1450         usage();
1451     }
1452   }
1453
1454   lp_load(servicesf,True,False,False);       
1455
1456   argv_new = (const char **)poptGetArgs(pc);
1457
1458   argc_new = argc;
1459   for (i=0; i<argc; i++) {
1460     if (argv_new[i] == NULL) {
1461       argc_new = i;
1462       break;
1463     }
1464   }
1465          
1466   if (argc_new < 2) {
1467     usage();
1468     return -1;
1469   }
1470
1471   func = get_func(argv_new[1]);
1472
1473   if (func == 0)
1474     return -1;
1475
1476   if (argc_new < 3) {
1477     if (func == VALIDATEF) {
1478       validate_usage();
1479       return -1;
1480     }
1481     if (func == HELPF) {
1482       usage();
1483       return 0;
1484     }
1485   }
1486         
1487   if (func == HELPF) {
1488      switch(get_func(argv_new[2])) { 
1489       case FILEF:
1490             file_usage();
1491             break;
1492       case SHAREF:
1493             share_usage();
1494             break;
1495       case SESSIONF:
1496             session_usage();
1497             break;
1498       case SERVERF:
1499             server_usage();
1500             break;
1501       case DOMAINF:
1502             domain_usage();
1503             break;
1504       case PRINTQF:
1505             printq_usage();
1506             break;
1507       case USERF:
1508             user_usage();
1509             break;
1510       case GROUPF:
1511             group_usage();
1512             break;
1513       case VALIDATEF:
1514             validate_usage();
1515             break;
1516       case SERVICEF:
1517             service_usage();
1518             break;
1519       case ADMINF:
1520             admin_usage();
1521             break;
1522       case GROUPMEMBERF:
1523             groupmember_usage();
1524             break;
1525       case DOMJOINF:
1526             join_usage();
1527             break;
1528       case PASSWORDF:
1529             password_usage();
1530             break;
1531       case HELPF:
1532             usage();
1533             break;
1534       default:
1535             d_printf(ERRMSG_INVALID_HELP_OPTION);
1536             usage();
1537     }
1538     return 0;
1539   }
1540
1541   if (argc_new > 2) {
1542     /* parse next parm (argument 2) - i.e. sub function */
1543     subfunc = get_subfunc(argv_new[2]);
1544   }
1545   if (func == 0) return -1;
1546
1547   if (requester_name)
1548     pstrcpy(global_requester_name, requester_name);
1549   else
1550     get_myname(global_requester_name);
1551
1552   if (user_name)
1553     pstrcpy(global_user_name, user_name);
1554   else if (getenv("LOGNAME"))
1555     pstrcpy(global_user_name,getenv("LOGNAME"));
1556
1557   fstrcpy(global_workgroup, my_workgroup ? my_workgroup :lp_workgroup());
1558
1559   if (dest_host)
1560     pstrcpy(host, dest_host);
1561
1562   if((have_ip) && (host[0]))
1563     d_printf(ERRMSG_BOTH_SERVER_IPADDRESS);
1564
1565   while (!got_pass) {    /* BB if nulluser operation. why bother to ask for pword BB */
1566     p = getpass(PASSWORD_PROMPT);
1567     if (p) {
1568       pstrcpy(password, p);
1569       got_pass = 1;
1570     }
1571   }
1572
1573   load_interfaces();
1574
1575   switch (func) {
1576     case FILEF:
1577       if(argc_new <= 3) {
1578             if (subfunc == OTHER_SF)
1579                 rc = net_file(subfunc, argv_new[2]);
1580             else
1581                 rc = net_file(subfunc,NULL);
1582       } else 
1583             rc = net_file(subfunc,argv_new[3]);
1584       break;
1585     case SHAREF:
1586       if (argc_new == 2)
1587             rc = net_share(subfunc, NULL, NULL, 0);
1588       else
1589             rc = net_share(subfunc,argv_new[3], comment, maxusers);
1590       break;
1591     case SESSIONF:
1592       if (argc_new <= 3)
1593             rc = net_session(subfunc,NULL);
1594       else
1595             rc = net_session(subfunc,argv_new[3]);
1596       break;
1597     case SERVERF:
1598       rc = net_server(target_workgroup, subfunc);
1599       break;
1600     case DOMAINF:
1601       if(subfunc != LIST_SF)
1602             d_printf(ERRMSG_INVALID_DOMAIN_ACTION);
1603       rc = net_domain();
1604       break;
1605     case USERF:
1606       if (argc_new == 2)
1607             rc = net_user(subfunc, NULL, NULL, -1);
1608       else if(argc_new == 3)
1609             rc = net_user(subfunc,NULL, NULL, -1);
1610       else if(argc_new > 3)
1611             rc = net_user(subfunc,argv_new[3], comment, flagsarg);
1612       break;
1613     case GROUPF:
1614       if (argc_new == 2)
1615             rc = net_group(subfunc, NULL, NULL);
1616       else if(argc_new == 3)
1617             rc = net_group(subfunc,NULL, NULL);
1618       else if(argc_new > 3)
1619             rc = net_group(subfunc,argv_new[3], comment);
1620       break;
1621     case GROUPMEMBERF:
1622       if (argc_new == 4)
1623             rc = net_groupmember(subfunc, argv_new[3], NULL);
1624       else if (argc_new == 5)
1625             rc = net_groupmember(subfunc, argv_new[3], argv_new[4]);
1626       else {
1627             groupmember_usage();
1628             rc = -1;
1629       }
1630       break;
1631     case VALIDATEF:
1632       rc = net_validate(global_user_name);
1633       break;
1634     case SERVICEF:
1635       rc = net_service(subfunc, argv_new[3], argv_new[4]);
1636       break;
1637     case ADMINF:
1638       if(argc_new < 3)
1639       {
1640           admin_usage();
1641           rc = -1;
1642       }
1643       else if (argc_new == 3) {
1644           rc = net_admin(argv_new[2], NULL, NULL);
1645       } else if (argc_new == 4) {
1646           rc = net_admin(argv_new[2], argv_new[3], NULL);
1647       } else {
1648           rc = net_admin(argv_new[2], argv_new[3], argv_new[4]);
1649       }
1650       break;
1651     case PASSWORDF:
1652       if(argc_new != 5)
1653       {
1654         password_usage();
1655         rc = -1;
1656       } else {
1657         rc = net_password(argv_new[2], argv_new[3], argv_new[4]);
1658       }
1659       break;
1660     case PRINTQF:
1661       if (argc_new <= 3)
1662             rc = net_printq(subfunc, NULL, jobid);
1663       else
1664             rc = net_printq(subfunc, argv_new[3], jobid);
1665       break;
1666  /* case DOMJOINF:
1667       break; */ /* not implemented yet */
1668     default:
1669       usage();
1670       return -1;
1671   }     
1672   DEBUG(1,("return code = %d\n", rc));
1673   return rc;
1674 }
1675
1676
1677
1678