CVE-2018-16852 dcerpc dnsserver: Verification tests
[Samba.git] / source3 / utils / smbcontrol.c
blob597bab6450dd7ae8246c706da1960ea2721baed0
1 /*
2 Unix SMB/CIFS implementation.
4 Send messages to other Samba daemons
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
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.
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.
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/>.
26 #include "includes.h"
27 #include "system/filesys.h"
28 #include "lib/util/server_id.h"
29 #include "popt_common.h"
30 #include "librpc/gen_ndr/spoolss.h"
31 #include "nt_printing.h"
32 #include "printing/notify.h"
33 #include "libsmb/nmblib.h"
34 #include "messages.h"
35 #include "util_tdb.h"
36 #include "../lib/util/pidfile.h"
37 #include "serverid.h"
38 #include "cmdline_contexts.h"
40 #if HAVE_LIBUNWIND_H
41 #include <libunwind.h>
42 #endif
44 #if HAVE_LIBUNWIND_PTRACE_H
45 #include <libunwind-ptrace.h>
46 #endif
48 #if HAVE_SYS_PTRACE_H
49 #include <sys/ptrace.h>
50 #endif
52 /* Default timeout value when waiting for replies (in seconds) */
54 #define DEFAULT_TIMEOUT 10
56 static int timeout = DEFAULT_TIMEOUT;
57 static int num_replies; /* Used by message callback fns */
59 /* Send a message to a destination pid. Zero means broadcast smbd. */
61 static bool send_message(struct messaging_context *msg_ctx,
62 struct server_id pid, int msg_type,
63 const void *buf, int len)
65 if (procid_to_pid(&pid) != 0)
66 return NT_STATUS_IS_OK(
67 messaging_send_buf(msg_ctx, pid, msg_type,
68 (const uint8_t *)buf, len));
70 messaging_send_all(msg_ctx, msg_type, buf, len);
72 return true;
75 static void smbcontrol_timeout(struct tevent_context *event_ctx,
76 struct tevent_timer *te,
77 struct timeval now,
78 void *private_data)
80 bool *timed_out = (bool *)private_data;
81 TALLOC_FREE(te);
82 *timed_out = True;
85 /* Wait for one or more reply messages */
87 static void wait_replies(struct tevent_context *ev_ctx,
88 struct messaging_context *msg_ctx,
89 bool multiple_replies)
91 struct tevent_timer *te;
92 bool timed_out = False;
94 te = tevent_add_timer(ev_ctx, NULL,
95 timeval_current_ofs(timeout, 0),
96 smbcontrol_timeout, (void *)&timed_out);
97 if (te == NULL) {
98 DEBUG(0, ("tevent_add_timer failed\n"));
99 return;
102 while (!timed_out) {
103 int ret;
104 if (num_replies > 0 && !multiple_replies)
105 break;
106 ret = tevent_loop_once(ev_ctx);
107 if (ret != 0) {
108 break;
113 /* Message handler callback that displays the PID and a string on stdout */
115 static void print_pid_string_cb(struct messaging_context *msg,
116 void *private_data,
117 uint32_t msg_type,
118 struct server_id pid,
119 DATA_BLOB *data)
121 struct server_id_buf pidstr;
123 printf("PID %s: %.*s", server_id_str_buf(pid, &pidstr),
124 (int)data->length, (const char *)data->data);
125 num_replies++;
128 /* Message handler callback that displays a string on stdout */
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)
136 printf("%*s", (int)data->length, (const char *)data->data);
137 num_replies++;
140 /* Send no message. Useful for testing. */
142 static bool do_noop(struct tevent_context *ev_ctx,
143 struct messaging_context *msg_ctx,
144 const struct server_id pid,
145 const int argc, const char **argv)
147 if (argc != 1) {
148 fprintf(stderr, "Usage: smbcontrol <dest> noop\n");
149 return False;
152 /* Move along, nothing to see here */
154 return True;
157 /* Send a debug string */
159 static bool do_debug(struct tevent_context *ev_ctx,
160 struct messaging_context *msg_ctx,
161 const struct server_id pid,
162 const int argc, const char **argv)
164 if (argc != 2) {
165 fprintf(stderr, "Usage: smbcontrol <dest> debug "
166 "<debug-string>\n");
167 return False;
170 return send_message(msg_ctx, pid, MSG_DEBUG, argv[1],
171 strlen(argv[1]) + 1);
175 static bool do_idmap(struct tevent_context *ev,
176 struct messaging_context *msg_ctx,
177 const struct server_id pid,
178 const int argc, const char **argv)
180 static const char* usage = "Usage: "
181 "smbcontrol <dest> idmap <cmd> [arg]\n"
182 "\tcmd:"
183 "\tdelete \"UID <uid>\"|\"GID <gid>\"|<sid>\n"
184 "\t\tkill \"UID <uid>\"|\"GID <gid>\"|<sid>\n";
185 const char* arg = NULL;
186 int arglen = 0;
187 int msg_type;
189 switch (argc) {
190 case 2:
191 break;
192 case 3:
193 arg = argv[2];
194 arglen = strlen(arg) + 1;
195 break;
196 default:
197 fprintf(stderr, "%s", usage);
198 return false;
201 if (strcmp(argv[1], "delete") == 0) {
202 msg_type = ID_CACHE_DELETE;
204 else if (strcmp(argv[1], "kill") == 0) {
205 msg_type = ID_CACHE_KILL;
207 else if (strcmp(argv[1], "help") == 0) {
208 fprintf(stdout, "%s", usage);
209 return true;
211 else {
212 fprintf(stderr, "%s", usage);
213 return false;
216 return send_message(msg_ctx, pid, msg_type, arg, arglen);
220 #if defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE)
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 implementation is
224 * Linux-specific anyway.
226 static const char * procname(pid_t pid, char * buf, size_t bufsz)
228 char path[64];
229 FILE * fp;
231 snprintf(path, sizeof(path), "/proc/%llu/cmdline",
232 (unsigned long long)pid);
233 if ((fp = fopen(path, "r")) == NULL) {
234 return NULL;
237 fgets(buf, bufsz, fp);
239 fclose(fp);
240 return buf;
243 static void print_stack_trace(pid_t pid, int * count)
245 void * pinfo = NULL;
246 unw_addr_space_t aspace = NULL;
247 unw_cursor_t cursor;
248 unw_word_t ip, sp;
250 char nbuf[256];
251 unw_word_t off;
253 int ret;
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;
262 /* Wait until the attach is complete. */
263 waitpid(pid, NULL, 0);
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;
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;
281 if (*count > 0) {
282 printf("\n");
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);
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);
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>");
302 printf(" %s + %#llx [ip=%#llx] [sp=%#llx]\n",
303 nbuf, (long long)off, (long long)ip,
304 (long long)sp);
307 (*count)++;
309 cleanup:
310 if (aspace) {
311 unw_destroy_addr_space(aspace);
314 if (pinfo) {
315 _UPT_destroy(pinfo);
318 ptrace(PTRACE_DETACH, pid, NULL, NULL);
321 static int stack_trace_server(pid_t pid, void *priv)
323 print_stack_trace(pid, (int *)priv);
324 return 0;
327 static bool do_daemon_stack_trace(struct tevent_context *ev_ctx,
328 struct messaging_context *msg_ctx,
329 const struct server_id pid,
330 const int argc, const char **argv)
332 pid_t dest;
333 int count = 0;
335 if (argc != 1) {
336 fprintf(stderr, "Usage: smbcontrol <dest> stacktrace\n");
337 return False;
340 dest = procid_to_pid(&pid);
342 if (dest != 0) {
343 /* It would be nice to be able to make sure that this PID is
344 * the PID of a smbd/winbind/nmbd process, not some random PID
345 * the user liked the look of. It doesn't seem like it's worth
346 * the effort at the moment, however.
348 print_stack_trace(dest, &count);
349 } else {
350 messaging_dgm_forall(stack_trace_server, &count);
353 return True;
356 #else /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
358 static bool do_daemon_stack_trace(struct tevent_context *ev_ctx,
359 struct messaging_context *msg_ctx,
360 const struct server_id pid,
361 const int argc, const char **argv)
363 fprintf(stderr,
364 "Daemon stack tracing is not supported on this platform\n");
365 return False;
368 #endif /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
370 /* Inject a fault (fatal signal) into a running smbd */
372 static bool do_inject_fault(struct tevent_context *ev_ctx,
373 struct messaging_context *msg_ctx,
374 const struct server_id pid,
375 const int argc, const char **argv)
377 if (argc != 2) {
378 fprintf(stderr, "Usage: smbcontrol <dest> inject "
379 "<bus|hup|term|internal|segv>\n");
380 return False;
383 #ifndef DEVELOPER
384 fprintf(stderr, "Fault injection is only available in "
385 "developer builds\n");
386 return False;
387 #else /* DEVELOPER */
389 int sig = 0;
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;
407 return send_message(msg_ctx, pid, MSG_SMB_INJECT_FAULT,
408 &sig, sizeof(int));
410 #endif /* DEVELOPER */
413 /* Force a browser election */
415 static bool do_election(struct tevent_context *ev_ctx,
416 struct messaging_context *msg_ctx,
417 const struct server_id pid,
418 const int argc, const char **argv)
420 if (argc != 1) {
421 fprintf(stderr, "Usage: smbcontrol <dest> force-election\n");
422 return False;
425 return send_message(msg_ctx, pid, MSG_FORCE_ELECTION, NULL, 0);
428 /* Ping a samba daemon process */
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)
436 struct server_id_buf src_string;
437 printf("PONG from pid %s\n", server_id_str_buf(pid, &src_string));
438 num_replies++;
441 static bool do_ping(struct tevent_context *ev_ctx,
442 struct messaging_context *msg_ctx,
443 const struct server_id pid,
444 const int argc, const char **argv)
446 if (argc != 1) {
447 fprintf(stderr, "Usage: smbcontrol <dest> ping\n");
448 return False;
451 /* Send a message and register our interest in a reply */
453 if (!send_message(msg_ctx, pid, MSG_PING, NULL, 0))
454 return False;
456 messaging_register(msg_ctx, NULL, MSG_PONG, pong_cb);
458 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
460 /* No replies were received within the timeout period */
462 if (num_replies == 0)
463 printf("No replies received\n");
465 messaging_deregister(msg_ctx, MSG_PONG, NULL);
467 return num_replies;
470 /* Set profiling options */
472 static bool do_profile(struct tevent_context *ev_ctx,
473 struct messaging_context *msg_ctx,
474 const struct server_id pid,
475 const int argc, const char **argv)
477 int v;
479 if (argc != 2) {
480 fprintf(stderr, "Usage: smbcontrol <dest> profile "
481 "<off|count|on|flush>\n");
482 return False;
485 if (strcmp(argv[1], "off") == 0) {
486 v = 0;
487 } else if (strcmp(argv[1], "count") == 0) {
488 v = 1;
489 } else if (strcmp(argv[1], "on") == 0) {
490 v = 2;
491 } else if (strcmp(argv[1], "flush") == 0) {
492 v = 3;
493 } else {
494 fprintf(stderr, "Unknown profile command '%s'\n", argv[1]);
495 return False;
498 return send_message(msg_ctx, pid, MSG_PROFILE, &v, sizeof(int));
501 /* Return the profiling level */
503 static void profilelevel_cb(struct messaging_context *msg_ctx,
504 void *private_data,
505 uint32_t msg_type,
506 struct server_id pid,
507 DATA_BLOB *data)
509 int level;
510 const char *s;
512 num_replies++;
514 if (data->length != sizeof(int)) {
515 fprintf(stderr, "invalid message length %ld returned\n",
516 (unsigned long)data->length);
517 return;
520 memcpy(&level, data->data, sizeof(int));
522 switch (level) {
523 case 0:
524 s = "not enabled";
525 break;
526 case 1:
527 s = "off";
528 break;
529 case 3:
530 s = "count only";
531 break;
532 case 7:
533 s = "count and time";
534 break;
535 default:
536 s = "BOGUS";
537 break;
540 printf("Profiling %s on pid %u\n",s,(unsigned int)procid_to_pid(&pid));
543 static void profilelevel_rqst(struct messaging_context *msg_ctx,
544 void *private_data,
545 uint32_t msg_type,
546 struct server_id pid,
547 DATA_BLOB *data)
549 int v = 0;
551 /* Send back a dummy reply */
553 send_message(msg_ctx, pid, MSG_PROFILELEVEL, &v, sizeof(int));
556 static bool do_profilelevel(struct tevent_context *ev_ctx,
557 struct messaging_context *msg_ctx,
558 const struct server_id pid,
559 const int argc, const char **argv)
561 if (argc != 1) {
562 fprintf(stderr, "Usage: smbcontrol <dest> profilelevel\n");
563 return False;
566 /* Send a message and register our interest in a reply */
568 if (!send_message(msg_ctx, pid, MSG_REQ_PROFILELEVEL, NULL, 0))
569 return False;
571 messaging_register(msg_ctx, NULL, MSG_PROFILELEVEL, profilelevel_cb);
572 messaging_register(msg_ctx, NULL, MSG_REQ_PROFILELEVEL,
573 profilelevel_rqst);
575 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
577 /* No replies were received within the timeout period */
579 if (num_replies == 0)
580 printf("No replies received\n");
582 messaging_deregister(msg_ctx, MSG_PROFILE, NULL);
584 return num_replies;
587 /* Display debug level settings */
589 static bool do_debuglevel(struct tevent_context *ev_ctx,
590 struct messaging_context *msg_ctx,
591 const struct server_id pid,
592 const int argc, const char **argv)
594 if (argc != 1) {
595 fprintf(stderr, "Usage: smbcontrol <dest> debuglevel\n");
596 return False;
599 /* Send a message and register our interest in a reply */
601 if (!send_message(msg_ctx, pid, MSG_REQ_DEBUGLEVEL, NULL, 0))
602 return False;
604 messaging_register(msg_ctx, NULL, MSG_DEBUGLEVEL, print_pid_string_cb);
606 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
608 /* No replies were received within the timeout period */
610 if (num_replies == 0)
611 printf("No replies received\n");
613 messaging_deregister(msg_ctx, MSG_DEBUGLEVEL, NULL);
615 return num_replies;
618 /* Send a print notify message */
620 static bool do_printnotify(struct tevent_context *ev_ctx,
621 struct messaging_context *msg_ctx,
622 const struct server_id pid,
623 const int argc, const char **argv)
625 const char *cmd;
627 /* Check for subcommand */
629 if (argc == 1) {
630 fprintf(stderr, "Must specify subcommand:\n");
631 fprintf(stderr, "\tqueuepause <printername>\n");
632 fprintf(stderr, "\tqueueresume <printername>\n");
633 fprintf(stderr, "\tjobpause <printername> <unix jobid>\n");
634 fprintf(stderr, "\tjobresume <printername> <unix jobid>\n");
635 fprintf(stderr, "\tjobdelete <printername> <unix jobid>\n");
636 fprintf(stderr, "\tprinter <printername> <comment|port|"
637 "driver> <value>\n");
639 return False;
642 cmd = argv[1];
644 if (strcmp(cmd, "queuepause") == 0) {
646 if (argc != 3) {
647 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
648 " queuepause <printername>\n");
649 return False;
652 notify_printer_status_byname(ev_ctx, msg_ctx, argv[2],
653 PRINTER_STATUS_PAUSED);
655 goto send;
657 } else if (strcmp(cmd, "queueresume") == 0) {
659 if (argc != 3) {
660 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
661 " queuereume <printername>\n");
662 return False;
665 notify_printer_status_byname(ev_ctx, msg_ctx, argv[2],
666 PRINTER_STATUS_OK);
668 goto send;
670 } else if (strcmp(cmd, "jobpause") == 0) {
671 int jobid;
673 if (argc != 4) {
674 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
675 " jobpause <printername> <unix-jobid>\n");
676 return False;
679 jobid = atoi(argv[3]);
681 notify_job_status_byname(
682 ev_ctx, msg_ctx,
683 argv[2], jobid, JOB_STATUS_PAUSED,
684 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
686 goto send;
688 } else if (strcmp(cmd, "jobresume") == 0) {
689 int jobid;
691 if (argc != 4) {
692 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
693 " jobpause <printername> <unix-jobid>\n");
694 return False;
697 jobid = atoi(argv[3]);
699 notify_job_status_byname(
700 ev_ctx, msg_ctx,
701 argv[2], jobid, JOB_STATUS_QUEUED,
702 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
704 goto send;
706 } else if (strcmp(cmd, "jobdelete") == 0) {
707 int jobid;
709 if (argc != 4) {
710 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
711 " jobpause <printername> <unix-jobid>\n");
712 return False;
715 jobid = atoi(argv[3]);
717 notify_job_status_byname(
718 ev_ctx, msg_ctx,
719 argv[2], jobid, JOB_STATUS_DELETING,
720 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
722 notify_job_status_byname(
723 ev_ctx, msg_ctx,
724 argv[2], jobid, JOB_STATUS_DELETING|
725 JOB_STATUS_DELETED,
726 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
728 goto send;
730 } else if (strcmp(cmd, "printer") == 0) {
731 uint32_t attribute;
733 if (argc != 5) {
734 fprintf(stderr, "Usage: smbcontrol <dest> printnotify "
735 "printer <printername> <comment|port|driver> "
736 "<value>\n");
737 return False;
740 if (strcmp(argv[3], "comment") == 0) {
741 attribute = PRINTER_NOTIFY_FIELD_COMMENT;
742 } else if (strcmp(argv[3], "port") == 0) {
743 attribute = PRINTER_NOTIFY_FIELD_PORT_NAME;
744 } else if (strcmp(argv[3], "driver") == 0) {
745 attribute = PRINTER_NOTIFY_FIELD_DRIVER_NAME;
746 } else {
747 fprintf(stderr, "Invalid printer command '%s'\n",
748 argv[3]);
749 return False;
752 notify_printer_byname(ev_ctx, msg_ctx, argv[2], attribute,
753 discard_const_p(char, argv[4]));
755 goto send;
758 fprintf(stderr, "Invalid subcommand '%s'\n", cmd);
759 return False;
761 send:
762 print_notify_send_messages(msg_ctx, 0);
763 return True;
766 /* Close a share */
768 static bool do_closeshare(struct tevent_context *ev_ctx,
769 struct messaging_context *msg_ctx,
770 const struct server_id pid,
771 const int argc, const char **argv)
773 if (argc != 2) {
774 fprintf(stderr, "Usage: smbcontrol <dest> close-share "
775 "<sharename>\n");
776 return False;
779 return send_message(msg_ctx, pid, MSG_SMB_FORCE_TDIS, argv[1],
780 strlen(argv[1]) + 1);
783 /* Kill a client by IP address */
784 static bool do_kill_client_by_ip(struct tevent_context *ev_ctx,
785 struct messaging_context *msg_ctx,
786 const struct server_id pid,
787 const int argc, const char **argv)
789 if (argc != 2) {
790 fprintf(stderr, "Usage: smbcontrol <dest> kill-client-ip "
791 "<IP address>\n");
792 return false;
795 if (!is_ipaddress_v4(argv[1]) && !is_ipaddress_v6(argv[1])) {
796 fprintf(stderr, "%s is not a valid IP address!\n", argv[1]);
797 return false;
800 return send_message(msg_ctx, pid, MSG_SMB_KILL_CLIENT_IP,
801 argv[1], strlen(argv[1]) + 1);
804 /* Tell winbindd an IP got dropped */
806 static bool do_ip_dropped(struct tevent_context *ev_ctx,
807 struct messaging_context *msg_ctx,
808 const struct server_id pid,
809 const int argc, const char **argv)
811 if (argc != 2) {
812 fprintf(stderr, "Usage: smbcontrol <dest> ip-dropped "
813 "<ip-address>\n");
814 return False;
817 return send_message(msg_ctx, pid, MSG_WINBIND_IP_DROPPED, argv[1],
818 strlen(argv[1]) + 1);
821 /* force a blocking lock retry */
823 static bool do_lockretry(struct tevent_context *ev_ctx,
824 struct messaging_context *msg_ctx,
825 const struct server_id pid,
826 const int argc, const char **argv)
828 if (argc != 1) {
829 fprintf(stderr, "Usage: smbcontrol <dest> lockretry\n");
830 return False;
833 return send_message(msg_ctx, pid, MSG_SMB_UNLOCK, NULL, 0);
836 /* force a validation of all brl entries, including re-sends. */
838 static bool do_brl_revalidate(struct tevent_context *ev_ctx,
839 struct messaging_context *msg_ctx,
840 const struct server_id pid,
841 const int argc, const char **argv)
843 if (argc != 1) {
844 fprintf(stderr, "Usage: smbcontrol <dest> brl-revalidate\n");
845 return False;
848 return send_message(msg_ctx, pid, MSG_SMB_BRL_VALIDATE, NULL, 0);
851 /* Display talloc pool usage */
853 static bool do_poolusage(struct tevent_context *ev_ctx,
854 struct messaging_context *msg_ctx,
855 const struct server_id pid,
856 const int argc, const char **argv)
858 if (argc != 1) {
859 fprintf(stderr, "Usage: smbcontrol <dest> pool-usage\n");
860 return False;
863 messaging_register(msg_ctx, NULL, MSG_POOL_USAGE, print_string_cb);
865 /* Send a message and register our interest in a reply */
867 if (!send_message(msg_ctx, pid, MSG_REQ_POOL_USAGE, NULL, 0))
868 return False;
870 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
872 /* No replies were received within the timeout period */
874 if (num_replies == 0)
875 printf("No replies received\n");
877 messaging_deregister(msg_ctx, MSG_POOL_USAGE, NULL);
879 return num_replies;
882 /* Fetch and print the ringbuf log */
884 static void print_ringbuf_log_cb(struct messaging_context *msg,
885 void *private_data,
886 uint32_t msg_type,
887 struct server_id pid,
888 DATA_BLOB *data)
890 printf("%s", (const char *)data->data);
891 num_replies++;
894 static bool do_ringbuflog(struct tevent_context *ev_ctx,
895 struct messaging_context *msg_ctx,
896 const struct server_id pid,
897 const int argc, const char **argv)
899 if (argc != 1) {
900 fprintf(stderr, "Usage: smbcontrol <dest> ringbuf-log\n");
901 return false;
904 messaging_register(msg_ctx, NULL, MSG_RINGBUF_LOG,
905 print_ringbuf_log_cb);
907 /* Send a message and register our interest in a reply */
909 if (!send_message(msg_ctx, pid, MSG_REQ_RINGBUF_LOG, NULL, 0)) {
910 return false;
913 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
915 /* No replies were received within the timeout period */
917 if (num_replies == 0) {
918 printf("No replies received\n");
921 messaging_deregister(msg_ctx, MSG_RINGBUF_LOG, NULL);
923 return num_replies != 0;
926 /* Perform a dmalloc mark */
928 static bool do_dmalloc_mark(struct tevent_context *ev_ctx,
929 struct messaging_context *msg_ctx,
930 const struct server_id pid,
931 const int argc, const char **argv)
933 if (argc != 1) {
934 fprintf(stderr, "Usage: smbcontrol <dest> dmalloc-mark\n");
935 return False;
938 return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_MARK, NULL, 0);
941 /* Perform a dmalloc changed */
943 static bool do_dmalloc_changed(struct tevent_context *ev_ctx,
944 struct messaging_context *msg_ctx,
945 const struct server_id pid,
946 const int argc, const char **argv)
948 if (argc != 1) {
949 fprintf(stderr, "Usage: smbcontrol <dest> "
950 "dmalloc-log-changed\n");
951 return False;
954 return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_LOG_CHANGED,
955 NULL, 0);
958 static void print_uint32_cb(struct messaging_context *msg, void *private_data,
959 uint32_t msg_type, struct server_id pid,
960 DATA_BLOB *data)
962 uint32_t num_children;
964 if (data->length != sizeof(uint32_t)) {
965 printf("Invalid response: %d bytes long\n",
966 (int)data->length);
967 goto done;
969 num_children = IVAL(data->data, 0);
970 printf("%u children\n", (unsigned)num_children);
971 done:
972 num_replies++;
975 static bool do_num_children(struct tevent_context *ev_ctx,
976 struct messaging_context *msg_ctx,
977 const struct server_id pid,
978 const int argc, const char **argv)
980 if (argc != 1) {
981 fprintf(stderr, "Usage: smbcontrol <dest> num-children\n");
982 return False;
985 messaging_register(msg_ctx, NULL, MSG_SMB_NUM_CHILDREN,
986 print_uint32_cb);
988 /* Send a message and register our interest in a reply */
990 if (!send_message(msg_ctx, pid, MSG_SMB_TELL_NUM_CHILDREN, NULL, 0))
991 return false;
993 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
995 /* No replies were received within the timeout period */
997 if (num_replies == 0)
998 printf("No replies received\n");
1000 messaging_deregister(msg_ctx, MSG_SMB_NUM_CHILDREN, NULL);
1002 return num_replies;
1005 static bool do_msg_cleanup(struct tevent_context *ev_ctx,
1006 struct messaging_context *msg_ctx,
1007 const struct server_id pid,
1008 const int argc, const char **argv)
1010 int ret;
1012 ret = messaging_cleanup(msg_ctx, pid.pid);
1014 printf("cleanup(%u) returned %s\n", (unsigned)pid.pid,
1015 ret ? strerror(ret) : "ok");
1017 return (ret == 0);
1020 /* Shutdown a server process */
1022 static bool do_shutdown(struct tevent_context *ev_ctx,
1023 struct messaging_context *msg_ctx,
1024 const struct server_id pid,
1025 const int argc, const char **argv)
1027 if (argc != 1) {
1028 fprintf(stderr, "Usage: smbcontrol <dest> shutdown\n");
1029 return False;
1032 return send_message(msg_ctx, pid, MSG_SHUTDOWN, NULL, 0);
1035 /* Notify a driver upgrade */
1037 static bool do_drvupgrade(struct tevent_context *ev_ctx,
1038 struct messaging_context *msg_ctx,
1039 const struct server_id pid,
1040 const int argc, const char **argv)
1042 if (argc != 2) {
1043 fprintf(stderr, "Usage: smbcontrol <dest> drvupgrade "
1044 "<driver-name>\n");
1045 return False;
1048 return send_message(msg_ctx, pid, MSG_PRINTER_DRVUPGRADE, argv[1],
1049 strlen(argv[1]) + 1);
1052 static bool do_winbind_online(struct tevent_context *ev_ctx,
1053 struct messaging_context *msg_ctx,
1054 const struct server_id pid,
1055 const int argc, const char **argv)
1057 TDB_CONTEXT *tdb;
1058 char *db_path;
1060 if (argc != 1) {
1061 fprintf(stderr, "Usage: smbcontrol winbindd online\n");
1062 return False;
1065 db_path = state_path(talloc_tos(), "winbindd_cache.tdb");
1066 if (db_path == NULL) {
1067 return false;
1070 /* Remove the entry in the winbindd_cache tdb to tell a later
1071 starting winbindd that we're online. */
1073 tdb = tdb_open_log(db_path, 0, TDB_DEFAULT, O_RDWR, 0600);
1074 if (!tdb) {
1075 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
1076 db_path);
1077 TALLOC_FREE(db_path);
1078 return False;
1081 TALLOC_FREE(db_path);
1082 tdb_delete_bystring(tdb, "WINBINDD_OFFLINE");
1083 tdb_close(tdb);
1085 return send_message(msg_ctx, pid, MSG_WINBIND_ONLINE, NULL, 0);
1088 static bool do_winbind_offline(struct tevent_context *ev_ctx,
1089 struct messaging_context *msg_ctx,
1090 const struct server_id pid,
1091 const int argc, const char **argv)
1093 TDB_CONTEXT *tdb;
1094 bool ret = False;
1095 int retry = 0;
1096 char *db_path;
1098 if (argc != 1) {
1099 fprintf(stderr, "Usage: smbcontrol winbindd offline\n");
1100 return False;
1103 db_path = state_path(talloc_tos(), "winbindd_cache.tdb");
1104 if (db_path == NULL) {
1105 return false;
1108 /* Create an entry in the winbindd_cache tdb to tell a later
1109 starting winbindd that we're offline. We may actually create
1110 it here... */
1112 tdb = tdb_open_log(db_path,
1113 WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
1114 TDB_DEFAULT|TDB_INCOMPATIBLE_HASH /* TDB_CLEAR_IF_FIRST */,
1115 O_RDWR|O_CREAT, 0600);
1117 if (!tdb) {
1118 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
1119 db_path);
1120 TALLOC_FREE(db_path);
1121 return False;
1123 TALLOC_FREE(db_path);
1125 /* There's a potential race condition that if a child
1126 winbindd detects a domain is online at the same time
1127 we're trying to tell it to go offline that it might
1128 delete the record we add between us adding it and
1129 sending the message. Minimize this by retrying up to
1130 5 times. */
1132 for (retry = 0; retry < 5; retry++) {
1133 uint8_t buf[4];
1134 TDB_DATA d = { .dptr = buf, .dsize = sizeof(buf) };
1136 SIVAL(buf, 0, time(NULL));
1138 tdb_store_bystring(tdb, "WINBINDD_OFFLINE", d, TDB_INSERT);
1140 ret = send_message(msg_ctx, pid, MSG_WINBIND_OFFLINE,
1141 NULL, 0);
1143 /* Check that the entry "WINBINDD_OFFLINE" still exists. */
1144 d = tdb_fetch_bystring( tdb, "WINBINDD_OFFLINE" );
1145 if (d.dptr != NULL && d.dsize == 4) {
1146 SAFE_FREE(d.dptr);
1147 break;
1150 SAFE_FREE(d.dptr);
1151 DEBUG(10,("do_winbind_offline: offline state not set - retrying.\n"));
1154 tdb_close(tdb);
1155 return ret;
1158 static bool do_winbind_onlinestatus(struct tevent_context *ev_ctx,
1159 struct messaging_context *msg_ctx,
1160 const struct server_id pid,
1161 const int argc, const char **argv)
1163 if (argc != 1) {
1164 fprintf(stderr, "Usage: smbcontrol winbindd onlinestatus\n");
1165 return False;
1168 messaging_register(msg_ctx, NULL, MSG_WINBIND_ONLINESTATUS,
1169 print_pid_string_cb);
1171 if (!send_message(msg_ctx, pid, MSG_WINBIND_ONLINESTATUS, NULL, 0)) {
1172 return False;
1175 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
1177 /* No replies were received within the timeout period */
1179 if (num_replies == 0)
1180 printf("No replies received\n");
1182 messaging_deregister(msg_ctx, MSG_WINBIND_ONLINESTATUS, NULL);
1184 return num_replies;
1187 static bool do_winbind_dump_domain_list(struct tevent_context *ev_ctx,
1188 struct messaging_context *msg_ctx,
1189 const struct server_id pid,
1190 const int argc, const char **argv)
1192 const char *domain = NULL;
1193 int domain_len = 0;
1195 if (argc < 1 || argc > 2) {
1196 fprintf(stderr, "Usage: smbcontrol <dest> dump-domain-list "
1197 "<domain>\n");
1198 return false;
1201 if (argc == 2) {
1202 domain = argv[1];
1203 domain_len = strlen(argv[1]) + 1;
1206 messaging_register(msg_ctx, NULL, MSG_WINBIND_DUMP_DOMAIN_LIST,
1207 print_pid_string_cb);
1209 if (!send_message(msg_ctx, pid, MSG_WINBIND_DUMP_DOMAIN_LIST,
1210 domain, domain_len))
1212 return false;
1215 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
1217 /* No replies were received within the timeout period */
1219 if (num_replies == 0) {
1220 printf("No replies received\n");
1223 messaging_deregister(msg_ctx, MSG_WINBIND_DUMP_DOMAIN_LIST, NULL);
1225 return num_replies;
1228 static bool do_msg_disconnect_dc(struct tevent_context *ev_ctx,
1229 struct messaging_context *msg_ctx,
1230 const struct server_id pid,
1231 const int argc, const char **argv)
1233 if (argc != 1) {
1234 fprintf(stderr, "Usage: smbcontrol <dest> disconnect-dc\n");
1235 return False;
1238 return send_message(msg_ctx, pid, MSG_WINBIND_DISCONNECT_DC, NULL, 0);
1241 static void winbind_validate_cache_cb(struct messaging_context *msg,
1242 void *private_data,
1243 uint32_t msg_type,
1244 struct server_id pid,
1245 DATA_BLOB *data)
1247 struct server_id_buf src_string;
1248 printf("Winbindd cache is %svalid. (answer from pid %s)\n",
1249 (*(data->data) == 0 ? "" : "NOT "),
1250 server_id_str_buf(pid, &src_string));
1251 num_replies++;
1254 static bool do_winbind_validate_cache(struct tevent_context *ev_ctx,
1255 struct messaging_context *msg_ctx,
1256 const struct server_id pid,
1257 const int argc, const char **argv)
1259 struct server_id myid;
1261 myid = messaging_server_id(msg_ctx);
1263 if (argc != 1) {
1264 fprintf(stderr, "Usage: smbcontrol winbindd validate-cache\n");
1265 return False;
1268 messaging_register(msg_ctx, NULL, MSG_WINBIND_VALIDATE_CACHE,
1269 winbind_validate_cache_cb);
1271 if (!send_message(msg_ctx, pid, MSG_WINBIND_VALIDATE_CACHE, &myid,
1272 sizeof(myid))) {
1273 return False;
1276 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
1278 if (num_replies == 0) {
1279 printf("No replies received\n");
1282 messaging_deregister(msg_ctx, MSG_WINBIND_VALIDATE_CACHE, NULL);
1284 return num_replies;
1287 static bool do_reload_config(struct tevent_context *ev_ctx,
1288 struct messaging_context *msg_ctx,
1289 const struct server_id pid,
1290 const int argc, const char **argv)
1292 if (argc != 1) {
1293 fprintf(stderr, "Usage: smbcontrol <dest> reload-config\n");
1294 return False;
1297 return send_message(msg_ctx, pid, MSG_SMB_CONF_UPDATED, NULL, 0);
1300 static bool do_reload_printers(struct tevent_context *ev_ctx,
1301 struct messaging_context *msg_ctx,
1302 const struct server_id pid,
1303 const int argc, const char **argv)
1305 if (argc != 1) {
1306 fprintf(stderr, "Usage: smbcontrol <dest> reload-printers\n");
1307 return False;
1310 return send_message(msg_ctx, pid, MSG_PRINTER_PCAP, NULL, 0);
1313 static void my_make_nmb_name( struct nmb_name *n, const char *name, int type)
1315 fstring unix_name;
1316 memset( (char *)n, '\0', sizeof(struct nmb_name) );
1317 fstrcpy(unix_name, name);
1318 (void)strupper_m(unix_name);
1319 push_ascii(n->name, unix_name, sizeof(n->name), STR_TERMINATE);
1320 n->name_type = (unsigned int)type & 0xFF;
1321 push_ascii(n->scope, lp_netbios_scope(), 64, STR_TERMINATE);
1324 static bool do_nodestatus(struct tevent_context *ev_ctx,
1325 struct messaging_context *msg_ctx,
1326 const struct server_id pid,
1327 const int argc, const char **argv)
1329 struct packet_struct p;
1331 if (argc != 2) {
1332 fprintf(stderr, "Usage: smbcontrol nmbd nodestatus <ip>\n");
1333 return False;
1336 ZERO_STRUCT(p);
1338 p.ip = interpret_addr2(argv[1]);
1339 p.port = 137;
1340 p.packet_type = NMB_PACKET;
1342 p.packet.nmb.header.name_trn_id = 10;
1343 p.packet.nmb.header.opcode = 0;
1344 p.packet.nmb.header.response = False;
1345 p.packet.nmb.header.nm_flags.bcast = False;
1346 p.packet.nmb.header.nm_flags.recursion_available = False;
1347 p.packet.nmb.header.nm_flags.recursion_desired = False;
1348 p.packet.nmb.header.nm_flags.trunc = False;
1349 p.packet.nmb.header.nm_flags.authoritative = False;
1350 p.packet.nmb.header.rcode = 0;
1351 p.packet.nmb.header.qdcount = 1;
1352 p.packet.nmb.header.ancount = 0;
1353 p.packet.nmb.header.nscount = 0;
1354 p.packet.nmb.header.arcount = 0;
1355 my_make_nmb_name(&p.packet.nmb.question.question_name, "*", 0x00);
1356 p.packet.nmb.question.question_type = 0x21;
1357 p.packet.nmb.question.question_class = 0x1;
1359 return send_message(msg_ctx, pid, MSG_SEND_PACKET, &p, sizeof(p));
1362 static bool do_notify_cleanup(struct tevent_context *ev_ctx,
1363 struct messaging_context *msg_ctx,
1364 const struct server_id pid,
1365 const int argc, const char **argv)
1367 if (argc != 1) {
1368 fprintf(stderr, "Usage: smbcontrol smbd notify-cleanup\n");
1369 return false;
1371 return send_message(msg_ctx, pid, MSG_SMB_NOTIFY_CLEANUP, NULL, 0);
1374 /* A list of message type supported */
1376 static const struct {
1377 const char *name; /* Option name */
1378 bool (*fn)(struct tevent_context *ev_ctx,
1379 struct messaging_context *msg_ctx,
1380 const struct server_id pid,
1381 const int argc, const char **argv);
1382 const char *help; /* Short help text */
1383 } msg_types[] = {
1384 { "debug", do_debug, "Set debuglevel" },
1385 { "idmap", do_idmap, "Manipulate idmap cache" },
1386 { "force-election", do_election,
1387 "Force a browse election" },
1388 { "ping", do_ping, "Elicit a response" },
1389 { "profile", do_profile, "" },
1390 { "inject", do_inject_fault,
1391 "Inject a fatal signal into a running smbd"},
1392 { "stacktrace", do_daemon_stack_trace,
1393 "Display a stack trace of a daemon" },
1394 { "profilelevel", do_profilelevel, "" },
1395 { "debuglevel", do_debuglevel, "Display current debuglevels" },
1396 { "printnotify", do_printnotify, "Send a print notify message" },
1397 { "close-share", do_closeshare, "Forcibly disconnect a share" },
1398 { "kill-client-ip", do_kill_client_by_ip,
1399 "Forcibly disconnect a client with a specific IP address" },
1400 { "ip-dropped", do_ip_dropped, "Tell winbind that an IP got dropped" },
1401 { "lockretry", do_lockretry, "Force a blocking lock retry" },
1402 { "brl-revalidate", do_brl_revalidate, "Revalidate all brl entries" },
1403 { "pool-usage", do_poolusage, "Display talloc memory usage" },
1404 { "ringbuf-log", do_ringbuflog, "Display ringbuf log" },
1405 { "dmalloc-mark", do_dmalloc_mark, "" },
1406 { "dmalloc-log-changed", do_dmalloc_changed, "" },
1407 { "shutdown", do_shutdown, "Shut down daemon" },
1408 { "drvupgrade", do_drvupgrade, "Notify a printer driver has changed" },
1409 { "reload-config", do_reload_config, "Force smbd or winbindd to reload config file"},
1410 { "reload-printers", do_reload_printers, "Force smbd to reload printers"},
1411 { "nodestatus", do_nodestatus, "Ask nmbd to do a node status request"},
1412 { "online", do_winbind_online, "Ask winbind to go into online state"},
1413 { "offline", do_winbind_offline, "Ask winbind to go into offline state"},
1414 { "onlinestatus", do_winbind_onlinestatus, "Request winbind online status"},
1415 { "validate-cache" , do_winbind_validate_cache,
1416 "Validate winbind's credential cache" },
1417 { "dump-domain-list", do_winbind_dump_domain_list, "Dump winbind domain list"},
1418 { "disconnect-dc", do_msg_disconnect_dc },
1419 { "notify-cleanup", do_notify_cleanup },
1420 { "num-children", do_num_children,
1421 "Print number of smbd child processes" },
1422 { "msg-cleanup", do_msg_cleanup },
1423 { "noop", do_noop, "Do nothing" },
1424 { NULL }
1427 /* Display usage information */
1429 static void usage(poptContext pc)
1431 int i;
1433 poptPrintHelp(pc, stderr, 0);
1435 fprintf(stderr, "\n");
1436 fprintf(stderr, "<destination> is one of \"nmbd\", \"smbd\", \"winbindd\" or a "
1437 "process ID\n");
1439 fprintf(stderr, "\n");
1440 fprintf(stderr, "<message-type> is one of:\n");
1442 for (i = 0; msg_types[i].name; i++)
1443 fprintf(stderr, "\t%-30s%s\n", msg_types[i].name,
1444 msg_types[i].help);
1446 fprintf(stderr, "\n");
1448 exit(1);
1451 /* Return the pid number for a string destination */
1453 static struct server_id parse_dest(struct messaging_context *msg,
1454 const char *dest)
1456 struct server_id result = {-1};
1457 pid_t pid;
1459 /* Zero is a special return value for broadcast to all processes */
1461 if (strequal(dest, "all")) {
1462 return interpret_pid(MSG_BROADCAST_PID_STR);
1465 /* Try self - useful for testing */
1467 if (strequal(dest, "self")) {
1468 return messaging_server_id(msg);
1471 /* Fix winbind typo. */
1472 if (strequal(dest, "winbind")) {
1473 dest = "winbindd";
1476 /* Check for numeric pid number */
1477 result = interpret_pid(dest);
1479 /* Zero isn't valid if not "all". */
1480 if (result.pid && procid_valid(&result)) {
1481 return result;
1484 /* Look up other destinations in pidfile directory */
1486 if ((pid = pidfile_pid(lp_pid_directory(), dest)) != 0) {
1487 return pid_to_procid(pid);
1490 fprintf(stderr,"Can't find pid for destination '%s'\n", dest);
1492 return result;
1495 /* Execute smbcontrol command */
1497 static bool do_command(struct tevent_context *ev_ctx,
1498 struct messaging_context *msg_ctx,
1499 int argc, const char **argv)
1501 const char *dest = argv[0], *command = argv[1];
1502 struct server_id pid;
1503 int i;
1505 /* Check destination */
1507 pid = parse_dest(msg_ctx, dest);
1508 if (!procid_valid(&pid)) {
1509 return False;
1512 /* Check command */
1514 for (i = 0; msg_types[i].name; i++) {
1515 if (strequal(command, msg_types[i].name))
1516 return msg_types[i].fn(ev_ctx, msg_ctx, pid,
1517 argc - 1, argv + 1);
1520 fprintf(stderr, "smbcontrol: unknown command '%s'\n", command);
1522 return False;
1525 static void smbcontrol_help(poptContext pc,
1526 enum poptCallbackReason preason,
1527 struct poptOption * poption,
1528 const char * parg,
1529 void * pdata)
1531 if (poption->shortName != '?') {
1532 poptPrintUsage(pc, stdout, 0);
1533 } else {
1534 usage(pc);
1537 exit(0);
1540 struct poptOption help_options[] = {
1541 { NULL, '\0', POPT_ARG_CALLBACK, (void *)&smbcontrol_help, '\0',
1542 NULL, NULL },
1543 { "help", '?', 0, NULL, '?', "Show this help message", NULL },
1544 { "usage", '\0', 0, NULL, 'u', "Display brief usage message", NULL },
1545 { NULL }
1548 /* Main program */
1550 int main(int argc, const char **argv)
1552 poptContext pc;
1553 int opt;
1554 struct tevent_context *evt_ctx;
1555 struct messaging_context *msg_ctx;
1557 static struct poptOption long_options[] = {
1558 /* POPT_AUTOHELP */
1559 { NULL, '\0', POPT_ARG_INCLUDE_TABLE, help_options,
1560 0, "Help options:", NULL },
1561 { "timeout", 't', POPT_ARG_INT, &timeout, 't',
1562 "Set timeout value in seconds", "TIMEOUT" },
1564 POPT_COMMON_SAMBA
1565 POPT_TABLEEND
1567 TALLOC_CTX *frame = talloc_stackframe();
1568 int ret = 0;
1570 smb_init_locale();
1572 setup_logging(argv[0], DEBUG_STDOUT);
1573 lp_set_cmdline("log level", "0");
1575 /* Parse command line arguments using popt */
1577 pc = poptGetContext(
1578 "smbcontrol", argc, (const char **)argv, long_options, 0);
1580 poptSetOtherOptionHelp(pc, "[OPTION...] <destination> <message-type> "
1581 "<parameters>");
1583 if (argc == 1)
1584 usage(pc);
1586 while ((opt = poptGetNextOpt(pc)) != -1) {
1587 switch(opt) {
1588 case 't': /* --timeout */
1589 break;
1590 default:
1591 fprintf(stderr, "Invalid option\n");
1592 poptPrintHelp(pc, stderr, 0);
1593 break;
1597 /* We should now have the remaining command line arguments in
1598 argv. The argc parameter should have been decremented to the
1599 correct value in the above switch statement. */
1601 argv = (const char **)poptGetArgs(pc);
1602 argc = 0;
1603 if (argv != NULL) {
1604 while (argv[argc] != NULL) {
1605 argc++;
1609 if (argc <= 1)
1610 usage(pc);
1612 msg_ctx = cmdline_messaging_context(get_dyn_CONFIGFILE());
1613 if (msg_ctx == NULL) {
1614 fprintf(stderr,
1615 "Could not init messaging context, not root?\n");
1616 TALLOC_FREE(frame);
1617 exit(1);
1620 evt_ctx = global_event_context();
1622 lp_load_global(get_dyn_CONFIGFILE());
1624 /* Need to invert sense of return code -- samba
1625 * routines mostly return True==1 for success, but
1626 * shell needs 0. */
1628 ret = !do_command(evt_ctx, msg_ctx, argc, argv);
1629 TALLOC_FREE(frame);
1630 return ret;