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