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