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