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