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