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