1435cc57d0a23b8cfb893420d20a7ba69454ced8
[bbaumbach/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 #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 #if !defined(DEVELOPER) && !defined(ENABLE_SELFTEST)
384         fprintf(stderr, "Fault injection is only available in "
385                 "developer and self test builds\n");
386         return False;
387 #else /* DEVELOPER || ENABLE_SELFTEST */
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 || ENABLE_SELFTEST */
411 }
412
413 static bool do_sleep(struct tevent_context *ev_ctx,
414                      struct messaging_context *msg_ctx,
415                      const struct server_id pid,
416                      const int argc, const char **argv)
417 {
418 #if defined(DEVELOPER) || defined(ENABLE_SELFTEST)
419         unsigned int seconds;
420         long input;
421         const long MAX_SLEEP = 60 * 60; /* One hour maximum sleep */
422 #endif
423
424         if (argc != 2) {
425                 fprintf(stderr, "Usage: smbcontrol <dest> sleep seconds\n");
426                 return False;
427         }
428
429 #if !defined(DEVELOPER) && !defined(ENABLE_SELFTEST)
430         fprintf(stderr, "Sleep is only available in "
431                 "developer and self test builds\n");
432         return False;
433 #else /* DEVELOPER || ENABLE_SELFTEST */
434
435         input = atol(argv[1]);
436         if (input < 1 || input > MAX_SLEEP) {
437                 fprintf(stderr,
438                         "Invalid duration for sleep '%s'\n"
439                         "It should be at least 1 second and no more than %ld\n",
440                         argv[1],
441                         MAX_SLEEP);
442                 return False;
443         }
444         seconds = input;
445         return send_message(msg_ctx, pid,
446                             MSG_SMB_SLEEP,
447                             &seconds,
448                             sizeof(unsigned int));
449 #endif /* DEVELOPER || ENABLE_SELFTEST */
450 }
451
452 /* Force a browser election */
453
454 static bool do_election(struct tevent_context *ev_ctx,
455                         struct messaging_context *msg_ctx,
456                         const struct server_id pid,
457                         const int argc, const char **argv)
458 {
459         if (argc != 1) {
460                 fprintf(stderr, "Usage: smbcontrol <dest> force-election\n");
461                 return False;
462         }
463
464         return send_message(msg_ctx, pid, MSG_FORCE_ELECTION, NULL, 0);
465 }
466
467 /* Ping a samba daemon process */
468
469 static void pong_cb(struct messaging_context *msg,
470                     void *private_data, 
471                     uint32_t msg_type, 
472                     struct server_id pid,
473                     DATA_BLOB *data)
474 {
475         struct server_id_buf src_string;
476         printf("PONG from pid %s\n", server_id_str_buf(pid, &src_string));
477         num_replies++;
478 }
479
480 static bool do_ping(struct tevent_context *ev_ctx,
481                     struct messaging_context *msg_ctx,
482                     const struct server_id pid,
483                     const int argc, const char **argv)
484 {
485         if (argc != 1) {
486                 fprintf(stderr, "Usage: smbcontrol <dest> ping\n");
487                 return False;
488         }
489
490         /* Send a message and register our interest in a reply */
491
492         if (!send_message(msg_ctx, pid, MSG_PING, NULL, 0))
493                 return False;
494
495         messaging_register(msg_ctx, NULL, MSG_PONG, pong_cb);
496
497         wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
498
499         /* No replies were received within the timeout period */
500
501         if (num_replies == 0)
502                 printf("No replies received\n");
503
504         messaging_deregister(msg_ctx, MSG_PONG, NULL);
505
506         return num_replies;
507 }
508
509 /* Set profiling options */
510
511 static bool do_profile(struct tevent_context *ev_ctx,
512                        struct messaging_context *msg_ctx,
513                        const struct server_id pid,
514                        const int argc, const char **argv)
515 {
516         int v;
517
518         if (argc != 2) {
519                 fprintf(stderr, "Usage: smbcontrol <dest> profile "
520                         "<off|count|on|flush>\n");
521                 return False;
522         }
523
524         if (strcmp(argv[1], "off") == 0) {
525                 v = 0;
526         } else if (strcmp(argv[1], "count") == 0) {
527                 v = 1;
528         } else if (strcmp(argv[1], "on") == 0) {
529                 v = 2;
530         } else if (strcmp(argv[1], "flush") == 0) {
531                 v = 3;
532         } else {
533                 fprintf(stderr, "Unknown profile command '%s'\n", argv[1]);
534                 return False;
535         }
536
537         return send_message(msg_ctx, pid, MSG_PROFILE, &v, sizeof(int));
538 }
539
540 /* Return the profiling level */
541
542 static void profilelevel_cb(struct messaging_context *msg_ctx,
543                             void *private_data, 
544                             uint32_t msg_type, 
545                             struct server_id pid,
546                             DATA_BLOB *data)
547 {
548         int level;
549         const char *s;
550
551         num_replies++;
552
553         if (data->length != sizeof(int)) {
554                 fprintf(stderr, "invalid message length %ld returned\n", 
555                         (unsigned long)data->length);
556                 return;
557         }
558
559         memcpy(&level, data->data, sizeof(int));
560
561         switch (level) {
562         case 0:
563                 s = "not enabled";
564                 break;
565         case 1:
566                 s = "off";
567                 break;
568         case 3:
569                 s = "count only";
570                 break;
571         case 7:
572                 s = "count and time";
573                 break;
574         default:
575                 s = "BOGUS";
576                 break;
577         }
578
579         printf("Profiling %s on pid %u\n",s,(unsigned int)procid_to_pid(&pid));
580 }
581
582 static void profilelevel_rqst(struct messaging_context *msg_ctx,
583                               void *private_data, 
584                               uint32_t msg_type, 
585                               struct server_id pid,
586                               DATA_BLOB *data)
587 {
588         int v = 0;
589
590         /* Send back a dummy reply */
591
592         send_message(msg_ctx, pid, MSG_PROFILELEVEL, &v, sizeof(int));
593 }
594
595 static bool do_profilelevel(struct tevent_context *ev_ctx,
596                             struct messaging_context *msg_ctx,
597                             const struct server_id pid,
598                             const int argc, const char **argv)
599 {
600         if (argc != 1) {
601                 fprintf(stderr, "Usage: smbcontrol <dest> profilelevel\n");
602                 return False;
603         }
604
605         /* Send a message and register our interest in a reply */
606
607         if (!send_message(msg_ctx, pid, MSG_REQ_PROFILELEVEL, NULL, 0))
608                 return False;
609
610         messaging_register(msg_ctx, NULL, MSG_PROFILELEVEL, profilelevel_cb);
611         messaging_register(msg_ctx, NULL, MSG_REQ_PROFILELEVEL,
612                            profilelevel_rqst);
613
614         wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
615
616         /* No replies were received within the timeout period */
617
618         if (num_replies == 0)
619                 printf("No replies received\n");
620
621         messaging_deregister(msg_ctx, MSG_PROFILE, NULL);
622
623         return num_replies;
624 }
625
626 /* Display debug level settings */
627
628 static bool do_debuglevel(struct tevent_context *ev_ctx,
629                           struct messaging_context *msg_ctx,
630                           const struct server_id pid,
631                           const int argc, const char **argv)
632 {
633         if (argc != 1) {
634                 fprintf(stderr, "Usage: smbcontrol <dest> debuglevel\n");
635                 return False;
636         }
637
638         /* Send a message and register our interest in a reply */
639
640         if (!send_message(msg_ctx, pid, MSG_REQ_DEBUGLEVEL, NULL, 0))
641                 return False;
642
643         messaging_register(msg_ctx, NULL, MSG_DEBUGLEVEL, print_pid_string_cb);
644
645         wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
646
647         /* No replies were received within the timeout period */
648
649         if (num_replies == 0)
650                 printf("No replies received\n");
651
652         messaging_deregister(msg_ctx, MSG_DEBUGLEVEL, NULL);
653
654         return num_replies;
655 }
656
657 /* Send a print notify message */
658
659 static bool do_printnotify(struct tevent_context *ev_ctx,
660                            struct messaging_context *msg_ctx,
661                            const struct server_id pid,
662                            const int argc, const char **argv)
663 {
664         const char *cmd;
665
666         /* Check for subcommand */
667
668         if (argc == 1) {
669                 fprintf(stderr, "Must specify subcommand:\n");
670                 fprintf(stderr, "\tqueuepause <printername>\n");
671                 fprintf(stderr, "\tqueueresume <printername>\n");
672                 fprintf(stderr, "\tjobpause <printername> <unix jobid>\n");
673                 fprintf(stderr, "\tjobresume <printername> <unix jobid>\n");
674                 fprintf(stderr, "\tjobdelete <printername> <unix jobid>\n");
675                 fprintf(stderr, "\tprinter <printername> <comment|port|"
676                         "driver> <value>\n");
677
678                 return False;
679         }
680
681         cmd = argv[1];
682
683         if (strcmp(cmd, "queuepause") == 0) {
684
685                 if (argc != 3) {
686                         fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
687                                 " queuepause <printername>\n");
688                         return False;
689                 }
690
691                 notify_printer_status_byname(ev_ctx, msg_ctx, argv[2],
692                                              PRINTER_STATUS_PAUSED);
693
694                 goto send;
695
696         } else if (strcmp(cmd, "queueresume") == 0) {
697
698                 if (argc != 3) {
699                         fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
700                                 " queuereume <printername>\n");
701                         return False;
702                 }
703
704                 notify_printer_status_byname(ev_ctx, msg_ctx, argv[2],
705                                              PRINTER_STATUS_OK);
706
707                 goto send;
708
709         } else if (strcmp(cmd, "jobpause") == 0) {
710                 int jobid;
711
712                 if (argc != 4) {
713                         fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
714                                 " jobpause <printername> <unix-jobid>\n");
715                         return False;
716                 }
717
718                 jobid = atoi(argv[3]);
719
720                 notify_job_status_byname(
721                         ev_ctx, msg_ctx,
722                         argv[2], jobid, JOB_STATUS_PAUSED,
723                         SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
724
725                 goto send;
726
727         } else if (strcmp(cmd, "jobresume") == 0) {
728                 int jobid;
729
730                 if (argc != 4) {
731                         fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
732                                 " jobpause <printername> <unix-jobid>\n");
733                         return False;
734                 }
735
736                 jobid = atoi(argv[3]);
737
738                 notify_job_status_byname(
739                         ev_ctx, msg_ctx,
740                         argv[2], jobid, JOB_STATUS_QUEUED, 
741                         SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
742
743                 goto send;
744
745         } else if (strcmp(cmd, "jobdelete") == 0) {
746                 int jobid;
747
748                 if (argc != 4) {
749                         fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
750                                 " jobpause <printername> <unix-jobid>\n");
751                         return False;
752                 }
753
754                 jobid = atoi(argv[3]);
755
756                 notify_job_status_byname(
757                         ev_ctx, msg_ctx,
758                         argv[2], jobid, JOB_STATUS_DELETING,
759                         SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
760
761                 notify_job_status_byname(
762                         ev_ctx, msg_ctx,
763                         argv[2], jobid, JOB_STATUS_DELETING|
764                         JOB_STATUS_DELETED,
765                         SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
766
767                 goto send;
768
769         } else if (strcmp(cmd, "printer") == 0) {
770                 uint32_t attribute;
771
772                 if (argc != 5) {
773                         fprintf(stderr, "Usage: smbcontrol <dest> printnotify "
774                                 "printer <printername> <comment|port|driver> "
775                                 "<value>\n");
776                         return False;
777                 }
778
779                 if (strcmp(argv[3], "comment") == 0) {
780                         attribute = PRINTER_NOTIFY_FIELD_COMMENT;
781                 } else if (strcmp(argv[3], "port") == 0) {
782                         attribute = PRINTER_NOTIFY_FIELD_PORT_NAME;
783                 } else if (strcmp(argv[3], "driver") == 0) {
784                         attribute = PRINTER_NOTIFY_FIELD_DRIVER_NAME;
785                 } else {
786                         fprintf(stderr, "Invalid printer command '%s'\n",
787                                 argv[3]);
788                         return False;
789                 }
790
791                 notify_printer_byname(ev_ctx, msg_ctx, argv[2], attribute,
792                                       discard_const_p(char, argv[4]));
793
794                 goto send;
795         }
796
797         fprintf(stderr, "Invalid subcommand '%s'\n", cmd);
798         return False;
799
800 send:
801         print_notify_send_messages(msg_ctx, 0);
802         return True;
803 }
804
805 /* Close a share */
806
807 static bool do_closeshare(struct tevent_context *ev_ctx,
808                           struct messaging_context *msg_ctx,
809                           const struct server_id pid,
810                           const int argc, const char **argv)
811 {
812         if (argc != 2) {
813                 fprintf(stderr, "Usage: smbcontrol <dest> close-share "
814                         "<sharename>\n");
815                 return False;
816         }
817
818         return send_message(msg_ctx, pid, MSG_SMB_FORCE_TDIS, argv[1],
819                             strlen(argv[1]) + 1);
820 }
821
822 /* Kill a client by IP address */
823 static bool do_kill_client_by_ip(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 != 2) {
829                 fprintf(stderr, "Usage: smbcontrol <dest> kill-client-ip "
830                         "<IP address>\n");
831                 return false;
832         }
833
834         if (!is_ipaddress_v4(argv[1]) && !is_ipaddress_v6(argv[1])) {
835                 fprintf(stderr, "%s is not a valid IP address!\n", argv[1]);
836                 return false;
837         }
838
839         return send_message(msg_ctx, pid, MSG_SMB_KILL_CLIENT_IP,
840                             argv[1], strlen(argv[1]) + 1);
841 }
842
843 /* Tell winbindd an IP got dropped */
844
845 static bool do_ip_dropped(struct tevent_context *ev_ctx,
846                           struct messaging_context *msg_ctx,
847                           const struct server_id pid,
848                           const int argc, const char **argv)
849 {
850         if (argc != 2) {
851                 fprintf(stderr, "Usage: smbcontrol <dest> ip-dropped "
852                         "<ip-address>\n");
853                 return False;
854         }
855
856         return send_message(msg_ctx, pid, MSG_WINBIND_IP_DROPPED, argv[1],
857                             strlen(argv[1]) + 1);
858 }
859
860 /* Display talloc pool usage */
861
862 static bool do_poolusage(struct tevent_context *ev_ctx,
863                          struct messaging_context *msg_ctx,
864                          const struct server_id pid,
865                          const int argc, const char **argv)
866 {
867         if (argc != 1) {
868                 fprintf(stderr, "Usage: smbcontrol <dest> pool-usage\n");
869                 return False;
870         }
871
872         messaging_register(msg_ctx, NULL, MSG_POOL_USAGE, print_string_cb);
873
874         /* Send a message and register our interest in a reply */
875
876         if (!send_message(msg_ctx, pid, MSG_REQ_POOL_USAGE, NULL, 0))
877                 return False;
878
879         wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
880
881         /* No replies were received within the timeout period */
882
883         if (num_replies == 0)
884                 printf("No replies received\n");
885
886         messaging_deregister(msg_ctx, MSG_POOL_USAGE, NULL);
887
888         return num_replies;
889 }
890
891 /* Fetch and print the ringbuf log */
892
893 static void print_ringbuf_log_cb(struct messaging_context *msg,
894                                  void *private_data,
895                                  uint32_t msg_type,
896                                  struct server_id pid,
897                                  DATA_BLOB *data)
898 {
899         printf("%s", (const char *)data->data);
900         num_replies++;
901 }
902
903 static bool do_ringbuflog(struct tevent_context *ev_ctx,
904                           struct messaging_context *msg_ctx,
905                           const struct server_id pid,
906                           const int argc, const char **argv)
907 {
908         if (argc != 1) {
909                 fprintf(stderr, "Usage: smbcontrol <dest> ringbuf-log\n");
910                 return false;
911         }
912
913         messaging_register(msg_ctx, NULL, MSG_RINGBUF_LOG,
914                            print_ringbuf_log_cb);
915
916         /* Send a message and register our interest in a reply */
917
918         if (!send_message(msg_ctx, pid, MSG_REQ_RINGBUF_LOG, NULL, 0)) {
919                 return false;
920         }
921
922         wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
923
924         /* No replies were received within the timeout period */
925
926         if (num_replies == 0) {
927                 printf("No replies received\n");
928         }
929
930         messaging_deregister(msg_ctx, MSG_RINGBUF_LOG, NULL);
931
932         return num_replies != 0;
933 }
934
935 /* Perform a dmalloc mark */
936
937 static bool do_dmalloc_mark(struct tevent_context *ev_ctx,
938                             struct messaging_context *msg_ctx,
939                             const struct server_id pid,
940                             const int argc, const char **argv)
941 {
942         if (argc != 1) {
943                 fprintf(stderr, "Usage: smbcontrol <dest> dmalloc-mark\n");
944                 return False;
945         }
946
947         return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_MARK, NULL, 0);
948 }
949
950 /* Perform a dmalloc changed */
951
952 static bool do_dmalloc_changed(struct tevent_context *ev_ctx,
953                                struct messaging_context *msg_ctx,
954                                const struct server_id pid,
955                                const int argc, const char **argv)
956 {
957         if (argc != 1) {
958                 fprintf(stderr, "Usage: smbcontrol <dest> "
959                         "dmalloc-log-changed\n");
960                 return False;
961         }
962
963         return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_LOG_CHANGED,
964                             NULL, 0);
965 }
966
967 static void print_uint32_cb(struct messaging_context *msg, void *private_data,
968                             uint32_t msg_type, struct server_id pid,
969                             DATA_BLOB *data)
970 {
971         uint32_t num_children;
972
973         if (data->length != sizeof(uint32_t)) {
974                 printf("Invalid response: %d bytes long\n",
975                        (int)data->length);
976                 goto done;
977         }
978         num_children = IVAL(data->data, 0);
979         printf("%u children\n", (unsigned)num_children);
980 done:
981         num_replies++;
982 }
983
984 static bool do_num_children(struct tevent_context *ev_ctx,
985                             struct messaging_context *msg_ctx,
986                             const struct server_id pid,
987                             const int argc, const char **argv)
988 {
989         if (argc != 1) {
990                 fprintf(stderr, "Usage: smbcontrol <dest> num-children\n");
991                 return False;
992         }
993
994         messaging_register(msg_ctx, NULL, MSG_SMB_NUM_CHILDREN,
995                            print_uint32_cb);
996
997         /* Send a message and register our interest in a reply */
998
999         if (!send_message(msg_ctx, pid, MSG_SMB_TELL_NUM_CHILDREN, NULL, 0))
1000                 return false;
1001
1002         wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
1003
1004         /* No replies were received within the timeout period */
1005
1006         if (num_replies == 0)
1007                 printf("No replies received\n");
1008
1009         messaging_deregister(msg_ctx, MSG_SMB_NUM_CHILDREN, NULL);
1010
1011         return num_replies;
1012 }
1013
1014 static bool do_msg_cleanup(struct tevent_context *ev_ctx,
1015                            struct messaging_context *msg_ctx,
1016                            const struct server_id pid,
1017                            const int argc, const char **argv)
1018 {
1019         int ret;
1020
1021         ret = messaging_cleanup(msg_ctx, pid.pid);
1022
1023         printf("cleanup(%u) returned %s\n", (unsigned)pid.pid,
1024                ret ? strerror(ret) : "ok");
1025
1026         return (ret == 0);
1027 }
1028
1029 /* Shutdown a server process */
1030
1031 static bool do_shutdown(struct tevent_context *ev_ctx,
1032                         struct messaging_context *msg_ctx,
1033                         const struct server_id pid,
1034                         const int argc, const char **argv)
1035 {
1036         if (argc != 1) {
1037                 fprintf(stderr, "Usage: smbcontrol <dest> shutdown\n");
1038                 return False;
1039         }
1040
1041         return send_message(msg_ctx, pid, MSG_SHUTDOWN, NULL, 0);
1042 }
1043
1044 /* Notify a driver upgrade */
1045
1046 static bool do_drvupgrade(struct tevent_context *ev_ctx,
1047                           struct messaging_context *msg_ctx,
1048                           const struct server_id pid,
1049                           const int argc, const char **argv)
1050 {
1051         if (argc != 2) {
1052                 fprintf(stderr, "Usage: smbcontrol <dest> drvupgrade "
1053                         "<driver-name>\n");
1054                 return False;
1055         }
1056
1057         return send_message(msg_ctx, pid, MSG_PRINTER_DRVUPGRADE, argv[1],
1058                             strlen(argv[1]) + 1);
1059 }
1060
1061 static bool do_winbind_online(struct tevent_context *ev_ctx,
1062                               struct messaging_context *msg_ctx,
1063                               const struct server_id pid,
1064                               const int argc, const char **argv)
1065 {
1066         TDB_CONTEXT *tdb;
1067         char *db_path;
1068
1069         if (argc != 1) {
1070                 fprintf(stderr, "Usage: smbcontrol winbindd online\n");
1071                 return False;
1072         }
1073
1074         db_path = state_path(talloc_tos(), "winbindd_cache.tdb");
1075         if (db_path == NULL) {
1076                 return false;
1077         }
1078
1079         /* Remove the entry in the winbindd_cache tdb to tell a later
1080            starting winbindd that we're online. */
1081
1082         tdb = tdb_open_log(db_path, 0, TDB_DEFAULT, O_RDWR, 0600);
1083         if (!tdb) {
1084                 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
1085                         db_path);
1086                 TALLOC_FREE(db_path);
1087                 return False;
1088         }
1089
1090         TALLOC_FREE(db_path);
1091         tdb_delete_bystring(tdb, "WINBINDD_OFFLINE");
1092         tdb_close(tdb);
1093
1094         return send_message(msg_ctx, pid, MSG_WINBIND_ONLINE, NULL, 0);
1095 }
1096
1097 static bool do_winbind_offline(struct tevent_context *ev_ctx,
1098                                struct messaging_context *msg_ctx,
1099                                const struct server_id pid,
1100                                const int argc, const char **argv)
1101 {
1102         TDB_CONTEXT *tdb;
1103         bool ret = False;
1104         int retry = 0;
1105         char *db_path;
1106
1107         if (argc != 1) {
1108                 fprintf(stderr, "Usage: smbcontrol winbindd offline\n");
1109                 return False;
1110         }
1111
1112         db_path = state_path(talloc_tos(), "winbindd_cache.tdb");
1113         if (db_path == NULL) {
1114                 return false;
1115         }
1116
1117         /* Create an entry in the winbindd_cache tdb to tell a later
1118            starting winbindd that we're offline. We may actually create
1119            it here... */
1120
1121         tdb = tdb_open_log(db_path,
1122                                 WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
1123                                 TDB_DEFAULT|TDB_INCOMPATIBLE_HASH /* TDB_CLEAR_IF_FIRST */,
1124                                 O_RDWR|O_CREAT, 0600);
1125
1126         if (!tdb) {
1127                 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
1128                         db_path);
1129                 TALLOC_FREE(db_path);
1130                 return False;
1131         }
1132         TALLOC_FREE(db_path);
1133
1134         /* There's a potential race condition that if a child
1135            winbindd detects a domain is online at the same time
1136            we're trying to tell it to go offline that it might 
1137            delete the record we add between us adding it and
1138            sending the message. Minimize this by retrying up to
1139            5 times. */
1140
1141         for (retry = 0; retry < 5; retry++) {
1142                 uint8_t buf[4];
1143                 TDB_DATA d = { .dptr = buf, .dsize = sizeof(buf) };
1144
1145                 SIVAL(buf, 0, time(NULL));
1146
1147                 tdb_store_bystring(tdb, "WINBINDD_OFFLINE", d, TDB_INSERT);
1148
1149                 ret = send_message(msg_ctx, pid, MSG_WINBIND_OFFLINE,
1150                                    NULL, 0);
1151
1152                 /* Check that the entry "WINBINDD_OFFLINE" still exists. */
1153                 d = tdb_fetch_bystring( tdb, "WINBINDD_OFFLINE" );
1154                 if (d.dptr != NULL && d.dsize == 4) {
1155                         SAFE_FREE(d.dptr);
1156                         break;
1157                 }
1158
1159                 SAFE_FREE(d.dptr);
1160                 DEBUG(10,("do_winbind_offline: offline state not set - retrying.\n"));
1161         }
1162
1163         tdb_close(tdb);
1164         return ret;
1165 }
1166
1167 static bool do_winbind_onlinestatus(struct tevent_context *ev_ctx,
1168                                     struct messaging_context *msg_ctx,
1169                                     const struct server_id pid,
1170                                     const int argc, const char **argv)
1171 {
1172         if (argc != 1) {
1173                 fprintf(stderr, "Usage: smbcontrol winbindd onlinestatus\n");
1174                 return False;
1175         }
1176
1177         messaging_register(msg_ctx, NULL, MSG_WINBIND_ONLINESTATUS,
1178                            print_pid_string_cb);
1179
1180         if (!send_message(msg_ctx, pid, MSG_WINBIND_ONLINESTATUS, NULL, 0)) {
1181                 return False;
1182         }
1183
1184         wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
1185
1186         /* No replies were received within the timeout period */
1187
1188         if (num_replies == 0)
1189                 printf("No replies received\n");
1190
1191         messaging_deregister(msg_ctx, MSG_WINBIND_ONLINESTATUS, NULL);
1192
1193         return num_replies;
1194 }
1195
1196 static bool do_winbind_dump_domain_list(struct tevent_context *ev_ctx,
1197                                         struct messaging_context *msg_ctx,
1198                                         const struct server_id pid,
1199                                         const int argc, const char **argv)
1200 {
1201         const char *domain = NULL;
1202         int domain_len = 0;
1203
1204         if (argc < 1 || argc > 2) {
1205                 fprintf(stderr, "Usage: smbcontrol <dest> dump-domain-list "
1206                         "<domain>\n");
1207                 return false;
1208         }
1209
1210         if (argc == 2) {
1211                 domain = argv[1];
1212                 domain_len = strlen(argv[1]) + 1;
1213         }
1214
1215         messaging_register(msg_ctx, NULL, MSG_WINBIND_DUMP_DOMAIN_LIST,
1216                            print_pid_string_cb);
1217
1218         if (!send_message(msg_ctx, pid, MSG_WINBIND_DUMP_DOMAIN_LIST,
1219                           domain, domain_len))
1220         {
1221                 return false;
1222         }
1223
1224         wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
1225
1226         /* No replies were received within the timeout period */
1227
1228         if (num_replies == 0) {
1229                 printf("No replies received\n");
1230         }
1231
1232         messaging_deregister(msg_ctx, MSG_WINBIND_DUMP_DOMAIN_LIST, NULL);
1233
1234         return num_replies;
1235 }
1236
1237 static bool do_msg_disconnect_dc(struct tevent_context *ev_ctx,
1238                                  struct messaging_context *msg_ctx,
1239                                  const struct server_id pid,
1240                                  const int argc, const char **argv)
1241 {
1242         if (argc != 1) {
1243                 fprintf(stderr, "Usage: smbcontrol <dest> disconnect-dc\n");
1244                 return False;
1245         }
1246
1247         return send_message(msg_ctx, pid, MSG_WINBIND_DISCONNECT_DC, NULL, 0);
1248 }
1249
1250 static void winbind_validate_cache_cb(struct messaging_context *msg,
1251                                       void *private_data,
1252                                       uint32_t msg_type,
1253                                       struct server_id pid,
1254                                       DATA_BLOB *data)
1255 {
1256         struct server_id_buf src_string;
1257         printf("Winbindd cache is %svalid. (answer from pid %s)\n",
1258                (*(data->data) == 0 ? "" : "NOT "),
1259                server_id_str_buf(pid, &src_string));
1260         num_replies++;
1261 }
1262
1263 static bool do_winbind_validate_cache(struct tevent_context *ev_ctx,
1264                                       struct messaging_context *msg_ctx,
1265                                       const struct server_id pid,
1266                                       const int argc, const char **argv)
1267 {
1268         struct server_id myid;
1269
1270         myid = messaging_server_id(msg_ctx);
1271
1272         if (argc != 1) {
1273                 fprintf(stderr, "Usage: smbcontrol winbindd validate-cache\n");
1274                 return False;
1275         }
1276
1277         messaging_register(msg_ctx, NULL, MSG_WINBIND_VALIDATE_CACHE,
1278                            winbind_validate_cache_cb);
1279
1280         if (!send_message(msg_ctx, pid, MSG_WINBIND_VALIDATE_CACHE, &myid,
1281                           sizeof(myid))) {
1282                 return False;
1283         }
1284
1285         wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
1286
1287         if (num_replies == 0) {
1288                 printf("No replies received\n");
1289         }
1290
1291         messaging_deregister(msg_ctx, MSG_WINBIND_VALIDATE_CACHE, NULL);
1292
1293         return num_replies;
1294 }
1295
1296 static bool do_reload_config(struct tevent_context *ev_ctx,
1297                              struct messaging_context *msg_ctx,
1298                              const struct server_id pid,
1299                              const int argc, const char **argv)
1300 {
1301         if (argc != 1) {
1302                 fprintf(stderr, "Usage: smbcontrol <dest> reload-config\n");
1303                 return False;
1304         }
1305
1306         return send_message(msg_ctx, pid, MSG_SMB_CONF_UPDATED, NULL, 0);
1307 }
1308
1309 static bool do_reload_printers(struct tevent_context *ev_ctx,
1310                                struct messaging_context *msg_ctx,
1311                                const struct server_id pid,
1312                                const int argc, const char **argv)
1313 {
1314         if (argc != 1) {
1315                 fprintf(stderr, "Usage: smbcontrol <dest> reload-printers\n");
1316                 return False;
1317         }
1318
1319         return send_message(msg_ctx, pid, MSG_PRINTER_PCAP, NULL, 0);
1320 }
1321
1322 static void my_make_nmb_name( struct nmb_name *n, const char *name, int type)
1323 {
1324         fstring unix_name;
1325         memset( (char *)n, '\0', sizeof(struct nmb_name) );
1326         fstrcpy(unix_name, name);
1327         (void)strupper_m(unix_name);
1328         push_ascii(n->name, unix_name, sizeof(n->name), STR_TERMINATE);
1329         n->name_type = (unsigned int)type & 0xFF;
1330         push_ascii(n->scope,  lp_netbios_scope(), 64, STR_TERMINATE);
1331 }
1332
1333 static bool do_nodestatus(struct tevent_context *ev_ctx,
1334                           struct messaging_context *msg_ctx,
1335                           const struct server_id pid,
1336                           const int argc, const char **argv)
1337 {
1338         struct packet_struct p;
1339
1340         if (argc != 2) {
1341                 fprintf(stderr, "Usage: smbcontrol nmbd nodestatus <ip>\n");
1342                 return False;
1343         }
1344
1345         ZERO_STRUCT(p);
1346
1347         p.ip = interpret_addr2(argv[1]);
1348         p.port = 137;
1349         p.packet_type = NMB_PACKET;
1350
1351         p.packet.nmb.header.name_trn_id = 10;
1352         p.packet.nmb.header.opcode = 0;
1353         p.packet.nmb.header.response = False;
1354         p.packet.nmb.header.nm_flags.bcast = False;
1355         p.packet.nmb.header.nm_flags.recursion_available = False;
1356         p.packet.nmb.header.nm_flags.recursion_desired = False;
1357         p.packet.nmb.header.nm_flags.trunc = False;
1358         p.packet.nmb.header.nm_flags.authoritative = False;
1359         p.packet.nmb.header.rcode = 0;
1360         p.packet.nmb.header.qdcount = 1;
1361         p.packet.nmb.header.ancount = 0;
1362         p.packet.nmb.header.nscount = 0;
1363         p.packet.nmb.header.arcount = 0;
1364         my_make_nmb_name(&p.packet.nmb.question.question_name, "*", 0x00);
1365         p.packet.nmb.question.question_type = 0x21;
1366         p.packet.nmb.question.question_class = 0x1;
1367
1368         return send_message(msg_ctx, pid, MSG_SEND_PACKET, &p, sizeof(p));
1369 }
1370
1371 static bool do_notify_cleanup(struct tevent_context *ev_ctx,
1372                               struct messaging_context *msg_ctx,
1373                               const struct server_id pid,
1374                               const int argc, const char **argv)
1375 {
1376         if (argc != 1) {
1377                 fprintf(stderr, "Usage: smbcontrol smbd notify-cleanup\n");
1378                 return false;
1379         }
1380         return send_message(msg_ctx, pid, MSG_SMB_NOTIFY_CLEANUP, NULL, 0);
1381 }
1382
1383 /* A list of message type supported */
1384
1385 static const struct {
1386         const char *name;       /* Option name */
1387         bool (*fn)(struct tevent_context *ev_ctx,
1388                    struct messaging_context *msg_ctx,
1389                    const struct server_id pid,
1390                    const int argc, const char **argv);
1391         const char *help;       /* Short help text */
1392 } msg_types[] = {
1393         {
1394                 .name = "debug",
1395                 .fn   = do_debug,
1396                 .help = "Set debuglevel",
1397         },
1398         {
1399                 .name = "idmap",
1400                 .fn   = do_idmap,
1401                 .help = "Manipulate idmap cache",
1402         },
1403         {
1404                 .name = "force-election",
1405                 .fn   = do_election,
1406                 .help = "Force a browse election",
1407         },
1408         {
1409                 .name = "ping",
1410                 .fn   = do_ping,
1411                 .help = "Elicit a response",
1412         },
1413         {
1414                 .name = "profile",
1415                 .fn   = do_profile,
1416                 .help = "",
1417         },
1418         {
1419                 .name = "inject",
1420                 .fn   = do_inject_fault,
1421                 .help = "Inject a fatal signal into a running smbd"},
1422         {
1423                 .name = "stacktrace",
1424                 .fn   = do_daemon_stack_trace,
1425                 .help = "Display a stack trace of a daemon",
1426         },
1427         {
1428                 .name = "profilelevel",
1429                 .fn   = do_profilelevel,
1430                 .help = "",
1431         },
1432         {
1433                 .name = "debuglevel",
1434                 .fn   = do_debuglevel,
1435                 .help = "Display current debuglevels",
1436         },
1437         {
1438                 .name = "printnotify",
1439                 .fn   = do_printnotify,
1440                 .help = "Send a print notify message",
1441         },
1442         {
1443                 .name = "close-share",
1444                 .fn   = do_closeshare,
1445                 .help = "Forcibly disconnect a share",
1446         },
1447         {
1448                 .name = "kill-client-ip",
1449                 .fn   = do_kill_client_by_ip,
1450                 .help = "Forcibly disconnect a client with a specific IP address",
1451         },
1452         {
1453                 .name = "ip-dropped",
1454                 .fn   = do_ip_dropped,
1455                 .help = "Tell winbind that an IP got dropped",
1456         },
1457         {
1458                 .name = "pool-usage",
1459                 .fn   = do_poolusage,
1460                 .help = "Display talloc memory usage",
1461         },
1462         {
1463                 .name = "ringbuf-log",
1464                 .fn   = do_ringbuflog,
1465                 .help = "Display ringbuf log",
1466         },
1467         {
1468                 .name = "dmalloc-mark",
1469                 .fn   = do_dmalloc_mark,
1470                 .help = "",
1471         },
1472         {
1473                 .name = "dmalloc-log-changed",
1474                 .fn   = do_dmalloc_changed,
1475                 .help = "",
1476         },
1477         {
1478                 .name = "shutdown",
1479                 .fn   = do_shutdown,
1480                 .help = "Shut down daemon",
1481         },
1482         {
1483                 .name = "drvupgrade",
1484                 .fn   = do_drvupgrade,
1485                 .help = "Notify a printer driver has changed",
1486         },
1487         {
1488                 .name = "reload-config",
1489                 .fn   = do_reload_config,
1490                 .help = "Force smbd or winbindd to reload config file"},
1491         {
1492                 .name = "reload-printers",
1493                 .fn   = do_reload_printers,
1494                 .help = "Force smbd to reload printers"},
1495         {
1496                 .name = "nodestatus",
1497                 .fn   = do_nodestatus,
1498                 .help = "Ask nmbd to do a node status request"},
1499         {
1500                 .name = "online",
1501                 .fn   = do_winbind_online,
1502                 .help = "Ask winbind to go into online state"},
1503         {
1504                 .name = "offline",
1505                 .fn   = do_winbind_offline,
1506                 .help = "Ask winbind to go into offline state"},
1507         {
1508                 .name = "onlinestatus",
1509                 .fn   = do_winbind_onlinestatus,
1510                 .help = "Request winbind online status"},
1511         {
1512                 .name = "validate-cache" ,
1513                 .fn   = do_winbind_validate_cache,
1514                 .help = "Validate winbind's credential cache",
1515         },
1516         {
1517                 .name = "dump-domain-list",
1518                 .fn   = do_winbind_dump_domain_list,
1519                 .help = "Dump winbind domain list"},
1520         {
1521                 .name = "disconnect-dc",
1522                 .fn   = do_msg_disconnect_dc,
1523         },
1524         {
1525                 .name = "notify-cleanup",
1526                 .fn   = do_notify_cleanup,
1527         },
1528         {
1529                 .name = "num-children",
1530                 .fn   = do_num_children,
1531                 .help = "Print number of smbd child processes",
1532         },
1533         {
1534                 .name = "msg-cleanup",
1535                 .fn   = do_msg_cleanup,
1536         },
1537         {
1538                 .name = "noop",
1539                 .fn   = do_noop,
1540                 .help = "Do nothing",
1541         },
1542         {
1543                 .name = "sleep",
1544                 .fn   = do_sleep,
1545                 .help = "Cause the target process to sleep",
1546         },
1547         { .name = NULL, },
1548 };
1549
1550 /* Display usage information */
1551
1552 static void usage(poptContext pc)
1553 {
1554         int i;
1555
1556         poptPrintHelp(pc, stderr, 0);
1557
1558         fprintf(stderr, "\n");
1559         fprintf(stderr, "<destination> is one of \"nmbd\", \"smbd\", \"winbindd\" or a "
1560                 "process ID\n");
1561
1562         fprintf(stderr, "\n");
1563         fprintf(stderr, "<message-type> is one of:\n");
1564
1565         for (i = 0; msg_types[i].name; i++) {
1566                 const char *help = msg_types[i].help;
1567                 if (help == NULL) {
1568                         help = "";
1569                 }
1570                 fprintf(stderr, "\t%-30s%s\n", msg_types[i].name, help);
1571         }
1572
1573         fprintf(stderr, "\n");
1574
1575         exit(1);
1576 }
1577
1578 /* Return the pid number for a string destination */
1579
1580 static struct server_id parse_dest(struct messaging_context *msg,
1581                                    const char *dest)
1582 {
1583         struct server_id result = {
1584                 .pid = (uint64_t)-1,
1585         };
1586         pid_t pid;
1587
1588         /* Zero is a special return value for broadcast to all processes */
1589
1590         if (strequal(dest, "all")) {
1591                 return interpret_pid(MSG_BROADCAST_PID_STR);
1592         }
1593
1594         /* Try self - useful for testing */
1595
1596         if (strequal(dest, "self")) {
1597                 return messaging_server_id(msg);
1598         }
1599
1600         /* Fix winbind typo. */
1601         if (strequal(dest, "winbind")) {
1602                 dest = "winbindd";
1603         }
1604
1605         /* Check for numeric pid number */
1606         result = interpret_pid(dest);
1607
1608         /* Zero isn't valid if not "all". */
1609         if (result.pid && procid_valid(&result)) {
1610                 return result;
1611         }
1612
1613         /* Look up other destinations in pidfile directory */
1614
1615         if ((pid = pidfile_pid(lp_pid_directory(), dest)) != 0) {
1616                 return pid_to_procid(pid);
1617         }
1618
1619         fprintf(stderr,"Can't find pid for destination '%s'\n", dest);
1620
1621         return result;
1622 }
1623
1624 /* Execute smbcontrol command */
1625
1626 static bool do_command(struct tevent_context *ev_ctx,
1627                        struct messaging_context *msg_ctx,
1628                        int argc, const char **argv)
1629 {
1630         const char *dest = argv[0], *command = argv[1];
1631         struct server_id pid;
1632         int i;
1633
1634         /* Check destination */
1635
1636         pid = parse_dest(msg_ctx, dest);
1637         if (!procid_valid(&pid)) {
1638                 return False;
1639         }
1640
1641         /* Check command */
1642
1643         for (i = 0; msg_types[i].name; i++) {
1644                 if (strequal(command, msg_types[i].name))
1645                         return msg_types[i].fn(ev_ctx, msg_ctx, pid,
1646                                                argc - 1, argv + 1);
1647         }
1648
1649         fprintf(stderr, "smbcontrol: unknown command '%s'\n", command);
1650
1651         return False;
1652 }
1653
1654 static void smbcontrol_help(poptContext pc,
1655                     enum poptCallbackReason preason,
1656                     struct poptOption * poption,
1657                     const char * parg,
1658                     void * pdata)
1659 {
1660         if (poption->shortName != '?') {
1661                 poptPrintUsage(pc, stdout, 0);
1662         } else {
1663                 usage(pc);
1664         }
1665
1666         exit(0);
1667 }
1668
1669 struct poptOption help_options[] = {
1670         { NULL, '\0', POPT_ARG_CALLBACK, (void *)&smbcontrol_help, '\0',
1671           NULL, NULL },
1672         { "help", '?', 0, NULL, '?', "Show this help message", NULL },
1673         { "usage", '\0', 0, NULL, 'u', "Display brief usage message", NULL },
1674         { NULL }
1675 } ;
1676
1677 /* Main program */
1678
1679 int main(int argc, const char **argv)
1680 {
1681         poptContext pc;
1682         int opt;
1683         struct tevent_context *evt_ctx;
1684         struct messaging_context *msg_ctx;
1685
1686         static struct poptOption long_options[] = {
1687                 /* POPT_AUTOHELP */
1688                 { NULL, '\0', POPT_ARG_INCLUDE_TABLE, help_options,
1689                                         0, "Help options:", NULL },
1690                 { "timeout", 't', POPT_ARG_INT, &timeout, 't', 
1691                   "Set timeout value in seconds", "TIMEOUT" },
1692
1693                 POPT_COMMON_SAMBA
1694                 POPT_TABLEEND
1695         };
1696         TALLOC_CTX *frame = talloc_stackframe();
1697         int ret = 0;
1698
1699         smb_init_locale();
1700
1701         setup_logging(argv[0], DEBUG_STDOUT);
1702         lp_set_cmdline("log level", "0");
1703
1704         /* Parse command line arguments using popt */
1705
1706         pc = poptGetContext(
1707                 "smbcontrol", argc, (const char **)argv, long_options, 0);
1708
1709         poptSetOtherOptionHelp(pc, "[OPTION...] <destination> <message-type> "
1710                                "<parameters>");
1711
1712         if (argc == 1)
1713                 usage(pc);
1714
1715         while ((opt = poptGetNextOpt(pc)) != -1) {
1716                 switch(opt) {
1717                 case 't':       /* --timeout */
1718                         break;
1719                 default:
1720                         fprintf(stderr, "Invalid option\n");
1721                         poptPrintHelp(pc, stderr, 0);
1722                         break;
1723                 }
1724         }
1725
1726         /* We should now have the remaining command line arguments in
1727            argv.  The argc parameter should have been decremented to the
1728            correct value in the above switch statement. */
1729
1730         argv = (const char **)poptGetArgs(pc);
1731         argc = 0;
1732         if (argv != NULL) {
1733                 while (argv[argc] != NULL) {
1734                         argc++;
1735                 }
1736         }
1737
1738         if (argc <= 1)
1739                 usage(pc);
1740
1741         msg_ctx = cmdline_messaging_context(get_dyn_CONFIGFILE());
1742         if (msg_ctx == NULL) {
1743                 fprintf(stderr,
1744                         "Could not init messaging context, not root?\n");
1745                 TALLOC_FREE(frame);
1746                 exit(1);
1747         }
1748
1749         evt_ctx = global_event_context();
1750
1751         lp_load_global(get_dyn_CONFIGFILE());
1752
1753         /* Need to invert sense of return code -- samba
1754          * routines mostly return True==1 for success, but
1755          * shell needs 0. */ 
1756
1757         ret = !do_command(evt_ctx, msg_ctx, argc, argv);
1758
1759         poptFreeContext(pc);
1760         TALLOC_FREE(frame);
1761         return ret;
1762 }