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