s3-net: fix crash in rap_share_add().
[ira/wip.git] / source3 / utils / net_rap.c
1 /*
2    Samba Unix/Linux SMB client library
3    Distributed SMB/CIFS Server Management Utility
4    Copyright (C) 2001 Steve French  (sfrench@us.ibm.com)
5    Copyright (C) 2001 Jim McDonough (jmcd@us.ibm.com)
6    Copyright (C) 2001 Andrew Tridgell (tridge@samba.org)
7    Copyright (C) 2001 Andrew Bartlett (abartlet@samba.org)
8
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 3 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, see <http://www.gnu.org/licenses/>.  */
24
25 #include "includes.h"
26 #include "utils/net.h"
27 #include "../librpc/gen_ndr/rap.h"
28
29 /* The following messages were for error checking that is not properly
30    reported at the moment.  Which should be reinstated? */
31 #define ERRMSG_TARGET_WG_NOT_VALID      "\nTarget workgroup option not valid "\
32                                         "except on net rap server command, ignored"
33 #define ERRMSG_INVALID_HELP_OPTION      "\nInvalid help option\n"
34
35 #define ERRMSG_BOTH_SERVER_IPADDRESS    "\nTarget server and IP address both "\
36   "specified. Do not set both at the same time.  The target IP address was used\n"
37
38 static int errmsg_not_implemented(void)
39 {
40         d_printf(_("\nNot implemented\n"));
41         return 0;
42 }
43
44 int net_rap_file_usage(struct net_context *c, int argc, const char **argv)
45 {
46         return net_file_usage(c, argc, argv);
47 }
48
49 /***************************************************************************
50   list info on an open file
51 ***************************************************************************/
52 static void file_fn(const char * pPath, const char * pUser, uint16 perms,
53                     uint16 locks, uint32 id)
54 {
55         d_printf("%-7.1d %-20.20s 0x%-4.2x %-6.1d %s\n",
56                  id, pUser, perms, locks, pPath);
57 }
58
59 static void one_file_fn(const char *pPath, const char *pUser, uint16 perms,
60                         uint16 locks, uint32 id)
61 {
62         d_printf(_("File ID          %d\n"
63                    "User name        %s\n"
64                    "Locks            0x%-4.2x\n"
65                    "Path             %s\n"
66                    "Permissions      0x%x\n"),
67                  id, pUser, locks, pPath, perms);
68 }
69
70
71 static int rap_file_close(struct net_context *c, int argc, const char **argv)
72 {
73         struct cli_state *cli;
74         int ret;
75         if (argc == 0 || c->display_usage) {
76                 return net_rap_file_usage(c, argc, argv);
77         }
78
79         if (!NT_STATUS_IS_OK(net_make_ipc_connection(c, 0, &cli)))
80                 return -1;
81
82         ret = cli_NetFileClose(cli, atoi(argv[0]));
83         cli_shutdown(cli);
84         return ret;
85 }
86
87 static int rap_file_info(struct net_context *c, int argc, const char **argv)
88 {
89         struct cli_state *cli;
90         int ret;
91         if (argc == 0 || c->display_usage)
92                 return net_rap_file_usage(c, argc, argv);
93
94         if (!NT_STATUS_IS_OK(net_make_ipc_connection(c, 0, &cli)))
95                 return -1;
96
97         ret = cli_NetFileGetInfo(cli, atoi(argv[0]), one_file_fn);
98         cli_shutdown(cli);
99         return ret;
100 }
101
102 static int rap_file_user(struct net_context *c, int argc, const char **argv)
103 {
104         struct cli_state *cli;
105         int ret;
106
107         if (argc == 0 || c->display_usage)
108                 return net_rap_file_usage(c, argc, argv);
109
110         if (!NT_STATUS_IS_OK(net_make_ipc_connection(c, 0, &cli)))
111                 return -1;
112
113         /* list open files */
114
115         d_printf(_("\nEnumerating open files on remote server:\n\n"
116                    "\nFileId  Opened by            Perms  Locks  Path \n"
117                    "------  ---------            -----  -----  ---- \n"));
118         ret = cli_NetFileEnum(cli, argv[0], NULL, file_fn);
119
120         if (ret == -1)
121                 d_printf(_("\nOperation not supported by server!\n\n"));
122
123         cli_shutdown(cli);
124         return ret;
125 }
126
127 int net_rap_file(struct net_context *c, int argc, const char **argv)
128 {
129         struct functable func[] = {
130                 {
131                         "close",
132                         rap_file_close,
133                         NET_TRANSPORT_RAP,
134                         N_("Close specified file on server"),
135                         N_("net rap file close\n"
136                            "    Close specified file on server")
137                 },
138                 {
139                         "user",
140                         rap_file_user,
141                         NET_TRANSPORT_RAP,
142                         N_("List all files opened by username"),
143                         N_("net rap file user\n"
144                            "    List all files opened by username")
145                 },
146                 {
147                         "info",
148                         rap_file_info,
149                         NET_TRANSPORT_RAP,
150                         N_("Display info about an opened file"),
151                         N_("net rap file info\n"
152                            "    Display info about an opened file")
153                 },
154                 {NULL, NULL, 0, NULL, NULL}
155         };
156
157         if (argc == 0) {
158                 struct cli_state *cli;
159                 int ret;
160
161                 if (c->display_usage) {
162                         d_printf(_("Usage:\n"));
163                         d_printf(_("net rap file\n"
164                                    "    List all open files on rempte "
165                                    "server\n"));
166                         net_display_usage_from_functable(func);
167                         return 0;
168                 }
169
170                 if (!NT_STATUS_IS_OK(net_make_ipc_connection(c, 0, &cli)))
171                         return -1;
172
173                 /* list open files */
174
175                 d_printf(_("\nEnumerating open files on remote server:\n\n"
176                            "\nFileId  Opened by            Perms  Locks  Path\n"
177                            "------  ---------            -----  -----  ----\n"));
178                 ret = cli_NetFileEnum(cli, NULL, NULL, file_fn);
179
180                 if (ret == -1)
181                         d_printf(_("\nOperation not supported by server!\n\n"));
182
183                 cli_shutdown(cli);
184                 return ret;
185         }
186
187         return net_run_function(c, argc, argv, "net rap file", func);
188 }
189
190 int net_rap_share_usage(struct net_context *c, int argc, const char **argv)
191 {
192         return net_share_usage(c, argc, argv);
193 }
194
195 static void long_share_fn(const char *share_name, uint32 type,
196                           const char *comment, void *state)
197 {
198         d_printf("%-12s %-8.8s %-50s\n",
199                  share_name, net_share_type_str(type), comment);
200 }
201
202 static void share_fn(const char *share_name, uint32 type,
203                      const char *comment, void *state)
204 {
205         d_printf("%s\n", share_name);
206 }
207
208 static int rap_share_delete(struct net_context *c, int argc, const char **argv)
209 {
210         struct cli_state *cli;
211         int ret;
212
213         if (argc == 0 || c->display_usage) {
214                 return net_rap_share_usage(c, argc, argv);
215         }
216
217         if (!NT_STATUS_IS_OK(net_make_ipc_connection(c, 0, &cli)))
218                 return -1;
219
220         ret = cli_NetShareDelete(cli, argv[0]);
221         cli_shutdown(cli);
222         return ret;
223 }
224
225 static int rap_share_add(struct net_context *c, int argc, const char **argv)
226 {
227         struct cli_state *cli;
228         int ret;
229
230         struct rap_share_info_2 sinfo;
231         char *p;
232         char *sharename;
233
234         if (argc == 0 || c->display_usage) {
235                 return net_rap_share_usage(c, argc, argv);
236         }
237
238         if (!NT_STATUS_IS_OK(net_make_ipc_connection(c, 0, &cli)))
239                 return -1;
240
241         sharename = SMB_STRDUP(argv[0]);
242         p = strchr(sharename, '=');
243         if (p == NULL) {
244                 d_printf(_("Server path not specified\n"));
245                 SAFE_FREE(sharename);
246                 return net_rap_share_usage(c, argc, argv);
247         }
248         *p = 0;
249         strlcpy((char *)sinfo.share_name, sharename, sizeof(sinfo.share_name));
250         sinfo.reserved1 = '\0';
251         sinfo.share_type = 0;
252         sinfo.comment = c->opt_comment ? smb_xstrdup(c->opt_comment) : "";
253         sinfo.perms = 0;
254         sinfo.maximum_users = c->opt_maxusers;
255         sinfo.active_users = 0;
256         sinfo.path = p+1;
257         memset(sinfo.password, '\0', sizeof(sinfo.password));
258         sinfo.reserved2 = '\0';
259
260         ret = cli_NetShareAdd(cli, &sinfo);
261         cli_shutdown(cli);
262         SAFE_FREE(sharename);
263         return ret;
264 }
265
266
267 int net_rap_share(struct net_context *c, int argc, const char **argv)
268 {
269         struct functable func[] = {
270                 {
271                         "delete",
272                         rap_share_delete,
273                         NET_TRANSPORT_RAP,
274                         N_("Delete a share from server"),
275                         N_("net rap share delete\n"
276                            "    Delete a share from server")
277                 },
278                 {
279                         "close",
280                         rap_share_delete,
281                         NET_TRANSPORT_RAP,
282                         N_("Delete a share from server"),
283                         N_("net rap share close\n"
284                            "    Delete a share from server\n"
285                            "    Alias for net rap share delete")
286                 },
287                 {
288                         "add",
289                         rap_share_add,
290                         NET_TRANSPORT_RAP,
291                         N_("Add a share to server"),
292                         N_("net rap share add\n"
293                            "    Add a share to server")
294                 },
295                 {NULL, NULL, 0, NULL, NULL}
296         };
297
298         if (argc == 0) {
299                 struct cli_state *cli;
300                 int ret;
301
302                 if (c->display_usage) {
303                         d_printf(_("Usage:\n"));
304                         d_printf(_("net rap share\n"
305                                    "    List all shares on remote server\n"));
306                         net_display_usage_from_functable(func);
307                         return 0;
308                 }
309
310                 if (!NT_STATUS_IS_OK(net_make_ipc_connection(c, 0, &cli)))
311                         return -1;
312
313                 if (c->opt_long_list_entries) {
314                         d_printf(_(
315         "\nEnumerating shared resources (exports) on remote server:\n\n"
316         "\nShare name   Type     Description\n"
317         "----------   ----     -----------\n"));
318                         ret = cli_RNetShareEnum(cli, long_share_fn, NULL);
319                 } else {
320                         ret = cli_RNetShareEnum(cli, share_fn, NULL);
321                 }
322                 cli_shutdown(cli);
323                 return ret;
324         }
325
326         return net_run_function(c, argc, argv, "net rap share", func);
327 }
328
329 int net_rap_session_usage(struct net_context *c, int argc, const char **argv)
330 {
331         d_printf(_(
332          "\nnet rap session [misc. options] [targets]"
333          "\n\tenumerates all active SMB/CIFS sessions on target server\n"));
334         d_printf(_(
335          "\nnet rap session DELETE <client_name> [misc. options] [targets] \n"
336          "\tor"
337          "\nnet rap session CLOSE <client_name> [misc. options] [targets]"
338          "\n\tDeletes (closes) a session from specified client to server\n"));
339         d_printf(_(
340         "\nnet rap session INFO <client_name>"
341         "\n\tEnumerates all open files in specified session\n"));
342
343         net_common_flags_usage(c, argc, argv);
344         return -1;
345 }
346
347 static void list_sessions_func(char *wsname, char *username, uint16 conns,
348                         uint16 opens, uint16 users, uint32 sess_time,
349                         uint32 idle_time, uint32 user_flags, char *clitype)
350 {
351         int hrs = idle_time / 3600;
352         int min = (idle_time / 60) % 60;
353         int sec = idle_time % 60;
354
355         d_printf("\\\\%-18.18s %-20.20s %-18.18s %5d %2.2d:%2.2d:%2.2d\n",
356                  wsname, username, clitype, opens, hrs, min, sec);
357 }
358
359 static void display_session_func(const char *wsname, const char *username,
360                                  uint16 conns, uint16 opens, uint16 users,
361                                  uint32 sess_time, uint32 idle_time,
362                                  uint32 user_flags, const char *clitype)
363 {
364         int ihrs = idle_time / 3600;
365         int imin = (idle_time / 60) % 60;
366         int isec = idle_time % 60;
367         int shrs = sess_time / 3600;
368         int smin = (sess_time / 60) % 60;
369         int ssec = sess_time % 60;
370         d_printf(_("User name       %-20.20s\n"
371                    "Computer        %-20.20s\n"
372                    "Guest logon     %-20.20s\n"
373                    "Client Type     %-40.40s\n"
374                    "Sess time       %2.2d:%2.2d:%2.2d\n"
375                    "Idle time       %2.2d:%2.2d:%2.2d\n"),
376                  username, wsname,
377                  (user_flags&0x0)?_("yes"):_("no"), clitype,
378                  shrs, smin, ssec, ihrs, imin, isec);
379 }
380
381 static void display_conns_func(uint16 conn_id, uint16 conn_type, uint16 opens,
382                                uint16 users, uint32 conn_time,
383                                const char *username, const char *netname)
384 {
385         d_printf("%-14.14s %-8.8s %5d\n",
386                  netname, net_share_type_str(conn_type), opens);
387 }
388
389 static int rap_session_info(struct net_context *c, int argc, const char **argv)
390 {
391         const char *sessname;
392         struct cli_state *cli;
393         int ret;
394
395         if (argc == 0 || c->display_usage)
396                 return net_rap_session_usage(c, argc, argv);
397
398         if (!NT_STATUS_IS_OK(net_make_ipc_connection(c, 0, &cli)))
399                 return -1;
400
401         sessname = argv[0];
402
403         ret = cli_NetSessionGetInfo(cli, sessname, display_session_func);
404         if (ret < 0) {
405                 cli_shutdown(cli);
406                 return ret;
407         }
408
409         d_printf(_("Share name     Type     # Opens\n-------------------------"
410                    "-----------------------------------------------------\n"));
411         ret = cli_NetConnectionEnum(cli, sessname, display_conns_func);
412         cli_shutdown(cli);
413         return ret;
414 }
415
416 static int rap_session_delete(struct net_context *c, int argc, const char **argv)
417 {
418         struct cli_state *cli;
419         int ret;
420
421         if (argc == 0 || c->display_usage)
422                 return net_rap_session_usage(c, argc, argv);
423
424         if (!NT_STATUS_IS_OK(net_make_ipc_connection(c, 0, &cli)))
425                 return -1;
426
427         ret = cli_NetSessionDel(cli, argv[0]);
428         cli_shutdown(cli);
429         return ret;
430 }
431
432 int net_rap_session(struct net_context *c, int argc, const char **argv)
433 {
434         struct functable func[] = {
435                 {
436                         "info",
437                         rap_session_info,
438                         NET_TRANSPORT_RAP,
439                         N_("Display information about session"),
440                         N_("net rap session info\n"
441                            "    Display information about session")
442                 },
443                 {
444                         "delete",
445                         rap_session_delete,
446                         NET_TRANSPORT_RAP,
447                         N_("Close specified session"),
448                         N_("net rap session delete\n"
449                            "    Close specified session\n"
450                            "    Alias for net rap session close")
451                 },
452                 {
453                         "close",
454                         rap_session_delete,
455                         NET_TRANSPORT_RAP,
456                         N_("Close specified session"),
457                         N_("net rap session close\n"
458                            "    Close specified session")
459                 },
460                 {NULL, NULL, 0, NULL, NULL}
461         };
462
463         if (argc == 0) {
464                 struct cli_state *cli;
465                 int ret;
466
467                 if (c->display_usage) {
468                         d_printf(_("Usage:\n"));
469                         d_printf(_("net rap session\n"
470                                    "    List all open sessions on remote "
471                                    "server\n"));
472                         net_display_usage_from_functable(func);
473                         return 0;
474                 }
475
476                 if (!NT_STATUS_IS_OK(net_make_ipc_connection(c, 0, &cli)))
477                         return -1;
478
479                 d_printf(_("Computer             User name            "
480                            "Client Type        Opens Idle time\n"
481                            "------------------------------------------"
482                            "------------------------------------\n"));
483                 ret = cli_NetSessionEnum(cli, list_sessions_func);
484
485                 cli_shutdown(cli);
486                 return ret;
487         }
488
489         return net_run_function(c, argc, argv, "net rap session", func);
490 }
491
492 /****************************************************************************
493 list a server name
494 ****************************************************************************/
495 static void display_server_func(const char *name, uint32 m,
496                                 const char *comment, void * reserved)
497 {
498         d_printf("\t%-16.16s     %s\n", name, comment);
499 }
500
501 static int net_rap_server_name(struct net_context *c, int argc, const char *argv[])
502 {
503         struct cli_state *cli;
504         char *name;
505
506         if (c->display_usage) {
507                 d_printf("%s\n%s",
508                          _("Usage:"),
509                          _("net rap server name\n"
510                            "    Get the name of the server\n"));
511                 return 0;
512         }
513
514         if (!NT_STATUS_IS_OK(net_make_ipc_connection(c, 0, &cli)))
515                 return -1;
516
517         if (!cli_get_server_name(NULL, cli, &name)) {
518                 d_fprintf(stderr, _("cli_get_server_name failed\n"));
519                 cli_shutdown(cli);
520                 return -1;
521         }
522
523         d_printf(_("Server name = %s\n"), name);
524
525         TALLOC_FREE(name);
526         cli_shutdown(cli);
527         return 0;
528 }
529
530 static int net_rap_server_domain(struct net_context *c, int argc,
531                                  const char **argv)
532 {
533         struct cli_state *cli;
534         int ret;
535
536         if (c->display_usage) {
537                 d_printf("%s\n%s",
538                          _("Usage:"),
539                          _("net rap server domain\n"
540                            "    Enumerate servers in this domain/workgroup\n"));
541                 return 0;
542         }
543
544         if (!NT_STATUS_IS_OK(net_make_ipc_connection(c, 0, &cli)))
545                 return -1;
546
547         d_printf(_("\nEnumerating servers in this domain or workgroup: \n\n"
548                    "\tServer name          Server description\n"
549                    "\t-------------        ----------------------------\n"));
550
551         ret = cli_NetServerEnum(cli, cli->server_domain, SV_TYPE_ALL,
552                                 display_server_func,NULL);
553         cli_shutdown(cli);
554         return ret;
555 }
556
557 int net_rap_server(struct net_context *c, int argc, const char **argv)
558 {
559         struct functable func[] = {
560                 {
561                         "name",
562                         net_rap_server_name,
563                         NET_TRANSPORT_RAP,
564                         N_("Get the name of the server"),
565                         N_("net rap server name\n"
566                            "    Get the name of the server")
567                 },
568                 {
569                         "domain",
570                         net_rap_server_domain,
571                         NET_TRANSPORT_RAP,
572                         N_("Get the servers in this domain/workgroup"),
573                         N_("net rap server domain\n"
574                            "    Get the servers in this domain/workgroup")
575                 },
576                 {NULL, NULL, 0, NULL, NULL}
577         };
578
579         /* smb4k uses 'net [rap|rpc] server domain' to query servers in a domain */
580         /* Fall through for 'domain', any other forms will cause to show usage message */
581         return net_run_function(c, argc, argv, "net rap server", func);
582
583 }
584
585 int net_rap_domain_usage(struct net_context *c, int argc, const char **argv)
586 {
587         d_printf(_("net rap domain [misc. options] [target]\n\tlists the"
588                    " domains or workgroups visible on the current network\n"));
589
590         net_common_flags_usage(c, argc, argv);
591         return -1;
592 }
593
594 int net_rap_domain(struct net_context *c, int argc, const char **argv)
595 {
596         struct cli_state *cli;
597         int ret;
598
599         if (c->display_usage)
600                 return net_rap_domain_usage(c, argc, argv);
601
602         if (!NT_STATUS_IS_OK(net_make_ipc_connection(c, 0, &cli)))
603                 return -1;
604
605         d_printf(_("\nEnumerating domains:\n\n"
606                    "\tDomain name          Server name of Browse Master\n"
607                    "\t-------------        ----------------------------\n"));
608
609         ret = cli_NetServerEnum(cli, cli->server_domain, SV_TYPE_DOMAIN_ENUM,
610                                 display_server_func,NULL);
611         cli_shutdown(cli);
612         return ret;
613 }
614
615 int net_rap_printq_usage(struct net_context *c, int argc, const char **argv)
616 {
617         d_printf(_(
618          "net rap printq [misc. options] [targets]\n"
619          "\tor\n"
620          "net rap printq info [<queue_name>] [misc. options] [targets]\n"
621          "\tlists the specified queue and jobs on the target server.\n"
622          "\tIf the queue name is not specified, all queues are listed.\n\n"));
623         d_printf(_(
624          "net rap printq delete [<queue name>] [misc. options] [targets]\n"
625          "\tdeletes the specified job number on the target server, or the\n"
626          "\tprinter queue if no job number is specified\n"));
627
628         net_common_flags_usage(c, argc, argv);
629
630         return -1;
631 }
632
633 static void enum_queue(const char *queuename, uint16 pri, uint16 start,
634                        uint16 until, const char *sep, const char *pproc,
635                        const char *dest, const char *qparms,
636                        const char *qcomment, uint16 status, uint16 jobcount)
637 {
638         d_printf(_("%-17.17s Queue %5d jobs                      "),
639                  queuename, jobcount);
640
641         switch (status) {
642         case 0:
643                 d_printf(_("*Printer Active*\n"));
644                 break;
645         case 1:
646                 d_printf(_("*Printer Paused*\n"));
647                 break;
648         case 2:
649                 d_printf(_("*Printer error*\n"));
650                 break;
651         case 3:
652                 d_printf(_("*Delete Pending*\n"));
653                 break;
654         default:
655                 d_printf(_("**UNKNOWN STATUS**\n"));
656         }
657 }
658
659 static void enum_jobs(uint16 jobid, const char *ownername,
660                       const char *notifyname, const char *datatype,
661                       const char *jparms, uint16 pos, uint16 status,
662                       const char *jstatus, unsigned int submitted, unsigned int jobsize,
663                       const char *comment)
664 {
665         d_printf("     %-23.23s %5d %9d            ",
666                  ownername, jobid, jobsize);
667         switch (status) {
668         case 0:
669                 d_printf(_("Waiting\n"));
670                 break;
671         case 1:
672                 d_printf(_("Held in queue\n"));
673                 break;
674         case 2:
675                 d_printf(_("Spooling\n"));
676                 break;
677         case 3:
678                 d_printf(_("Printing\n"));
679                 break;
680         default:
681                 d_printf(_("**UNKNOWN STATUS**\n"));
682         }
683 }
684
685 #define PRINTQ_ENUM_DISPLAY \
686     _("Print queues at \\\\%s\n\n"\
687       "Name                         Job #      Size            Status\n\n"\
688       "------------------------------------------------------------------"\
689       "-------------\n")
690
691 static int rap_printq_info(struct net_context *c, int argc, const char **argv)
692 {
693         struct cli_state *cli;
694         int ret;
695
696         if (argc == 0 || c->display_usage)
697                 return net_rap_printq_usage(c, argc, argv);
698
699         if (!NT_STATUS_IS_OK(net_make_ipc_connection(c, 0, &cli)))
700                 return -1;
701
702         d_printf(PRINTQ_ENUM_DISPLAY, cli->desthost); /* list header */
703         ret = cli_NetPrintQGetInfo(cli, argv[0], enum_queue, enum_jobs);
704         cli_shutdown(cli);
705         return ret;
706 }
707
708 static int rap_printq_delete(struct net_context *c, int argc, const char **argv)
709 {
710         struct cli_state *cli;
711         int ret;
712
713         if (argc == 0 || c->display_usage)
714                 return net_rap_printq_usage(c, argc, argv);
715
716         if (!NT_STATUS_IS_OK(net_make_ipc_connection(c, 0, &cli)))
717                 return -1;
718
719         ret = cli_printjob_del(cli, atoi(argv[0]));
720         cli_shutdown(cli);
721         return ret;
722 }
723
724 int net_rap_printq(struct net_context *c, int argc, const char **argv)
725 {
726         struct cli_state *cli;
727         int ret;
728
729         struct functable func[] = {
730                 {
731                         "info",
732                         rap_printq_info,
733                         NET_TRANSPORT_RAP,
734                         N_("Display info about print queues and jobs"),
735                         N_("net rap printq info [queue]\n"
736                            "    Display info about print jobs in queue.\n"
737                            "    If queue is not specified, all queues are "
738                            "listed")
739                 },
740                 {
741                         "delete",
742                         rap_printq_delete,
743                         NET_TRANSPORT_RAP,
744                         N_("Delete print job(s)"),
745                         N_("net rap printq delete\n"
746                            "    Delete print job(s)")
747                 },
748                 {NULL, NULL, 0, NULL, NULL}
749         };
750
751         if (argc == 0) {
752                 if (c->display_usage) {
753                         d_printf(_("Usage:\n"));
754                         d_printf(_("net rap printq\n"
755                                    "    List the print queue\n"));
756                         net_display_usage_from_functable(func);
757                         return 0;
758                 }
759
760                 if (!NT_STATUS_IS_OK(net_make_ipc_connection(c, 0, &cli)))
761                         return -1;
762
763                 d_printf(PRINTQ_ENUM_DISPLAY, cli->desthost); /* list header */
764                 ret = cli_NetPrintQEnum(cli, enum_queue, enum_jobs);
765                 cli_shutdown(cli);
766                 return ret;
767         }
768
769         return net_run_function(c, argc, argv, "net rap printq", func);
770 }
771
772 static int net_rap_user_usage(struct net_context *c, int argc, const char **argv)
773 {
774         return net_user_usage(c, argc, argv);
775 }
776
777 static void user_fn(const char *user_name, void *state)
778 {
779         d_printf("%-21.21s\n", user_name);
780 }
781
782 static void long_user_fn(const char *user_name, const char *comment,
783                          const char * home_dir, const char * logon_script,
784                          void *state)
785 {
786         d_printf("%-21.21s %s\n",
787                  user_name, comment);
788 }
789
790 static void group_member_fn(const char *user_name, void *state)
791 {
792         d_printf("%-21.21s\n", user_name);
793 }
794
795 static int rap_user_delete(struct net_context *c, int argc, const char **argv)
796 {
797         struct cli_state *cli;
798         int ret;
799
800         if (argc == 0 || c->display_usage) {
801                 return net_rap_user_usage(c, argc, argv);
802         }
803
804         if (!NT_STATUS_IS_OK(net_make_ipc_connection(c, 0, &cli)))
805                 return -1;
806
807         ret = cli_NetUserDelete(cli, argv[0]);
808         cli_shutdown(cli);
809         return ret;
810 }
811
812 static int rap_user_add(struct net_context *c, int argc, const char **argv)
813 {
814         struct cli_state *cli;
815         int ret;
816         struct rap_user_info_1 userinfo;
817
818         if (argc == 0 || c->display_usage) {
819                 return net_rap_user_usage(c, argc, argv);
820         }
821
822         if (!NT_STATUS_IS_OK(net_make_ipc_connection(c, 0, &cli)))
823                 return -1;
824
825         safe_strcpy((char *)userinfo.user_name, argv[0], sizeof(userinfo.user_name)-1);
826         if (c->opt_flags == -1)
827                 c->opt_flags = 0x21;
828
829         userinfo.userflags = c->opt_flags;
830         userinfo.reserved1 = '\0';
831         userinfo.comment = smb_xstrdup(c->opt_comment ? c->opt_comment : "");
832         userinfo.priv = 1;
833         userinfo.home_dir = NULL;
834         userinfo.logon_script = NULL;
835         userinfo.passwrd[0] = '\0';
836
837         ret = cli_NetUserAdd(cli, &userinfo);
838
839         cli_shutdown(cli);
840         return ret;
841 }
842
843 static int rap_user_info(struct net_context *c, int argc, const char **argv)
844 {
845         struct cli_state *cli;
846         int ret;
847         if (argc == 0 || c->display_usage) {
848                 return net_rap_user_usage(c, argc, argv);
849         }
850
851         if (!NT_STATUS_IS_OK(net_make_ipc_connection(c, 0, &cli)))
852                 return -1;
853
854         ret = cli_NetUserGetGroups(cli, argv[0], group_member_fn, NULL);
855         cli_shutdown(cli);
856         return ret;
857 }
858
859 int net_rap_user(struct net_context *c, int argc, const char **argv)
860 {
861         int ret = -1;
862         struct functable func[] = {
863                 {
864                         "add",
865                         rap_user_add,
866                         NET_TRANSPORT_RAP,
867                         N_("Add specified user"),
868                         N_("net rap user add\n"
869                            "    Add specified user")
870                 },
871                 {
872                         "info",
873                         rap_user_info,
874                         NET_TRANSPORT_RAP,
875                         N_("List domain groups of specified user"),
876                         N_("net rap user info\n"
877                            "    List domain groups of specified user")
878
879                 },
880                 {
881                         "delete",
882                         rap_user_delete,
883                         NET_TRANSPORT_RAP,
884                         N_("Remove specified user"),
885                         N_("net rap user delete\n"
886                            "    Remove specified user")
887                 },
888                 {NULL, NULL, 0, NULL, NULL}
889         };
890
891         if (argc == 0) {
892                 struct cli_state *cli;
893                 if (c->display_usage) {
894                         d_printf(_("Usage:\n"));
895                         d_printf(_("net rap user\n"
896                                    "    List all users\n"));
897                         net_display_usage_from_functable(func);
898                         return 0;
899                 }
900
901                 if (!NT_STATUS_IS_OK(net_make_ipc_connection(c, 0, &cli)))
902                         goto done;
903                 if (c->opt_long_list_entries) {
904                         d_printf(_("\nUser name             Comment"
905                                    "\n-----------------------------\n"));
906                         ret = cli_RNetUserEnum(cli, long_user_fn, NULL);
907                         cli_shutdown(cli);
908                         goto done;
909                 }
910                 ret = cli_RNetUserEnum0(cli, user_fn, NULL);
911                 cli_shutdown(cli);
912                 goto done;
913         }
914
915         ret = net_run_function(c, argc, argv, "net rap user", func);
916  done:
917         if (ret != 0) {
918                 DEBUG(1, (_("Net user returned: %d\n"), ret));
919         }
920         return ret;
921 }
922
923
924 int net_rap_group_usage(struct net_context *c, int argc, const char **argv)
925 {
926         return net_group_usage(c, argc, argv);
927 }
928
929 static void long_group_fn(const char *group_name, const char *comment,
930                           void *state)
931 {
932         d_printf("%-21.21s %s\n", group_name, comment);
933 }
934
935 static void group_fn(const char *group_name, void *state)
936 {
937         d_printf("%-21.21s\n", group_name);
938 }
939
940 static int rap_group_delete(struct net_context *c, int argc, const char **argv)
941 {
942         struct cli_state *cli;
943         int ret;
944         if (argc == 0 || c->display_usage) {
945                 return net_rap_group_usage(c, argc, argv);
946         }
947
948         if (!NT_STATUS_IS_OK(net_make_ipc_connection(c, 0, &cli)))
949                 return -1;
950
951         ret = cli_NetGroupDelete(cli, argv[0]);
952         cli_shutdown(cli);
953         return ret;
954 }
955
956 static int rap_group_add(struct net_context *c, int argc, const char **argv)
957 {
958         struct cli_state *cli;
959         int ret;
960         struct rap_group_info_1 grinfo;
961
962         if (argc == 0 || c->display_usage) {
963                 return net_rap_group_usage(c, argc, argv);
964         }
965
966         if (!NT_STATUS_IS_OK(net_make_ipc_connection(c, 0, &cli)))
967                 return -1;
968
969         /* BB check for length 21 or smaller explicitly ? BB */
970         safe_strcpy((char *)grinfo.group_name, argv[0], sizeof(grinfo.group_name)-1);
971         grinfo.reserved1 = '\0';
972         grinfo.comment = smb_xstrdup(c->opt_comment ? c->opt_comment : "");
973
974         ret = cli_NetGroupAdd(cli, &grinfo);
975         cli_shutdown(cli);
976         return ret;
977 }
978
979 int net_rap_group(struct net_context *c, int argc, const char **argv)
980 {
981         struct functable func[] = {
982                 {
983                         "add",
984                         rap_group_add,
985                         NET_TRANSPORT_RAP,
986                         N_("Add specified group"),
987                         N_("net rap group add\n"
988                            "    Add specified group")
989                 },
990                 {
991                         "delete",
992                         rap_group_delete,
993                         NET_TRANSPORT_RAP,
994                         N_("Delete specified group"),
995                         N_("net rap group delete\n"
996                            "    Delete specified group")
997                 },
998                 {NULL, NULL, 0, NULL, NULL}
999         };
1000
1001         if (argc == 0) {
1002                 struct cli_state *cli;
1003                 int ret;
1004                 if (c->display_usage) {
1005                         d_printf(_("Usage:\n"));
1006                         d_printf(_("net rap group\n"
1007                                    "    List all groups\n"));
1008                         net_display_usage_from_functable(func);
1009                         return 0;
1010                 }
1011
1012                 if (!NT_STATUS_IS_OK(net_make_ipc_connection(c, 0, &cli)))
1013                         return -1;
1014                 if (c->opt_long_list_entries) {
1015                         d_printf(_("Group name            Comment\n"
1016                                    "-----------------------------\n"));
1017                         ret = cli_RNetGroupEnum(cli, long_group_fn, NULL);
1018                         cli_shutdown(cli);
1019                         return ret;
1020                 }
1021                 ret = cli_RNetGroupEnum0(cli, group_fn, NULL);
1022                 cli_shutdown(cli);
1023                 return ret;
1024         }
1025
1026         return net_run_function(c, argc, argv, "net rap group", func);
1027 }
1028
1029 int net_rap_groupmember_usage(struct net_context *c, int argc, const char **argv)
1030 {
1031         d_printf(_(
1032          "net rap groupmember LIST <group> [misc. options] [targets]"
1033          "\n\t Enumerate users in a group\n"
1034          "\nnet rap groupmember DELETE <group> <user> [misc. options] "
1035          "[targets]\n\t Delete specified user from specified group\n"
1036          "\nnet rap groupmember ADD <group> <user> [misc. options] [targets]"
1037          "\n\t Add specified user to specified group\n"));
1038
1039         net_common_flags_usage(c, argc, argv);
1040         return -1;
1041 }
1042
1043
1044 static int rap_groupmember_add(struct net_context *c, int argc, const char **argv)
1045 {
1046         struct cli_state *cli;
1047         int ret;
1048         if (argc != 2 || c->display_usage) {
1049                 return net_rap_groupmember_usage(c, argc, argv);
1050         }
1051
1052         if (!NT_STATUS_IS_OK(net_make_ipc_connection(c, 0, &cli)))
1053                 return -1;
1054
1055         ret = cli_NetGroupAddUser(cli, argv[0], argv[1]);
1056         cli_shutdown(cli);
1057         return ret;
1058 }
1059
1060 static int rap_groupmember_delete(struct net_context *c, int argc, const char **argv)
1061 {
1062         struct cli_state *cli;
1063         int ret;
1064         if (argc != 2 || c->display_usage) {
1065                 return net_rap_groupmember_usage(c, argc, argv);
1066         }
1067
1068         if (!NT_STATUS_IS_OK(net_make_ipc_connection(c, 0, &cli)))
1069                 return -1;
1070
1071         ret = cli_NetGroupDelUser(cli, argv[0], argv[1]);
1072         cli_shutdown(cli);
1073         return ret;
1074 }
1075
1076 static int rap_groupmember_list(struct net_context *c, int argc, const char **argv)
1077 {
1078         struct cli_state *cli;
1079         int ret;
1080         if (argc == 0 || c->display_usage) {
1081                 return net_rap_groupmember_usage(c, argc, argv);
1082         }
1083
1084         if (!NT_STATUS_IS_OK(net_make_ipc_connection(c, 0, &cli)))
1085                 return -1;
1086
1087         ret = cli_NetGroupGetUsers(cli, argv[0], group_member_fn, NULL );
1088         cli_shutdown(cli);
1089         return ret;
1090 }
1091
1092 int net_rap_groupmember(struct net_context *c, int argc, const char **argv)
1093 {
1094         struct functable func[] = {
1095                 {
1096                         "add",
1097                         rap_groupmember_add,
1098                         NET_TRANSPORT_RAP,
1099                         N_("Add specified user to group"),
1100                         N_("net rap groupmember add\n"
1101                            "    Add specified user to group")
1102                 },
1103                 {
1104                         "list",
1105                         rap_groupmember_list,
1106                         NET_TRANSPORT_RAP,
1107                         N_("List users in group"),
1108                         N_("net rap groupmember list\n"
1109                            "    List users in group")
1110                 },
1111                 {
1112                         "delete",
1113                         rap_groupmember_delete,
1114                         NET_TRANSPORT_RAP,
1115                         N_("Remove user from group"),
1116                         N_("net rap groupmember delete\n"
1117                            "    Remove user from group")
1118                 },
1119                 {NULL, NULL, 0, NULL, NULL}
1120         };
1121
1122         return net_run_function(c, argc, argv, "net rap groupmember", func);
1123 }
1124
1125 int net_rap_validate_usage(struct net_context *c, int argc, const char **argv)
1126 {
1127         d_printf(_("net rap validate <username> [password]\n"
1128                    "\tValidate user and password to check whether they"
1129                    " can access target server or domain\n"));
1130
1131         net_common_flags_usage(c, argc, argv);
1132         return -1;
1133 }
1134
1135 int net_rap_validate(struct net_context *c, int argc, const char **argv)
1136 {
1137         return errmsg_not_implemented();
1138 }
1139
1140 int net_rap_service_usage(struct net_context *c, int argc, const char **argv)
1141 {
1142         d_printf(_("net rap service [misc. options] [targets] \n"
1143                  "\tlists all running service daemons on target server\n"));
1144         d_printf(_("\nnet rap service START <name> [service startup arguments]"
1145                  " [misc. options] [targets]"
1146                  "\n\tStart named service on remote server\n"));
1147         d_printf(_("\nnet rap service STOP <name> [misc. options] [targets]\n"
1148                  "\n\tStop named service on remote server\n"));
1149
1150         net_common_flags_usage(c, argc, argv);
1151         return -1;
1152 }
1153
1154 static int rap_service_start(struct net_context *c, int argc, const char **argv)
1155 {
1156         return errmsg_not_implemented();
1157 }
1158
1159 static int rap_service_stop(struct net_context *c, int argc, const char **argv)
1160 {
1161         return errmsg_not_implemented();
1162 }
1163
1164 static void service_fn(const char *service_name, const char *dummy,
1165                        void *state)
1166 {
1167         d_printf("%-21.21s\n", service_name);
1168 }
1169
1170 int net_rap_service(struct net_context *c, int argc, const char **argv)
1171 {
1172         struct functable func[] = {
1173                 {
1174                         "start",
1175                         rap_service_start,
1176                         NET_TRANSPORT_RAP,
1177                         N_("Start service on remote server"),
1178                         N_("net rap service start\n"
1179                            "    Start service on remote server")
1180                 },
1181                 {
1182                         "stop",
1183                         rap_service_stop,
1184                         NET_TRANSPORT_RAP,
1185                         N_("Stop named serve on remote server"),
1186                         N_("net rap service stop\n"
1187                            "    Stop named serve on remote server")
1188                 },
1189                 {NULL, NULL, 0, NULL, NULL}
1190         };
1191
1192         if (argc == 0) {
1193                 struct cli_state *cli;
1194                 int ret;
1195                 if (c->display_usage) {
1196                         d_printf(_("Usage:\n"));
1197                         d_printf(_("net rap service\n"
1198                                    "    List services on remote server\n"));
1199                         net_display_usage_from_functable(func);
1200                         return 0;
1201                 }
1202
1203                 if (!NT_STATUS_IS_OK(net_make_ipc_connection(c, 0, &cli)))
1204                         return -1;
1205
1206                 if (c->opt_long_list_entries) {
1207                         d_printf(_("Service name          Comment\n"
1208                                    "-----------------------------\n"));
1209                         ret = cli_RNetServiceEnum(cli, long_group_fn, NULL);
1210                 }
1211                 ret = cli_RNetServiceEnum(cli, service_fn, NULL);
1212                 cli_shutdown(cli);
1213                 return ret;
1214         }
1215
1216         return net_run_function(c, argc, argv, "net rap service", func);
1217 }
1218
1219 int net_rap_password_usage(struct net_context *c, int argc, const char **argv)
1220 {
1221         d_printf(_(
1222          "net rap password <user> <oldpwo> <newpw> [misc. options] [target]\n"
1223          "\tchanges the password for the specified user at target\n"));
1224
1225         return -1;
1226 }
1227
1228
1229 int net_rap_password(struct net_context *c, int argc, const char **argv)
1230 {
1231         struct cli_state *cli;
1232         int ret;
1233
1234         if (argc < 3 || c->display_usage)
1235                 return net_rap_password_usage(c, argc, argv);
1236
1237         if (!NT_STATUS_IS_OK(net_make_ipc_connection(c, 0, &cli)))
1238                 return -1;
1239
1240         /* BB Add check for password lengths? */
1241         ret = cli_oem_change_password(cli, argv[0], argv[2], argv[1]);
1242         cli_shutdown(cli);
1243         return ret;
1244 }
1245
1246 int net_rap_admin_usage(struct net_context *c, int argc, const char **argv)
1247 {
1248         d_printf(_(
1249    "net rap admin <remote command> [cmd args [env]] [misc. options] [targets]"
1250    "\n\texecutes a remote command on an os/2 target server\n"));
1251
1252         return -1;
1253 }
1254
1255
1256 int net_rap_admin(struct net_context *c, int argc, const char **argv)
1257 {
1258         return errmsg_not_implemented();
1259 }
1260
1261 /* Entry-point for all the RAP functions. */
1262
1263 int net_rap(struct net_context *c, int argc, const char **argv)
1264 {
1265         struct functable func[] = {
1266                 {
1267                         "file",
1268                         net_rap_file,
1269                         NET_TRANSPORT_RAP,
1270                         N_("List open files"),
1271                         N_("net rap file\n"
1272                            "    List open files")
1273                 },
1274                 {
1275                         "share",
1276                         net_rap_share,
1277                         NET_TRANSPORT_RAP,
1278                         N_("List shares exported by server"),
1279                         N_("net rap share\n"
1280                            "    List shares exported by server")
1281                 },
1282                 {
1283                         "session",
1284                         net_rap_session,
1285                         NET_TRANSPORT_RAP,
1286                         N_("List open sessions"),
1287                         N_("net rap session\n"
1288                            "    List open sessions")
1289                 },
1290                 {
1291                         "server",
1292                         net_rap_server,
1293                         NET_TRANSPORT_RAP,
1294                         N_("List servers in workgroup"),
1295                         N_("net rap server\n"
1296                            "    List servers in domain/workgroup")
1297                 },
1298                 {
1299                         "domain",
1300                         net_rap_domain,
1301                         NET_TRANSPORT_RAP,
1302                         N_("List domains in network"),
1303                         N_("net rap domain\n"
1304                            "    List domains in network")
1305                 },
1306                 {
1307                         "printq",
1308                         net_rap_printq,
1309                         NET_TRANSPORT_RAP,
1310                         N_("List printer queues on server"),
1311                         N_("net rap printq\n"
1312                            "    List printer queues on server")
1313                 },
1314                 {
1315                         "user",
1316                         net_rap_user,
1317                         NET_TRANSPORT_RAP,
1318                         N_("List users"),
1319                         N_("net rap user\n"
1320                            "    List users")
1321                 },
1322                 {
1323                         "group",
1324                         net_rap_group,
1325                         NET_TRANSPORT_RAP,
1326                         N_("List user groups"),
1327                         N_("net rap group\n"
1328                            "    List user groups")
1329                 },
1330                 {
1331                         "validate",
1332                         net_rap_validate,
1333                         NET_TRANSPORT_RAP,
1334                         N_("Check username/password"),
1335                         N_("net rap validate\n"
1336                            "    Check username/password")
1337                 },
1338                 {
1339                         "groupmember",
1340                         net_rap_groupmember,
1341                         NET_TRANSPORT_RAP,
1342                         N_("List/modify group memberships"),
1343                         N_("net rap groupmember\n"
1344                            "    List/modify group memberships")
1345                 },
1346                 {
1347                         "admin",
1348                         net_rap_admin,
1349                         NET_TRANSPORT_RAP,
1350                         N_("Execute commands on remote OS/2"),
1351                         N_("net rap admin\n"
1352                            "    Execute commands on remote OS/2")
1353                 },
1354                 {
1355                         "service",
1356                         net_rap_service,
1357                         NET_TRANSPORT_RAP,
1358                         N_("Start/stop remote service"),
1359                         N_("net rap service\n"
1360                            "    Start/stop remote service")
1361                 },
1362                 {
1363                         "password",
1364                         net_rap_password,
1365                         NET_TRANSPORT_RAP,
1366                         N_("Change user password"),
1367                         N_("net rap password\n"
1368                            "    Change user password")
1369                 },
1370                 {NULL, NULL, 0, NULL, NULL}
1371         };
1372
1373         return net_run_function(c, argc, argv, "net rap", func);
1374 }
1375