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