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