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