s3: smbcontrol to notify smbd about idmap changes
[metze/samba/wip.git] / source3 / utils / smbcontrol.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    Send messages to other Samba daemons
5
6    Copyright (C) Tim Potter 2003
7    Copyright (C) Andrew Tridgell 1994-1998
8    Copyright (C) Martin Pool 2001-2002
9    Copyright (C) Simo Sorce 2002
10    Copyright (C) James Peach 2006
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
26 #include "includes.h"
27 #include "popt_common.h"
28 #include "librpc/gen_ndr/messaging.h"
29 #include "librpc/gen_ndr/spoolss.h"
30 #include "nt_printing.h"
31 #include "printing/notify.h"
32
33 #if HAVE_LIBUNWIND_H
34 #include <libunwind.h>
35 #endif
36
37 #if HAVE_LIBUNWIND_PTRACE_H
38 #include <libunwind-ptrace.h>
39 #endif
40
41 #if HAVE_SYS_PTRACE_H
42 #include <sys/ptrace.h>
43 #endif
44
45 /* Default timeout value when waiting for replies (in seconds) */
46
47 #define DEFAULT_TIMEOUT 10
48
49 static int timeout = DEFAULT_TIMEOUT;
50 static int num_replies;         /* Used by message callback fns */
51
52 /* Send a message to a destination pid.  Zero means broadcast smbd. */
53
54 static bool send_message(struct messaging_context *msg_ctx,
55                          struct server_id pid, int msg_type,
56                          const void *buf, int len)
57 {
58         bool ret;
59         int n_sent = 0;
60
61         if (procid_to_pid(&pid) != 0)
62                 return NT_STATUS_IS_OK(
63                         messaging_send_buf(msg_ctx, pid, msg_type,
64                                            (uint8 *)buf, len));
65
66         ret = message_send_all(msg_ctx, msg_type, buf, len, &n_sent);
67         DEBUG(10,("smbcontrol/send_message: broadcast message to "
68                   "%d processes\n", n_sent));
69
70         return ret;
71 }
72
73 static void smbcontrol_timeout(struct tevent_context *event_ctx,
74                                struct tevent_timer *te,
75                                struct timeval now,
76                                void *private_data)
77 {
78         bool *timed_out = (bool *)private_data;
79         TALLOC_FREE(te);
80         *timed_out = True;
81 }
82
83 /* Wait for one or more reply messages */
84
85 static void wait_replies(struct messaging_context *msg_ctx,
86                          bool multiple_replies)
87 {
88         struct tevent_timer *te;
89         bool timed_out = False;
90
91         if (!(te = tevent_add_timer(messaging_event_context(msg_ctx), NULL,
92                                     timeval_current_ofs(timeout, 0),
93                                     smbcontrol_timeout, (void *)&timed_out))) {
94                 DEBUG(0, ("tevent_add_timer failed\n"));
95                 return;
96         }
97
98         while (!timed_out) {
99                 int ret;
100                 if (num_replies > 0 && !multiple_replies)
101                         break;
102                 ret = tevent_loop_once(messaging_event_context(msg_ctx));
103                 if (ret != 0) {
104                         break;
105                 }
106         }
107 }
108
109 /* Message handler callback that displays the PID and a string on stdout */
110
111 static void print_pid_string_cb(struct messaging_context *msg,
112                                 void *private_data, 
113                                 uint32_t msg_type, 
114                                 struct server_id pid,
115                                 DATA_BLOB *data)
116 {
117         char *pidstr;
118
119         pidstr = procid_str(talloc_tos(), &pid);
120         printf("PID %s: %.*s", pidstr, (int)data->length,
121                (const char *)data->data);
122         TALLOC_FREE(pidstr);
123         num_replies++;
124 }
125
126 /* Message handler callback that displays a string on stdout */
127
128 static void print_string_cb(struct messaging_context *msg,
129                             void *private_data, 
130                             uint32_t msg_type, 
131                             struct server_id pid,
132                             DATA_BLOB *data)
133 {
134         printf("%*s", (int)data->length, (const char *)data->data);
135         num_replies++;
136 }
137
138 /* Send no message.  Useful for testing. */
139
140 static bool do_noop(struct messaging_context *msg_ctx,
141                     const struct server_id pid,
142                     const int argc, const char **argv)
143 {
144         if (argc != 1) {
145                 fprintf(stderr, "Usage: smbcontrol <dest> noop\n");
146                 return False;
147         }
148
149         /* Move along, nothing to see here */
150
151         return True;
152 }
153
154 /* Send a debug string */
155
156 static bool do_debug(struct messaging_context *msg_ctx,
157                      const struct server_id pid,
158                      const int argc, const char **argv)
159 {
160         if (argc != 2) {
161                 fprintf(stderr, "Usage: smbcontrol <dest> debug "
162                         "<debug-string>\n");
163                 return False;
164         }
165
166         return send_message(msg_ctx, pid, MSG_DEBUG, argv[1],
167                             strlen(argv[1]) + 1);
168 }
169
170
171 static bool do_idmap(struct messaging_context *msg_ctx,
172                      const struct server_id pid,
173                      const int argc, const char **argv)
174 {
175         static const char* usage = "Usage: "
176                 "smbcontrol <dest> idmap <cmd> [arg]\n"
177                 "\tcmd:\tflush [gid|uid]\n"
178                 "\t\tdelete \"UID <uid>\"|\"GID <gid>\"|<sid>\n"
179                 "\t\tkill \"UID <uid>\"|\"GID <gid>\"|<sid>\n";
180         const char* arg = NULL;
181         int arglen = 0;
182         int msg_type;
183
184         switch (argc) {
185         case 2:
186                 break;
187         case 3:
188                 arg = argv[2];
189                 arglen = strlen(arg) + 1;
190                 break;
191         default:
192                 fprintf(stderr, "%s", usage);
193                 return false;
194         }
195
196         if (strcmp(argv[1], "flush") == 0) {
197                 msg_type = MSG_IDMAP_FLUSH;
198         }
199         else if (strcmp(argv[1], "delete") == 0) {
200                 msg_type = MSG_IDMAP_DELETE;
201         }
202         else if (strcmp(argv[1], "kill") == 0) {
203                 msg_type = MSG_IDMAP_KILL;
204         }
205         else if (strcmp(argv[1], "help") == 0) {
206                 fprintf(stdout, "%s", usage);
207                 return true;
208         }
209         else {
210                 fprintf(stderr, "%s", usage);
211                 return false;
212         }
213
214         return send_message(msg_ctx, pid, msg_type, arg, arglen);
215 }
216
217
218 #if defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE)
219
220 /* Return the name of a process given it's PID. This will only work on Linux,
221  * but that's probably moot since this whole stack tracing implementatino is
222  * Linux-specific anyway.
223  */
224 static const char * procname(pid_t pid, char * buf, size_t bufsz)
225 {
226         char path[64];
227         FILE * fp;
228
229         snprintf(path, sizeof(path), "/proc/%llu/cmdline",
230                 (unsigned long long)pid);
231         if ((fp = fopen(path, "r")) == NULL) {
232                 return NULL;
233         }
234
235         fgets(buf, bufsz, fp);
236
237         fclose(fp);
238         return buf;
239 }
240
241 static void print_stack_trace(pid_t pid, int * count)
242 {
243         void *              pinfo = NULL;
244         unw_addr_space_t    aspace = NULL;
245         unw_cursor_t        cursor;
246         unw_word_t          ip, sp;
247
248         char                nbuf[256];
249         unw_word_t          off;
250
251         int ret;
252
253         if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) {
254                 fprintf(stderr,
255                         "Failed to attach to process %llu: %s\n",
256                         (unsigned long long)pid, strerror(errno));
257                 return;
258         }
259
260         /* Wait until the attach is complete. */
261         waitpid(pid, NULL, 0);
262
263         if (((pinfo = _UPT_create(pid)) == NULL) ||
264             ((aspace = unw_create_addr_space(&_UPT_accessors, 0)) == NULL)) {
265                 /* Probably out of memory. */
266                 fprintf(stderr,
267                         "Unable to initialize stack unwind for process %llu\n",
268                         (unsigned long long)pid);
269                 goto cleanup;
270         }
271
272         if ((ret = unw_init_remote(&cursor, aspace, pinfo))) {
273                 fprintf(stderr,
274                         "Unable to unwind stack for process %llu: %s\n",
275                         (unsigned long long)pid, unw_strerror(ret));
276                 goto cleanup;
277         }
278
279         if (*count > 0) {
280                 printf("\n");
281         }
282
283         if (procname(pid, nbuf, sizeof(nbuf))) {
284                 printf("Stack trace for process %llu (%s):\n",
285                         (unsigned long long)pid, nbuf);
286         } else {
287                 printf("Stack trace for process %llu:\n",
288                         (unsigned long long)pid);
289         }
290
291         while (unw_step(&cursor) > 0) {
292                 ip = sp = off = 0;
293                 unw_get_reg(&cursor, UNW_REG_IP, &ip);
294                 unw_get_reg(&cursor, UNW_REG_SP, &sp);
295
296                 ret = unw_get_proc_name(&cursor, nbuf, sizeof(nbuf), &off);
297                 if (ret != 0 && ret != -UNW_ENOMEM) {
298                         snprintf(nbuf, sizeof(nbuf), "<unknown symbol>");
299                 }
300                 printf("    %s + %#llx [ip=%#llx] [sp=%#llx]\n",
301                         nbuf, (long long)off, (long long)ip,
302                         (long long)sp);
303         }
304
305         (*count)++;
306
307 cleanup:
308         if (aspace) {
309                 unw_destroy_addr_space(aspace);
310         }
311
312         if (pinfo) {
313                 _UPT_destroy(pinfo);
314         }
315
316         ptrace(PTRACE_DETACH, pid, NULL, NULL);
317 }
318
319 static int stack_trace_connection(const struct connections_key *key,
320                                   const struct connections_data *crec,
321                                   void *priv)
322 {
323         print_stack_trace(procid_to_pid(&crec->pid), (int *)priv);
324
325         return 0;
326 }
327
328 static bool do_daemon_stack_trace(struct messaging_context *msg_ctx,
329                                   const struct server_id pid,
330                        const int argc, const char **argv)
331 {
332         pid_t   dest;
333         int     count = 0;
334
335         if (argc != 1) {
336                 fprintf(stderr, "Usage: smbcontrol <dest> stacktrace\n");
337                 return False;
338         }
339
340         dest = procid_to_pid(&pid);
341
342         if (dest != 0) {
343                 /* It would be nice to be able to make sure that this PID is
344                  * the PID of a smbd/winbind/nmbd process, not some random PID
345                  * the user liked the look of. It doesn't seem like it's worth
346                  * the effort at the moment, however.
347                  */
348                 print_stack_trace(dest, &count);
349         } else {
350                 connections_forall_read(stack_trace_connection, &count);
351         }
352
353         return True;
354 }
355
356 #else /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
357
358 static bool do_daemon_stack_trace(struct messaging_context *msg_ctx,
359                                   const struct server_id pid,
360                        const int argc, const char **argv)
361 {
362         fprintf(stderr,
363                 "Daemon stack tracing is not supported on this platform\n");
364         return False;
365 }
366
367 #endif /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
368
369 /* Inject a fault (fatal signal) into a running smbd */
370
371 static bool do_inject_fault(struct messaging_context *msg_ctx,
372                             const struct server_id pid,
373                        const int argc, const char **argv)
374 {
375         if (argc != 2) {
376                 fprintf(stderr, "Usage: smbcontrol <dest> inject "
377                         "<bus|hup|term|internal|segv>\n");
378                 return False;
379         }
380
381 #ifndef DEVELOPER
382         fprintf(stderr, "Fault injection is only available in "
383                 "developer builds\n");
384         return False;
385 #else /* DEVELOPER */
386         {
387                 int sig = 0;
388
389                 if (strcmp(argv[1], "bus") == 0) {
390                         sig = SIGBUS;
391                 } else if (strcmp(argv[1], "hup") == 0) {
392                         sig = SIGHUP;
393                 } else if (strcmp(argv[1], "term") == 0) {
394                         sig = SIGTERM;
395                 } else if (strcmp(argv[1], "segv") == 0) {
396                         sig = SIGSEGV;
397                 } else if (strcmp(argv[1], "internal") == 0) {
398                         /* Force an internal error, ie. an unclean exit. */
399                         sig = -1;
400                 } else {
401                         fprintf(stderr, "Unknown signal name '%s'\n", argv[1]);
402                         return False;
403                 }
404
405                 return send_message(msg_ctx, pid, MSG_SMB_INJECT_FAULT,
406                                     &sig, sizeof(int));
407         }
408 #endif /* DEVELOPER */
409 }
410
411 /* Force a browser election */
412
413 static bool do_election(struct messaging_context *msg_ctx,
414                         const struct server_id pid,
415                         const int argc, const char **argv)
416 {
417         if (argc != 1) {
418                 fprintf(stderr, "Usage: smbcontrol <dest> force-election\n");
419                 return False;
420         }
421
422         return send_message(msg_ctx, pid, MSG_FORCE_ELECTION, NULL, 0);
423 }
424
425 /* Ping a samba daemon process */
426
427 static void pong_cb(struct messaging_context *msg,
428                     void *private_data, 
429                     uint32_t msg_type, 
430                     struct server_id pid,
431                     DATA_BLOB *data)
432 {
433         char *src_string = procid_str(NULL, &pid);
434         printf("PONG from pid %s\n", src_string);
435         TALLOC_FREE(src_string);
436         num_replies++;
437 }
438
439 static bool do_ping(struct messaging_context *msg_ctx,
440                     const struct server_id pid,
441                     const int argc, const char **argv)
442 {
443         if (argc != 1) {
444                 fprintf(stderr, "Usage: smbcontrol <dest> ping\n");
445                 return False;
446         }
447
448         /* Send a message and register our interest in a reply */
449
450         if (!send_message(msg_ctx, pid, MSG_PING, NULL, 0))
451                 return False;
452
453         messaging_register(msg_ctx, NULL, MSG_PONG, pong_cb);
454
455         wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
456
457         /* No replies were received within the timeout period */
458
459         if (num_replies == 0)
460                 printf("No replies received\n");
461
462         messaging_deregister(msg_ctx, MSG_PONG, NULL);
463
464         return num_replies;
465 }
466
467 /* Set profiling options */
468
469 static bool do_profile(struct messaging_context *msg_ctx,
470                        const struct server_id pid,
471                        const int argc, const char **argv)
472 {
473         int v;
474
475         if (argc != 2) {
476                 fprintf(stderr, "Usage: smbcontrol <dest> profile "
477                         "<off|count|on|flush>\n");
478                 return False;
479         }
480
481         if (strcmp(argv[1], "off") == 0) {
482                 v = 0;
483         } else if (strcmp(argv[1], "count") == 0) {
484                 v = 1;
485         } else if (strcmp(argv[1], "on") == 0) {
486                 v = 2;
487         } else if (strcmp(argv[1], "flush") == 0) {
488                 v = 3;
489         } else {
490                 fprintf(stderr, "Unknown profile command '%s'\n", argv[1]);
491                 return False;
492         }
493
494         return send_message(msg_ctx, pid, MSG_PROFILE, &v, sizeof(int));
495 }
496
497 /* Return the profiling level */
498
499 static void profilelevel_cb(struct messaging_context *msg_ctx,
500                             void *private_data, 
501                             uint32_t msg_type, 
502                             struct server_id pid,
503                             DATA_BLOB *data)
504 {
505         int level;
506         const char *s;
507
508         num_replies++;
509
510         if (data->length != sizeof(int)) {
511                 fprintf(stderr, "invalid message length %ld returned\n", 
512                         (unsigned long)data->length);
513                 return;
514         }
515
516         memcpy(&level, data->data, sizeof(int));
517
518         switch (level) {
519         case 0:
520                 s = "not enabled";
521                 break;
522         case 1:
523                 s = "off";
524                 break;
525         case 3:
526                 s = "count only";
527                 break;
528         case 7:
529                 s = "count and time";
530                 break;
531         default:
532                 s = "BOGUS";
533                 break;
534         }
535
536         printf("Profiling %s on pid %u\n",s,(unsigned int)procid_to_pid(&pid));
537 }
538
539 static void profilelevel_rqst(struct messaging_context *msg_ctx,
540                               void *private_data, 
541                               uint32_t msg_type, 
542                               struct server_id pid,
543                               DATA_BLOB *data)
544 {
545         int v = 0;
546
547         /* Send back a dummy reply */
548
549         send_message(msg_ctx, pid, MSG_PROFILELEVEL, &v, sizeof(int));
550 }
551
552 static bool do_profilelevel(struct messaging_context *msg_ctx,
553                             const struct server_id pid,
554                             const int argc, const char **argv)
555 {
556         if (argc != 1) {
557                 fprintf(stderr, "Usage: smbcontrol <dest> profilelevel\n");
558                 return False;
559         }
560
561         /* Send a message and register our interest in a reply */
562
563         if (!send_message(msg_ctx, pid, MSG_REQ_PROFILELEVEL, NULL, 0))
564                 return False;
565
566         messaging_register(msg_ctx, NULL, MSG_PROFILELEVEL, profilelevel_cb);
567         messaging_register(msg_ctx, NULL, MSG_REQ_PROFILELEVEL,
568                            profilelevel_rqst);
569
570         wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
571
572         /* No replies were received within the timeout period */
573
574         if (num_replies == 0)
575                 printf("No replies received\n");
576
577         messaging_deregister(msg_ctx, MSG_PROFILE, NULL);
578
579         return num_replies;
580 }
581
582 /* Display debug level settings */
583
584 static bool do_debuglevel(struct messaging_context *msg_ctx,
585                           const struct server_id pid,
586                           const int argc, const char **argv)
587 {
588         if (argc != 1) {
589                 fprintf(stderr, "Usage: smbcontrol <dest> debuglevel\n");
590                 return False;
591         }
592
593         /* Send a message and register our interest in a reply */
594
595         if (!send_message(msg_ctx, pid, MSG_REQ_DEBUGLEVEL, NULL, 0))
596                 return False;
597
598         messaging_register(msg_ctx, NULL, MSG_DEBUGLEVEL, print_pid_string_cb);
599
600         wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
601
602         /* No replies were received within the timeout period */
603
604         if (num_replies == 0)
605                 printf("No replies received\n");
606
607         messaging_deregister(msg_ctx, MSG_DEBUGLEVEL, NULL);
608
609         return num_replies;
610 }
611
612 /* Send a print notify message */
613
614 static bool do_printnotify(struct messaging_context *msg_ctx,
615                            const struct server_id pid,
616                            const int argc, const char **argv)
617 {
618         const char *cmd;
619
620         /* Check for subcommand */
621
622         if (argc == 1) {
623                 fprintf(stderr, "Must specify subcommand:\n");
624                 fprintf(stderr, "\tqueuepause <printername>\n");
625                 fprintf(stderr, "\tqueueresume <printername>\n");
626                 fprintf(stderr, "\tjobpause <printername> <unix jobid>\n");
627                 fprintf(stderr, "\tjobresume <printername> <unix jobid>\n");
628                 fprintf(stderr, "\tjobdelete <printername> <unix jobid>\n");
629                 fprintf(stderr, "\tprinter <printername> <comment|port|"
630                         "driver> <value>\n");
631
632                 return False;
633         }
634
635         cmd = argv[1];
636
637         if (strcmp(cmd, "queuepause") == 0) {
638
639                 if (argc != 3) {
640                         fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
641                                 " queuepause <printername>\n");
642                         return False;
643                 }
644
645                 notify_printer_status_byname(messaging_event_context(msg_ctx),
646                                              msg_ctx, argv[2],
647                                              PRINTER_STATUS_PAUSED);
648
649                 goto send;
650
651         } else if (strcmp(cmd, "queueresume") == 0) {
652
653                 if (argc != 3) {
654                         fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
655                                 " queuereume <printername>\n");
656                         return False;
657                 }
658
659                 notify_printer_status_byname(messaging_event_context(msg_ctx),
660                                              msg_ctx, argv[2],
661                                              PRINTER_STATUS_OK);
662
663                 goto send;
664
665         } else if (strcmp(cmd, "jobpause") == 0) {
666                 int jobid;
667
668                 if (argc != 4) {
669                         fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
670                                 " jobpause <printername> <unix-jobid>\n");
671                         return False;
672                 }
673
674                 jobid = atoi(argv[3]);
675
676                 notify_job_status_byname(
677                         messaging_event_context(msg_ctx), msg_ctx,
678                         argv[2], jobid, JOB_STATUS_PAUSED,
679                         SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
680
681                 goto send;
682
683         } else if (strcmp(cmd, "jobresume") == 0) {
684                 int jobid;
685
686                 if (argc != 4) {
687                         fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
688                                 " jobpause <printername> <unix-jobid>\n");
689                         return False;
690                 }
691
692                 jobid = atoi(argv[3]);
693
694                 notify_job_status_byname(
695                         messaging_event_context(msg_ctx), msg_ctx,
696                         argv[2], jobid, JOB_STATUS_QUEUED, 
697                         SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
698
699                 goto send;
700
701         } else if (strcmp(cmd, "jobdelete") == 0) {
702                 int jobid;
703
704                 if (argc != 4) {
705                         fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
706                                 " jobpause <printername> <unix-jobid>\n");
707                         return False;
708                 }
709
710                 jobid = atoi(argv[3]);
711
712                 notify_job_status_byname(
713                         messaging_event_context(msg_ctx), msg_ctx,
714                         argv[2], jobid, JOB_STATUS_DELETING,
715                         SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
716
717                 notify_job_status_byname(
718                         messaging_event_context(msg_ctx), msg_ctx,
719                         argv[2], jobid, JOB_STATUS_DELETING|
720                         JOB_STATUS_DELETED,
721                         SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
722
723                 goto send;
724
725         } else if (strcmp(cmd, "printer") == 0) {
726                 uint32 attribute;
727
728                 if (argc != 5) {
729                         fprintf(stderr, "Usage: smbcontrol <dest> printnotify "
730                                 "printer <printername> <comment|port|driver> "
731                                 "<value>\n");
732                         return False;
733                 }
734
735                 if (strcmp(argv[3], "comment") == 0) {
736                         attribute = PRINTER_NOTIFY_FIELD_COMMENT;
737                 } else if (strcmp(argv[3], "port") == 0) {
738                         attribute = PRINTER_NOTIFY_FIELD_PORT_NAME;
739                 } else if (strcmp(argv[3], "driver") == 0) {
740                         attribute = PRINTER_NOTIFY_FIELD_DRIVER_NAME;
741                 } else {
742                         fprintf(stderr, "Invalid printer command '%s'\n",
743                                 argv[3]);
744                         return False;
745                 }
746
747                 notify_printer_byname(messaging_event_context(msg_ctx),
748                                       msg_ctx, argv[2], attribute,
749                                       CONST_DISCARD(char *, argv[4]));
750
751                 goto send;
752         }
753
754         fprintf(stderr, "Invalid subcommand '%s'\n", cmd);
755         return False;
756
757 send:
758         print_notify_send_messages(msg_ctx, 0);
759         return True;
760 }
761
762 /* Close a share */
763
764 static bool do_closeshare(struct messaging_context *msg_ctx,
765                           const struct server_id pid,
766                           const int argc, const char **argv)
767 {
768         if (argc != 2) {
769                 fprintf(stderr, "Usage: smbcontrol <dest> close-share "
770                         "<sharename>\n");
771                 return False;
772         }
773
774         return send_message(msg_ctx, pid, MSG_SMB_FORCE_TDIS, argv[1],
775                             strlen(argv[1]) + 1);
776 }
777
778 /* Tell winbindd an IP got dropped */
779
780 static bool do_ip_dropped(struct messaging_context *msg_ctx,
781                           const struct server_id pid,
782                           const int argc, const char **argv)
783 {
784         if (argc != 2) {
785                 fprintf(stderr, "Usage: smbcontrol <dest> ip-dropped "
786                         "<ip-address>\n");
787                 return False;
788         }
789
790         return send_message(msg_ctx, pid, MSG_WINBIND_IP_DROPPED, argv[1],
791                             strlen(argv[1]) + 1);
792 }
793
794 /* force a blocking lock retry */
795
796 static bool do_lockretry(struct messaging_context *msg_ctx,
797                          const struct server_id pid,
798                          const int argc, const char **argv)
799 {
800         if (argc != 1) {
801                 fprintf(stderr, "Usage: smbcontrol <dest> lockretry\n");
802                 return False;
803         }
804
805         return send_message(msg_ctx, pid, MSG_SMB_UNLOCK, NULL, 0);
806 }
807
808 /* force a validation of all brl entries, including re-sends. */
809
810 static bool do_brl_revalidate(struct messaging_context *msg_ctx,
811                               const struct server_id pid,
812                               const int argc, const char **argv)
813 {
814         if (argc != 1) {
815                 fprintf(stderr, "Usage: smbcontrol <dest> brl-revalidate\n");
816                 return False;
817         }
818
819         return send_message(msg_ctx, pid, MSG_SMB_BRL_VALIDATE, NULL, 0);
820 }
821
822 /* Force a SAM synchronisation */
823
824 static bool do_samsync(struct messaging_context *msg_ctx,
825                        const struct server_id pid,
826                        const int argc, const char **argv)
827 {
828         if (argc != 1) {
829                 fprintf(stderr, "Usage: smbcontrol <dest> samsync\n");
830                 return False;
831         }
832
833         return send_message(msg_ctx, pid, MSG_SMB_SAM_SYNC, NULL, 0);
834 }
835
836 /* Force a SAM replication */
837
838 static bool do_samrepl(struct messaging_context *msg_ctx,
839                        const struct server_id pid,
840                        const int argc, const char **argv)
841 {
842         if (argc != 1) {
843                 fprintf(stderr, "Usage: smbcontrol <dest> samrepl\n");
844                 return False;
845         }
846
847         return send_message(msg_ctx, pid, MSG_SMB_SAM_REPL, NULL, 0);
848 }
849
850 /* Display talloc pool usage */
851
852 static bool do_poolusage(struct messaging_context *msg_ctx,
853                          const struct server_id pid,
854                          const int argc, const char **argv)
855 {
856         if (argc != 1) {
857                 fprintf(stderr, "Usage: smbcontrol <dest> pool-usage\n");
858                 return False;
859         }
860
861         messaging_register(msg_ctx, NULL, MSG_POOL_USAGE, print_string_cb);
862
863         /* Send a message and register our interest in a reply */
864
865         if (!send_message(msg_ctx, pid, MSG_REQ_POOL_USAGE, NULL, 0))
866                 return False;
867
868         wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
869
870         /* No replies were received within the timeout period */
871
872         if (num_replies == 0)
873                 printf("No replies received\n");
874
875         messaging_deregister(msg_ctx, MSG_POOL_USAGE, NULL);
876
877         return num_replies;
878 }
879
880 /* Perform a dmalloc mark */
881
882 static bool do_dmalloc_mark(struct messaging_context *msg_ctx,
883                             const struct server_id pid,
884                             const int argc, const char **argv)
885 {
886         if (argc != 1) {
887                 fprintf(stderr, "Usage: smbcontrol <dest> dmalloc-mark\n");
888                 return False;
889         }
890
891         return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_MARK, NULL, 0);
892 }
893
894 /* Perform a dmalloc changed */
895
896 static bool do_dmalloc_changed(struct messaging_context *msg_ctx,
897                                const struct server_id pid,
898                                const int argc, const char **argv)
899 {
900         if (argc != 1) {
901                 fprintf(stderr, "Usage: smbcontrol <dest> "
902                         "dmalloc-log-changed\n");
903                 return False;
904         }
905
906         return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_LOG_CHANGED,
907                             NULL, 0);
908 }
909
910 /* Shutdown a server process */
911
912 static bool do_shutdown(struct messaging_context *msg_ctx,
913                         const struct server_id pid,
914                         const int argc, const char **argv)
915 {
916         if (argc != 1) {
917                 fprintf(stderr, "Usage: smbcontrol <dest> shutdown\n");
918                 return False;
919         }
920
921         return send_message(msg_ctx, pid, MSG_SHUTDOWN, NULL, 0);
922 }
923
924 /* Notify a driver upgrade */
925
926 static bool do_drvupgrade(struct messaging_context *msg_ctx,
927                           const struct server_id pid,
928                           const int argc, const char **argv)
929 {
930         if (argc != 2) {
931                 fprintf(stderr, "Usage: smbcontrol <dest> drvupgrade "
932                         "<driver-name>\n");
933                 return False;
934         }
935
936         return send_message(msg_ctx, pid, MSG_DEBUG, argv[1],
937                             strlen(argv[1]) + 1);
938 }
939
940 static bool do_winbind_online(struct messaging_context *msg_ctx,
941                               const struct server_id pid,
942                              const int argc, const char **argv)
943 {
944         TDB_CONTEXT *tdb;
945
946         if (argc != 1) {
947                 fprintf(stderr, "Usage: smbcontrol winbindd online\n");
948                 return False;
949         }
950
951         /* Remove the entry in the winbindd_cache tdb to tell a later
952            starting winbindd that we're online. */
953
954         tdb = tdb_open_log(cache_path("winbindd_cache.tdb"), 0, TDB_DEFAULT, O_RDWR, 0600);
955         if (!tdb) {
956                 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
957                         cache_path("winbindd_cache.tdb"));
958                 return False;
959         }
960
961         tdb_delete_bystring(tdb, "WINBINDD_OFFLINE");
962         tdb_close(tdb);
963
964         return send_message(msg_ctx, pid, MSG_WINBIND_ONLINE, NULL, 0);
965 }
966
967 static bool do_winbind_offline(struct messaging_context *msg_ctx,
968                                const struct server_id pid,
969                              const int argc, const char **argv)
970 {
971         TDB_CONTEXT *tdb;
972         bool ret = False;
973         int retry = 0;
974
975         if (argc != 1) {
976                 fprintf(stderr, "Usage: smbcontrol winbindd offline\n");
977                 return False;
978         }
979
980         /* Create an entry in the winbindd_cache tdb to tell a later
981            starting winbindd that we're offline. We may actually create
982            it here... */
983
984         tdb = tdb_open_log(cache_path("winbindd_cache.tdb"),
985                                 WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
986                                 TDB_DEFAULT|TDB_INCOMPATIBLE_HASH /* TDB_CLEAR_IF_FIRST */,
987                                 O_RDWR|O_CREAT, 0600);
988
989         if (!tdb) {
990                 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
991                         cache_path("winbindd_cache.tdb"));
992                 return False;
993         }
994
995         /* There's a potential race condition that if a child
996            winbindd detects a domain is online at the same time
997            we're trying to tell it to go offline that it might 
998            delete the record we add between us adding it and
999            sending the message. Minimize this by retrying up to
1000            5 times. */
1001
1002         for (retry = 0; retry < 5; retry++) {
1003                 TDB_DATA d;
1004                 uint8 buf[4];
1005
1006                 ZERO_STRUCT(d);
1007
1008                 SIVAL(buf, 0, time(NULL));
1009                 d.dptr = buf;
1010                 d.dsize = 4;
1011
1012                 tdb_store_bystring(tdb, "WINBINDD_OFFLINE", d, TDB_INSERT);
1013
1014                 ret = send_message(msg_ctx, pid, MSG_WINBIND_OFFLINE,
1015                                    NULL, 0);
1016
1017                 /* Check that the entry "WINBINDD_OFFLINE" still exists. */
1018                 d = tdb_fetch_bystring( tdb, "WINBINDD_OFFLINE" );
1019
1020                 if (!d.dptr || d.dsize != 4) {
1021                         SAFE_FREE(d.dptr);
1022                         DEBUG(10,("do_winbind_offline: offline state not set - retrying.\n"));
1023                 } else {
1024                         SAFE_FREE(d.dptr);
1025                         break;
1026                 }
1027         }
1028
1029         tdb_close(tdb);
1030         return ret;
1031 }
1032
1033 static bool do_winbind_onlinestatus(struct messaging_context *msg_ctx,
1034                                     const struct server_id pid,
1035                                     const int argc, const char **argv)
1036 {
1037         struct server_id myid;
1038
1039         myid = messaging_server_id(msg_ctx);
1040
1041         if (argc != 1) {
1042                 fprintf(stderr, "Usage: smbcontrol winbindd onlinestatus\n");
1043                 return False;
1044         }
1045
1046         messaging_register(msg_ctx, NULL, MSG_WINBIND_ONLINESTATUS,
1047                            print_pid_string_cb);
1048
1049         if (!send_message(msg_ctx, pid, MSG_WINBIND_ONLINESTATUS, &myid,
1050                           sizeof(myid)))
1051                 return False;
1052
1053         wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
1054
1055         /* No replies were received within the timeout period */
1056
1057         if (num_replies == 0)
1058                 printf("No replies received\n");
1059
1060         messaging_deregister(msg_ctx, MSG_WINBIND_ONLINESTATUS, NULL);
1061
1062         return num_replies;
1063 }
1064
1065 static bool do_dump_event_list(struct messaging_context *msg_ctx,
1066                                const struct server_id pid,
1067                                const int argc, const char **argv)
1068 {
1069         struct server_id myid;
1070
1071         myid = messaging_server_id(msg_ctx);
1072
1073         if (argc != 1) {
1074                 fprintf(stderr, "Usage: smbcontrol <dest> dump-event-list\n");
1075                 return False;
1076         }
1077
1078         return send_message(msg_ctx, pid, MSG_DUMP_EVENT_LIST, NULL, 0);
1079 }
1080
1081 static bool do_winbind_dump_domain_list(struct messaging_context *msg_ctx,
1082                                         const struct server_id pid,
1083                                         const int argc, const char **argv)
1084 {
1085         const char *domain = NULL;
1086         int domain_len = 0;
1087         struct server_id myid;
1088         uint8_t *buf = NULL;
1089         int buf_len = 0;
1090
1091         myid = messaging_server_id(msg_ctx);
1092
1093         if (argc < 1 || argc > 2) {
1094                 fprintf(stderr, "Usage: smbcontrol <dest> dump-domain-list "
1095                         "<domain>\n");
1096                 return false;
1097         }
1098
1099         if (argc == 2) {
1100                 domain = argv[1];
1101                 domain_len = strlen(argv[1]) + 1;
1102         }
1103
1104         messaging_register(msg_ctx, NULL, MSG_WINBIND_DUMP_DOMAIN_LIST,
1105                            print_pid_string_cb);
1106
1107         buf_len = sizeof(myid)+domain_len;
1108         buf = SMB_MALLOC_ARRAY(uint8_t, buf_len);
1109         if (!buf) {
1110                 return false;
1111         }
1112
1113         memcpy(buf, &myid, sizeof(myid));
1114         memcpy(&buf[sizeof(myid)], domain, domain_len);
1115
1116         if (!send_message(msg_ctx, pid, MSG_WINBIND_DUMP_DOMAIN_LIST,
1117                           buf, buf_len))
1118         {
1119                 SAFE_FREE(buf);
1120                 return false;
1121         }
1122
1123         wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
1124
1125         /* No replies were received within the timeout period */
1126
1127         SAFE_FREE(buf);
1128         if (num_replies == 0) {
1129                 printf("No replies received\n");
1130         }
1131
1132         messaging_deregister(msg_ctx, MSG_WINBIND_DUMP_DOMAIN_LIST, NULL);
1133
1134         return num_replies;
1135 }
1136
1137 static void winbind_validate_cache_cb(struct messaging_context *msg,
1138                                       void *private_data,
1139                                       uint32_t msg_type,
1140                                       struct server_id pid,
1141                                       DATA_BLOB *data)
1142 {
1143         char *src_string = procid_str(NULL, &pid);
1144         printf("Winbindd cache is %svalid. (answer from pid %s)\n",
1145                (*(data->data) == 0 ? "" : "NOT "), src_string);
1146         TALLOC_FREE(src_string);
1147         num_replies++;
1148 }
1149
1150 static bool do_winbind_validate_cache(struct messaging_context *msg_ctx,
1151                                       const struct server_id pid,
1152                                       const int argc, const char **argv)
1153 {
1154         struct server_id myid;
1155
1156         myid = messaging_server_id(msg_ctx);
1157
1158         if (argc != 1) {
1159                 fprintf(stderr, "Usage: smbcontrol winbindd validate-cache\n");
1160                 return False;
1161         }
1162
1163         messaging_register(msg_ctx, NULL, MSG_WINBIND_VALIDATE_CACHE,
1164                            winbind_validate_cache_cb);
1165
1166         if (!send_message(msg_ctx, pid, MSG_WINBIND_VALIDATE_CACHE, &myid,
1167                           sizeof(myid))) {
1168                 return False;
1169         }
1170
1171         wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
1172
1173         if (num_replies == 0) {
1174                 printf("No replies received\n");
1175         }
1176
1177         messaging_deregister(msg_ctx, MSG_WINBIND_VALIDATE_CACHE, NULL);
1178
1179         return num_replies;
1180 }
1181
1182 static bool do_reload_config(struct messaging_context *msg_ctx,
1183                              const struct server_id pid,
1184                              const int argc, const char **argv)
1185 {
1186         if (argc != 1) {
1187                 fprintf(stderr, "Usage: smbcontrol <dest> reload-config\n");
1188                 return False;
1189         }
1190
1191         return send_message(msg_ctx, pid, MSG_SMB_CONF_UPDATED, NULL, 0);
1192 }
1193
1194 static void my_make_nmb_name( struct nmb_name *n, const char *name, int type)
1195 {
1196         fstring unix_name;
1197         memset( (char *)n, '\0', sizeof(struct nmb_name) );
1198         fstrcpy(unix_name, name);
1199         strupper_m(unix_name);
1200         push_ascii(n->name, unix_name, sizeof(n->name), STR_TERMINATE);
1201         n->name_type = (unsigned int)type & 0xFF;
1202         push_ascii(n->scope,  global_scope(), 64, STR_TERMINATE);
1203 }
1204
1205 static bool do_nodestatus(struct messaging_context *msg_ctx,
1206                           const struct server_id pid,
1207                           const int argc, const char **argv)
1208 {
1209         struct packet_struct p;
1210
1211         if (argc != 2) {
1212                 fprintf(stderr, "Usage: smbcontrol nmbd nodestatus <ip>\n");
1213                 return False;
1214         }
1215
1216         ZERO_STRUCT(p);
1217
1218         p.ip = interpret_addr2(argv[1]);
1219         p.port = 137;
1220         p.packet_type = NMB_PACKET;
1221
1222         p.packet.nmb.header.name_trn_id = 10;
1223         p.packet.nmb.header.opcode = 0;
1224         p.packet.nmb.header.response = False;
1225         p.packet.nmb.header.nm_flags.bcast = False;
1226         p.packet.nmb.header.nm_flags.recursion_available = False;
1227         p.packet.nmb.header.nm_flags.recursion_desired = False;
1228         p.packet.nmb.header.nm_flags.trunc = False;
1229         p.packet.nmb.header.nm_flags.authoritative = False;
1230         p.packet.nmb.header.rcode = 0;
1231         p.packet.nmb.header.qdcount = 1;
1232         p.packet.nmb.header.ancount = 0;
1233         p.packet.nmb.header.nscount = 0;
1234         p.packet.nmb.header.arcount = 0;
1235         my_make_nmb_name(&p.packet.nmb.question.question_name, "*", 0x00);
1236         p.packet.nmb.question.question_type = 0x21;
1237         p.packet.nmb.question.question_class = 0x1;
1238
1239         return send_message(msg_ctx, pid, MSG_SEND_PACKET, &p, sizeof(p));
1240 }
1241
1242 /* A list of message type supported */
1243
1244 static const struct {
1245         const char *name;       /* Option name */
1246         bool (*fn)(struct messaging_context *msg_ctx,
1247                    const struct server_id pid,
1248                    const int argc, const char **argv);
1249         const char *help;       /* Short help text */
1250 } msg_types[] = {
1251         { "debug", do_debug, "Set debuglevel"  },
1252         { "idmap", do_idmap, "Manipulate idmap cache" },
1253         { "force-election", do_election,
1254           "Force a browse election" },
1255         { "ping", do_ping, "Elicit a response" },
1256         { "profile", do_profile, "" },
1257         { "inject", do_inject_fault,
1258             "Inject a fatal signal into a running smbd"},
1259         { "stacktrace", do_daemon_stack_trace,
1260             "Display a stack trace of a daemon" },
1261         { "profilelevel", do_profilelevel, "" },
1262         { "debuglevel", do_debuglevel, "Display current debuglevels" },
1263         { "printnotify", do_printnotify, "Send a print notify message" },
1264         { "close-share", do_closeshare, "Forcibly disconnect a share" },
1265         { "ip-dropped", do_ip_dropped, "Tell winbind that an IP got dropped" },
1266         { "lockretry", do_lockretry, "Force a blocking lock retry" },
1267         { "brl-revalidate", do_brl_revalidate, "Revalidate all brl entries" },
1268         { "samsync", do_samsync, "Initiate SAM synchronisation" },
1269         { "samrepl", do_samrepl, "Initiate SAM replication" },
1270         { "pool-usage", do_poolusage, "Display talloc memory usage" },
1271         { "dmalloc-mark", do_dmalloc_mark, "" },
1272         { "dmalloc-log-changed", do_dmalloc_changed, "" },
1273         { "shutdown", do_shutdown, "Shut down daemon" },
1274         { "drvupgrade", do_drvupgrade, "Notify a printer driver has changed" },
1275         { "reload-config", do_reload_config, "Force smbd or winbindd to reload config file"},
1276         { "nodestatus", do_nodestatus, "Ask nmbd to do a node status request"},
1277         { "online", do_winbind_online, "Ask winbind to go into online state"},
1278         { "offline", do_winbind_offline, "Ask winbind to go into offline state"},
1279         { "onlinestatus", do_winbind_onlinestatus, "Request winbind online status"},
1280         { "dump-event-list", do_dump_event_list, "Dump event list"},
1281         { "validate-cache" , do_winbind_validate_cache,
1282           "Validate winbind's credential cache" },
1283         { "dump-domain-list", do_winbind_dump_domain_list, "Dump winbind domain list"},
1284         { "noop", do_noop, "Do nothing" },
1285         { NULL }
1286 };
1287
1288 /* Display usage information */
1289
1290 static void usage(poptContext pc)
1291 {
1292         int i;
1293
1294         poptPrintHelp(pc, stderr, 0);
1295
1296         fprintf(stderr, "\n");
1297         fprintf(stderr, "<destination> is one of \"nmbd\", \"smbd\", \"winbindd\" or a "
1298                 "process ID\n");
1299
1300         fprintf(stderr, "\n");
1301         fprintf(stderr, "<message-type> is one of:\n");
1302
1303         for (i = 0; msg_types[i].name; i++) 
1304             fprintf(stderr, "\t%-30s%s\n", msg_types[i].name, 
1305                     msg_types[i].help);
1306
1307         fprintf(stderr, "\n");
1308
1309         exit(1);
1310 }
1311
1312 /* Return the pid number for a string destination */
1313
1314 static struct server_id parse_dest(struct messaging_context *msg,
1315                                    const char *dest)
1316 {
1317         struct server_id result = {-1};
1318         pid_t pid;
1319
1320         /* Zero is a special return value for broadcast to all processes */
1321
1322         if (strequal(dest, "all")) {
1323                 return interpret_pid(MSG_BROADCAST_PID_STR);
1324         }
1325
1326         /* Try self - useful for testing */
1327
1328         if (strequal(dest, "self")) {
1329                 return messaging_server_id(msg);
1330         }
1331
1332         /* Fix winbind typo. */
1333         if (strequal(dest, "winbind")) {
1334                 dest = "winbindd";
1335         }
1336
1337         /* Check for numeric pid number */
1338         result = interpret_pid(dest);
1339
1340         /* Zero isn't valid if not "all". */
1341         if (result.pid && procid_valid(&result)) {
1342                 return result;
1343         }
1344
1345         /* Look up other destinations in pidfile directory */
1346
1347         if ((pid = pidfile_pid(dest)) != 0) {
1348                 return pid_to_procid(pid);
1349         }
1350
1351         fprintf(stderr,"Can't find pid for destination '%s'\n", dest);
1352
1353         return result;
1354 }
1355
1356 /* Execute smbcontrol command */
1357
1358 static bool do_command(struct messaging_context *msg_ctx,
1359                        int argc, const char **argv)
1360 {
1361         const char *dest = argv[0], *command = argv[1];
1362         struct server_id pid;
1363         int i;
1364
1365         /* Check destination */
1366
1367         pid = parse_dest(msg_ctx, dest);
1368         if (!procid_valid(&pid)) {
1369                 return False;
1370         }
1371
1372         /* Check command */
1373
1374         for (i = 0; msg_types[i].name; i++) {
1375                 if (strequal(command, msg_types[i].name))
1376                         return msg_types[i].fn(msg_ctx, pid,
1377                                                argc - 1, argv + 1);
1378         }
1379
1380         fprintf(stderr, "smbcontrol: unknown command '%s'\n", command);
1381
1382         return False;
1383 }
1384
1385 static void smbcontrol_help(poptContext pc,
1386                     enum poptCallbackReason preason,
1387                     struct poptOption * poption,
1388                     const char * parg,
1389                     void * pdata)
1390 {
1391         if (poption->shortName != '?') {
1392                 poptPrintUsage(pc, stdout, 0);
1393         } else {
1394                 usage(pc);
1395         }
1396
1397         exit(0);
1398 }
1399
1400 struct poptOption help_options[] = {
1401         { NULL, '\0', POPT_ARG_CALLBACK, (void *)&smbcontrol_help, '\0',
1402           NULL, NULL },
1403         { "help", '?', 0, NULL, '?', "Show this help message", NULL },
1404         { "usage", '\0', 0, NULL, 'u', "Display brief usage message", NULL },
1405         { NULL }
1406 } ;
1407
1408 /* Main program */
1409
1410 int main(int argc, const char **argv)
1411 {
1412         poptContext pc;
1413         int opt;
1414         struct tevent_context *evt_ctx;
1415         struct messaging_context *msg_ctx;
1416
1417         static struct poptOption long_options[] = {
1418                 /* POPT_AUTOHELP */
1419                 { NULL, '\0', POPT_ARG_INCLUDE_TABLE, help_options,
1420                                         0, "Help options:", NULL },
1421                 { "timeout", 't', POPT_ARG_INT, &timeout, 't', 
1422                   "Set timeout value in seconds", "TIMEOUT" },
1423
1424                 POPT_COMMON_SAMBA
1425                 POPT_TABLEEND
1426         };
1427         TALLOC_CTX *frame = talloc_stackframe();
1428         int ret = 0;
1429
1430         load_case_tables();
1431
1432         setup_logging(argv[0], DEBUG_STDOUT);
1433
1434         /* Parse command line arguments using popt */
1435
1436         pc = poptGetContext(
1437                 "smbcontrol", argc, (const char **)argv, long_options, 0);
1438
1439         poptSetOtherOptionHelp(pc, "[OPTION...] <destination> <message-type> "
1440                                "<parameters>");
1441
1442         if (argc == 1)
1443                 usage(pc);
1444
1445         while ((opt = poptGetNextOpt(pc)) != -1) {
1446                 switch(opt) {
1447                 case 't':       /* --timeout */
1448                         break;
1449                 default:
1450                         fprintf(stderr, "Invalid option\n");
1451                         poptPrintHelp(pc, stderr, 0);
1452                         break;
1453                 }
1454         }
1455
1456         /* We should now have the remaining command line arguments in
1457            argv.  The argc parameter should have been decremented to the
1458            correct value in the above switch statement. */
1459
1460         argv = (const char **)poptGetArgs(pc);
1461         argc = 0;
1462         if (argv != NULL) {
1463                 while (argv[argc] != NULL) {
1464                         argc++;
1465                 }
1466         }
1467
1468         if (argc <= 1)
1469                 usage(pc);
1470
1471         lp_load(get_dyn_CONFIGFILE(),False,False,False,True);
1472
1473         /* Need to invert sense of return code -- samba
1474          * routines mostly return True==1 for success, but
1475          * shell needs 0. */ 
1476
1477         if (!(evt_ctx = tevent_context_init(NULL)) ||
1478             !(msg_ctx = messaging_init(NULL, procid_self(), evt_ctx))) {
1479                 fprintf(stderr, "could not init messaging context\n");
1480                 TALLOC_FREE(frame);
1481                 exit(1);
1482         }
1483
1484         ret = !do_command(msg_ctx, argc, argv);
1485         TALLOC_FREE(frame);
1486         return ret;
1487 }