vfs_aio_fork: Use a shorter random delay
[Samba.git] / source3 / utils / smbcontrol.c
blob0f6dacce20deece5e49e0a30d24a9c69fb9f561a
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"
39 #if HAVE_LIBUNWIND_H
40 #include <libunwind.h>
41 #endif
43 #if HAVE_LIBUNWIND_PTRACE_H
44 #include <libunwind-ptrace.h>
45 #endif
47 #if HAVE_SYS_PTRACE_H
48 #include <sys/ptrace.h>
49 #endif
51 /* Default timeout value when waiting for replies (in seconds) */
53 #define DEFAULT_TIMEOUT 10
55 static int timeout = DEFAULT_TIMEOUT;
56 static int num_replies; /* Used by message callback fns */
58 /* Send a message to a destination pid. Zero means broadcast smbd. */
60 static bool send_message(struct messaging_context *msg_ctx,
61 struct server_id pid, int msg_type,
62 const void *buf, int len)
64 if (procid_to_pid(&pid) != 0)
65 return NT_STATUS_IS_OK(
66 messaging_send_buf(msg_ctx, pid, msg_type,
67 (const uint8_t *)buf, len));
69 messaging_send_all(msg_ctx, msg_type, buf, len);
71 return true;
74 static void smbcontrol_timeout(struct tevent_context *event_ctx,
75 struct tevent_timer *te,
76 struct timeval now,
77 void *private_data)
79 bool *timed_out = (bool *)private_data;
80 TALLOC_FREE(te);
81 *timed_out = True;
84 /* Wait for one or more reply messages */
86 static void wait_replies(struct tevent_context *ev_ctx,
87 struct messaging_context *msg_ctx,
88 bool multiple_replies)
90 struct tevent_timer *te;
91 bool timed_out = False;
93 te = tevent_add_timer(ev_ctx, NULL,
94 timeval_current_ofs(timeout, 0),
95 smbcontrol_timeout, (void *)&timed_out);
96 if (te == NULL) {
97 DEBUG(0, ("tevent_add_timer failed\n"));
98 return;
101 while (!timed_out) {
102 int ret;
103 if (num_replies > 0 && !multiple_replies)
104 break;
105 ret = tevent_loop_once(ev_ctx);
106 if (ret != 0) {
107 break;
112 /* Message handler callback that displays the PID and a string on stdout */
114 static void print_pid_string_cb(struct messaging_context *msg,
115 void *private_data,
116 uint32_t msg_type,
117 struct server_id pid,
118 DATA_BLOB *data)
120 struct server_id_buf pidstr;
122 printf("PID %s: %.*s", server_id_str_buf(pid, &pidstr),
123 (int)data->length, (const char *)data->data);
124 num_replies++;
127 /* Message handler callback that displays a string on stdout */
129 static void print_string_cb(struct messaging_context *msg,
130 void *private_data,
131 uint32_t msg_type,
132 struct server_id pid,
133 DATA_BLOB *data)
135 printf("%*s", (int)data->length, (const char *)data->data);
136 num_replies++;
139 /* Send no message. Useful for testing. */
141 static bool do_noop(struct tevent_context *ev_ctx,
142 struct messaging_context *msg_ctx,
143 const struct server_id pid,
144 const int argc, const char **argv)
146 if (argc != 1) {
147 fprintf(stderr, "Usage: smbcontrol <dest> noop\n");
148 return False;
151 /* Move along, nothing to see here */
153 return True;
156 /* Send a debug string */
158 static bool do_debug(struct tevent_context *ev_ctx,
159 struct messaging_context *msg_ctx,
160 const struct server_id pid,
161 const int argc, const char **argv)
163 if (argc != 2) {
164 fprintf(stderr, "Usage: smbcontrol <dest> debug "
165 "<debug-string>\n");
166 return False;
169 return send_message(msg_ctx, pid, MSG_DEBUG, argv[1],
170 strlen(argv[1]) + 1);
174 static bool do_idmap(struct tevent_context *ev,
175 struct messaging_context *msg_ctx,
176 const struct server_id pid,
177 const int argc, const char **argv)
179 static const char* usage = "Usage: "
180 "smbcontrol <dest> idmap <cmd> [arg]\n"
181 "\tcmd:"
182 "\tdelete \"UID <uid>\"|\"GID <gid>\"|<sid>\n"
183 "\t\tkill \"UID <uid>\"|\"GID <gid>\"|<sid>\n";
184 const char* arg = NULL;
185 int arglen = 0;
186 int msg_type;
188 switch (argc) {
189 case 2:
190 break;
191 case 3:
192 arg = argv[2];
193 arglen = strlen(arg) + 1;
194 break;
195 default:
196 fprintf(stderr, "%s", usage);
197 return false;
200 if (strcmp(argv[1], "delete") == 0) {
201 msg_type = ID_CACHE_DELETE;
203 else if (strcmp(argv[1], "kill") == 0) {
204 msg_type = ID_CACHE_KILL;
206 else if (strcmp(argv[1], "help") == 0) {
207 fprintf(stdout, "%s", usage);
208 return true;
210 else {
211 fprintf(stderr, "%s", usage);
212 return false;
215 return send_message(msg_ctx, pid, msg_type, arg, arglen);
219 #if defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE)
221 /* Return the name of a process given it's PID. This will only work on Linux,
222 * but that's probably moot since this whole stack tracing implementation is
223 * Linux-specific anyway.
225 static const char * procname(pid_t pid, char * buf, size_t bufsz)
227 char path[64];
228 FILE * fp;
230 snprintf(path, sizeof(path), "/proc/%llu/cmdline",
231 (unsigned long long)pid);
232 if ((fp = fopen(path, "r")) == NULL) {
233 return NULL;
236 fgets(buf, bufsz, fp);
238 fclose(fp);
239 return buf;
242 static void print_stack_trace(pid_t pid, int * count)
244 void * pinfo = NULL;
245 unw_addr_space_t aspace = NULL;
246 unw_cursor_t cursor;
247 unw_word_t ip, sp;
249 char nbuf[256];
250 unw_word_t off;
252 int ret;
254 if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) {
255 fprintf(stderr,
256 "Failed to attach to process %llu: %s\n",
257 (unsigned long long)pid, strerror(errno));
258 return;
261 /* Wait until the attach is complete. */
262 waitpid(pid, NULL, 0);
264 if (((pinfo = _UPT_create(pid)) == NULL) ||
265 ((aspace = unw_create_addr_space(&_UPT_accessors, 0)) == NULL)) {
266 /* Probably out of memory. */
267 fprintf(stderr,
268 "Unable to initialize stack unwind for process %llu\n",
269 (unsigned long long)pid);
270 goto cleanup;
273 if ((ret = unw_init_remote(&cursor, aspace, pinfo))) {
274 fprintf(stderr,
275 "Unable to unwind stack for process %llu: %s\n",
276 (unsigned long long)pid, unw_strerror(ret));
277 goto cleanup;
280 if (*count > 0) {
281 printf("\n");
284 if (procname(pid, nbuf, sizeof(nbuf))) {
285 printf("Stack trace for process %llu (%s):\n",
286 (unsigned long long)pid, nbuf);
287 } else {
288 printf("Stack trace for process %llu:\n",
289 (unsigned long long)pid);
292 while (unw_step(&cursor) > 0) {
293 ip = sp = off = 0;
294 unw_get_reg(&cursor, UNW_REG_IP, &ip);
295 unw_get_reg(&cursor, UNW_REG_SP, &sp);
297 ret = unw_get_proc_name(&cursor, nbuf, sizeof(nbuf), &off);
298 if (ret != 0 && ret != -UNW_ENOMEM) {
299 snprintf(nbuf, sizeof(nbuf), "<unknown symbol>");
301 printf(" %s + %#llx [ip=%#llx] [sp=%#llx]\n",
302 nbuf, (long long)off, (long long)ip,
303 (long long)sp);
306 (*count)++;
308 cleanup:
309 if (aspace) {
310 unw_destroy_addr_space(aspace);
313 if (pinfo) {
314 _UPT_destroy(pinfo);
317 ptrace(PTRACE_DETACH, pid, NULL, NULL);
320 static int stack_trace_server(pid_t pid, void *priv)
322 print_stack_trace(pid, (int *)priv);
323 return 0;
326 static bool do_daemon_stack_trace(struct tevent_context *ev_ctx,
327 struct messaging_context *msg_ctx,
328 const struct server_id pid,
329 const int argc, const char **argv)
331 pid_t dest;
332 int count = 0;
334 if (argc != 1) {
335 fprintf(stderr, "Usage: smbcontrol <dest> stacktrace\n");
336 return False;
339 dest = procid_to_pid(&pid);
341 if (dest != 0) {
342 /* It would be nice to be able to make sure that this PID is
343 * the PID of a smbd/winbind/nmbd process, not some random PID
344 * the user liked the look of. It doesn't seem like it's worth
345 * the effort at the moment, however.
347 print_stack_trace(dest, &count);
348 } else {
349 messaging_dgm_forall(stack_trace_server, &count);
352 return True;
355 #else /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
357 static bool do_daemon_stack_trace(struct tevent_context *ev_ctx,
358 struct messaging_context *msg_ctx,
359 const struct server_id pid,
360 const int argc, const char **argv)
362 fprintf(stderr,
363 "Daemon stack tracing is not supported on this platform\n");
364 return False;
367 #endif /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
369 /* Inject a fault (fatal signal) into a running smbd */
371 static bool do_inject_fault(struct tevent_context *ev_ctx,
372 struct messaging_context *msg_ctx,
373 const struct server_id pid,
374 const int argc, const char **argv)
376 if (argc != 2) {
377 fprintf(stderr, "Usage: smbcontrol <dest> inject "
378 "<bus|hup|term|internal|segv>\n");
379 return False;
382 #ifndef DEVELOPER
383 fprintf(stderr, "Fault injection is only available in "
384 "developer builds\n");
385 return False;
386 #else /* DEVELOPER */
388 int sig = 0;
390 if (strcmp(argv[1], "bus") == 0) {
391 sig = SIGBUS;
392 } else if (strcmp(argv[1], "hup") == 0) {
393 sig = SIGHUP;
394 } else if (strcmp(argv[1], "term") == 0) {
395 sig = SIGTERM;
396 } else if (strcmp(argv[1], "segv") == 0) {
397 sig = SIGSEGV;
398 } else if (strcmp(argv[1], "internal") == 0) {
399 /* Force an internal error, ie. an unclean exit. */
400 sig = -1;
401 } else {
402 fprintf(stderr, "Unknown signal name '%s'\n", argv[1]);
403 return False;
406 return send_message(msg_ctx, pid, MSG_SMB_INJECT_FAULT,
407 &sig, sizeof(int));
409 #endif /* DEVELOPER */
412 /* Force a browser election */
414 static bool do_election(struct tevent_context *ev_ctx,
415 struct messaging_context *msg_ctx,
416 const struct server_id pid,
417 const int argc, const char **argv)
419 if (argc != 1) {
420 fprintf(stderr, "Usage: smbcontrol <dest> force-election\n");
421 return False;
424 return send_message(msg_ctx, pid, MSG_FORCE_ELECTION, NULL, 0);
427 /* Ping a samba daemon process */
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)
435 struct server_id_buf src_string;
436 printf("PONG from pid %s\n", server_id_str_buf(pid, &src_string));
437 num_replies++;
440 static bool do_ping(struct tevent_context *ev_ctx,
441 struct messaging_context *msg_ctx,
442 const struct server_id pid,
443 const int argc, const char **argv)
445 if (argc != 1) {
446 fprintf(stderr, "Usage: smbcontrol <dest> ping\n");
447 return False;
450 /* Send a message and register our interest in a reply */
452 if (!send_message(msg_ctx, pid, MSG_PING, NULL, 0))
453 return False;
455 messaging_register(msg_ctx, NULL, MSG_PONG, pong_cb);
457 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
459 /* No replies were received within the timeout period */
461 if (num_replies == 0)
462 printf("No replies received\n");
464 messaging_deregister(msg_ctx, MSG_PONG, NULL);
466 return num_replies;
469 /* Set profiling options */
471 static bool do_profile(struct tevent_context *ev_ctx,
472 struct messaging_context *msg_ctx,
473 const struct server_id pid,
474 const int argc, const char **argv)
476 int v;
478 if (argc != 2) {
479 fprintf(stderr, "Usage: smbcontrol <dest> profile "
480 "<off|count|on|flush>\n");
481 return False;
484 if (strcmp(argv[1], "off") == 0) {
485 v = 0;
486 } else if (strcmp(argv[1], "count") == 0) {
487 v = 1;
488 } else if (strcmp(argv[1], "on") == 0) {
489 v = 2;
490 } else if (strcmp(argv[1], "flush") == 0) {
491 v = 3;
492 } else {
493 fprintf(stderr, "Unknown profile command '%s'\n", argv[1]);
494 return False;
497 return send_message(msg_ctx, pid, MSG_PROFILE, &v, sizeof(int));
500 /* Return the profiling level */
502 static void profilelevel_cb(struct messaging_context *msg_ctx,
503 void *private_data,
504 uint32_t msg_type,
505 struct server_id pid,
506 DATA_BLOB *data)
508 int level;
509 const char *s;
511 num_replies++;
513 if (data->length != sizeof(int)) {
514 fprintf(stderr, "invalid message length %ld returned\n",
515 (unsigned long)data->length);
516 return;
519 memcpy(&level, data->data, sizeof(int));
521 switch (level) {
522 case 0:
523 s = "not enabled";
524 break;
525 case 1:
526 s = "off";
527 break;
528 case 3:
529 s = "count only";
530 break;
531 case 7:
532 s = "count and time";
533 break;
534 default:
535 s = "BOGUS";
536 break;
539 printf("Profiling %s on pid %u\n",s,(unsigned int)procid_to_pid(&pid));
542 static void profilelevel_rqst(struct messaging_context *msg_ctx,
543 void *private_data,
544 uint32_t msg_type,
545 struct server_id pid,
546 DATA_BLOB *data)
548 int v = 0;
550 /* Send back a dummy reply */
552 send_message(msg_ctx, pid, MSG_PROFILELEVEL, &v, sizeof(int));
555 static bool do_profilelevel(struct tevent_context *ev_ctx,
556 struct messaging_context *msg_ctx,
557 const struct server_id pid,
558 const int argc, const char **argv)
560 if (argc != 1) {
561 fprintf(stderr, "Usage: smbcontrol <dest> profilelevel\n");
562 return False;
565 /* Send a message and register our interest in a reply */
567 if (!send_message(msg_ctx, pid, MSG_REQ_PROFILELEVEL, NULL, 0))
568 return False;
570 messaging_register(msg_ctx, NULL, MSG_PROFILELEVEL, profilelevel_cb);
571 messaging_register(msg_ctx, NULL, MSG_REQ_PROFILELEVEL,
572 profilelevel_rqst);
574 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
576 /* No replies were received within the timeout period */
578 if (num_replies == 0)
579 printf("No replies received\n");
581 messaging_deregister(msg_ctx, MSG_PROFILE, NULL);
583 return num_replies;
586 /* Display debug level settings */
588 static bool do_debuglevel(struct tevent_context *ev_ctx,
589 struct messaging_context *msg_ctx,
590 const struct server_id pid,
591 const int argc, const char **argv)
593 if (argc != 1) {
594 fprintf(stderr, "Usage: smbcontrol <dest> debuglevel\n");
595 return False;
598 /* Send a message and register our interest in a reply */
600 if (!send_message(msg_ctx, pid, MSG_REQ_DEBUGLEVEL, NULL, 0))
601 return False;
603 messaging_register(msg_ctx, NULL, MSG_DEBUGLEVEL, print_pid_string_cb);
605 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
607 /* No replies were received within the timeout period */
609 if (num_replies == 0)
610 printf("No replies received\n");
612 messaging_deregister(msg_ctx, MSG_DEBUGLEVEL, NULL);
614 return num_replies;
617 /* Send a print notify message */
619 static bool do_printnotify(struct tevent_context *ev_ctx,
620 struct messaging_context *msg_ctx,
621 const struct server_id pid,
622 const int argc, const char **argv)
624 const char *cmd;
626 /* Check for subcommand */
628 if (argc == 1) {
629 fprintf(stderr, "Must specify subcommand:\n");
630 fprintf(stderr, "\tqueuepause <printername>\n");
631 fprintf(stderr, "\tqueueresume <printername>\n");
632 fprintf(stderr, "\tjobpause <printername> <unix jobid>\n");
633 fprintf(stderr, "\tjobresume <printername> <unix jobid>\n");
634 fprintf(stderr, "\tjobdelete <printername> <unix jobid>\n");
635 fprintf(stderr, "\tprinter <printername> <comment|port|"
636 "driver> <value>\n");
638 return False;
641 cmd = argv[1];
643 if (strcmp(cmd, "queuepause") == 0) {
645 if (argc != 3) {
646 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
647 " queuepause <printername>\n");
648 return False;
651 notify_printer_status_byname(ev_ctx, msg_ctx, argv[2],
652 PRINTER_STATUS_PAUSED);
654 goto send;
656 } else if (strcmp(cmd, "queueresume") == 0) {
658 if (argc != 3) {
659 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
660 " queuereume <printername>\n");
661 return False;
664 notify_printer_status_byname(ev_ctx, msg_ctx, argv[2],
665 PRINTER_STATUS_OK);
667 goto send;
669 } else if (strcmp(cmd, "jobpause") == 0) {
670 int jobid;
672 if (argc != 4) {
673 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
674 " jobpause <printername> <unix-jobid>\n");
675 return False;
678 jobid = atoi(argv[3]);
680 notify_job_status_byname(
681 ev_ctx, msg_ctx,
682 argv[2], jobid, JOB_STATUS_PAUSED,
683 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
685 goto send;
687 } else if (strcmp(cmd, "jobresume") == 0) {
688 int jobid;
690 if (argc != 4) {
691 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
692 " jobpause <printername> <unix-jobid>\n");
693 return False;
696 jobid = atoi(argv[3]);
698 notify_job_status_byname(
699 ev_ctx, msg_ctx,
700 argv[2], jobid, JOB_STATUS_QUEUED,
701 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
703 goto send;
705 } else if (strcmp(cmd, "jobdelete") == 0) {
706 int jobid;
708 if (argc != 4) {
709 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
710 " jobpause <printername> <unix-jobid>\n");
711 return False;
714 jobid = atoi(argv[3]);
716 notify_job_status_byname(
717 ev_ctx, msg_ctx,
718 argv[2], jobid, JOB_STATUS_DELETING,
719 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
721 notify_job_status_byname(
722 ev_ctx, msg_ctx,
723 argv[2], jobid, JOB_STATUS_DELETING|
724 JOB_STATUS_DELETED,
725 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
727 goto send;
729 } else if (strcmp(cmd, "printer") == 0) {
730 uint32_t attribute;
732 if (argc != 5) {
733 fprintf(stderr, "Usage: smbcontrol <dest> printnotify "
734 "printer <printername> <comment|port|driver> "
735 "<value>\n");
736 return False;
739 if (strcmp(argv[3], "comment") == 0) {
740 attribute = PRINTER_NOTIFY_FIELD_COMMENT;
741 } else if (strcmp(argv[3], "port") == 0) {
742 attribute = PRINTER_NOTIFY_FIELD_PORT_NAME;
743 } else if (strcmp(argv[3], "driver") == 0) {
744 attribute = PRINTER_NOTIFY_FIELD_DRIVER_NAME;
745 } else {
746 fprintf(stderr, "Invalid printer command '%s'\n",
747 argv[3]);
748 return False;
751 notify_printer_byname(ev_ctx, msg_ctx, argv[2], attribute,
752 discard_const_p(char, argv[4]));
754 goto send;
757 fprintf(stderr, "Invalid subcommand '%s'\n", cmd);
758 return False;
760 send:
761 print_notify_send_messages(msg_ctx, 0);
762 return True;
765 /* Close a share */
767 static bool do_closeshare(struct tevent_context *ev_ctx,
768 struct messaging_context *msg_ctx,
769 const struct server_id pid,
770 const int argc, const char **argv)
772 if (argc != 2) {
773 fprintf(stderr, "Usage: smbcontrol <dest> close-share "
774 "<sharename>\n");
775 return False;
778 return send_message(msg_ctx, pid, MSG_SMB_FORCE_TDIS, argv[1],
779 strlen(argv[1]) + 1);
782 /* Kill a client by IP address */
783 static bool do_kill_client_by_ip(struct tevent_context *ev_ctx,
784 struct messaging_context *msg_ctx,
785 const struct server_id pid,
786 const int argc, const char **argv)
788 if (argc != 2) {
789 fprintf(stderr, "Usage: smbcontrol <dest> kill-client-ip "
790 "<IP address>\n");
791 return false;
794 if (!is_ipaddress_v4(argv[1]) && !is_ipaddress_v6(argv[1])) {
795 fprintf(stderr, "%s is not a valid IP address!\n", argv[1]);
796 return false;
799 return send_message(msg_ctx, pid, MSG_SMB_KILL_CLIENT_IP,
800 argv[1], strlen(argv[1]) + 1);
803 /* Tell winbindd an IP got dropped */
805 static bool do_ip_dropped(struct tevent_context *ev_ctx,
806 struct messaging_context *msg_ctx,
807 const struct server_id pid,
808 const int argc, const char **argv)
810 if (argc != 2) {
811 fprintf(stderr, "Usage: smbcontrol <dest> ip-dropped "
812 "<ip-address>\n");
813 return False;
816 return send_message(msg_ctx, pid, MSG_WINBIND_IP_DROPPED, argv[1],
817 strlen(argv[1]) + 1);
820 /* force a blocking lock retry */
822 static bool do_lockretry(struct tevent_context *ev_ctx,
823 struct messaging_context *msg_ctx,
824 const struct server_id pid,
825 const int argc, const char **argv)
827 if (argc != 1) {
828 fprintf(stderr, "Usage: smbcontrol <dest> lockretry\n");
829 return False;
832 return send_message(msg_ctx, pid, MSG_SMB_UNLOCK, NULL, 0);
835 /* force a validation of all brl entries, including re-sends. */
837 static bool do_brl_revalidate(struct tevent_context *ev_ctx,
838 struct messaging_context *msg_ctx,
839 const struct server_id pid,
840 const int argc, const char **argv)
842 if (argc != 1) {
843 fprintf(stderr, "Usage: smbcontrol <dest> brl-revalidate\n");
844 return False;
847 return send_message(msg_ctx, pid, MSG_SMB_BRL_VALIDATE, NULL, 0);
850 /* Display talloc pool usage */
852 static bool do_poolusage(struct tevent_context *ev_ctx,
853 struct messaging_context *msg_ctx,
854 const struct server_id pid,
855 const int argc, const char **argv)
857 if (argc != 1) {
858 fprintf(stderr, "Usage: smbcontrol <dest> pool-usage\n");
859 return False;
862 messaging_register(msg_ctx, NULL, MSG_POOL_USAGE, print_string_cb);
864 /* Send a message and register our interest in a reply */
866 if (!send_message(msg_ctx, pid, MSG_REQ_POOL_USAGE, NULL, 0))
867 return False;
869 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
871 /* No replies were received within the timeout period */
873 if (num_replies == 0)
874 printf("No replies received\n");
876 messaging_deregister(msg_ctx, MSG_POOL_USAGE, NULL);
878 return num_replies;
881 /* Fetch and print the ringbuf log */
883 static void print_ringbuf_log_cb(struct messaging_context *msg,
884 void *private_data,
885 uint32_t msg_type,
886 struct server_id pid,
887 DATA_BLOB *data)
889 printf("%s", (const char *)data->data);
890 num_replies++;
893 static bool do_ringbuflog(struct tevent_context *ev_ctx,
894 struct messaging_context *msg_ctx,
895 const struct server_id pid,
896 const int argc, const char **argv)
898 if (argc != 1) {
899 fprintf(stderr, "Usage: smbcontrol <dest> ringbuf-log\n");
900 return false;
903 messaging_register(msg_ctx, NULL, MSG_RINGBUF_LOG,
904 print_ringbuf_log_cb);
906 /* Send a message and register our interest in a reply */
908 if (!send_message(msg_ctx, pid, MSG_REQ_RINGBUF_LOG, NULL, 0)) {
909 return false;
912 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
914 /* No replies were received within the timeout period */
916 if (num_replies == 0) {
917 printf("No replies received\n");
920 messaging_deregister(msg_ctx, MSG_RINGBUF_LOG, NULL);
922 return num_replies != 0;
925 /* Perform a dmalloc mark */
927 static bool do_dmalloc_mark(struct tevent_context *ev_ctx,
928 struct messaging_context *msg_ctx,
929 const struct server_id pid,
930 const int argc, const char **argv)
932 if (argc != 1) {
933 fprintf(stderr, "Usage: smbcontrol <dest> dmalloc-mark\n");
934 return False;
937 return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_MARK, NULL, 0);
940 /* Perform a dmalloc changed */
942 static bool do_dmalloc_changed(struct tevent_context *ev_ctx,
943 struct messaging_context *msg_ctx,
944 const struct server_id pid,
945 const int argc, const char **argv)
947 if (argc != 1) {
948 fprintf(stderr, "Usage: smbcontrol <dest> "
949 "dmalloc-log-changed\n");
950 return False;
953 return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_LOG_CHANGED,
954 NULL, 0);
957 static void print_uint32_cb(struct messaging_context *msg, void *private_data,
958 uint32_t msg_type, struct server_id pid,
959 DATA_BLOB *data)
961 uint32_t num_children;
963 if (data->length != sizeof(uint32_t)) {
964 printf("Invalid response: %d bytes long\n",
965 (int)data->length);
966 goto done;
968 num_children = IVAL(data->data, 0);
969 printf("%u children\n", (unsigned)num_children);
970 done:
971 num_replies++;
974 static bool do_num_children(struct tevent_context *ev_ctx,
975 struct messaging_context *msg_ctx,
976 const struct server_id pid,
977 const int argc, const char **argv)
979 if (argc != 1) {
980 fprintf(stderr, "Usage: smbcontrol <dest> num-children\n");
981 return False;
984 messaging_register(msg_ctx, NULL, MSG_SMB_NUM_CHILDREN,
985 print_uint32_cb);
987 /* Send a message and register our interest in a reply */
989 if (!send_message(msg_ctx, pid, MSG_SMB_TELL_NUM_CHILDREN, NULL, 0))
990 return false;
992 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
994 /* No replies were received within the timeout period */
996 if (num_replies == 0)
997 printf("No replies received\n");
999 messaging_deregister(msg_ctx, MSG_SMB_NUM_CHILDREN, NULL);
1001 return num_replies;
1004 static bool do_msg_cleanup(struct tevent_context *ev_ctx,
1005 struct messaging_context *msg_ctx,
1006 const struct server_id pid,
1007 const int argc, const char **argv)
1009 int ret;
1011 ret = messaging_cleanup(msg_ctx, pid.pid);
1013 printf("cleanup(%u) returned %s\n", (unsigned)pid.pid,
1014 ret ? strerror(ret) : "ok");
1016 return (ret == 0);
1019 /* Shutdown a server process */
1021 static bool do_shutdown(struct tevent_context *ev_ctx,
1022 struct messaging_context *msg_ctx,
1023 const struct server_id pid,
1024 const int argc, const char **argv)
1026 if (argc != 1) {
1027 fprintf(stderr, "Usage: smbcontrol <dest> shutdown\n");
1028 return False;
1031 return send_message(msg_ctx, pid, MSG_SHUTDOWN, NULL, 0);
1034 /* Notify a driver upgrade */
1036 static bool do_drvupgrade(struct tevent_context *ev_ctx,
1037 struct messaging_context *msg_ctx,
1038 const struct server_id pid,
1039 const int argc, const char **argv)
1041 if (argc != 2) {
1042 fprintf(stderr, "Usage: smbcontrol <dest> drvupgrade "
1043 "<driver-name>\n");
1044 return False;
1047 return send_message(msg_ctx, pid, MSG_PRINTER_DRVUPGRADE, argv[1],
1048 strlen(argv[1]) + 1);
1051 static bool do_winbind_online(struct tevent_context *ev_ctx,
1052 struct messaging_context *msg_ctx,
1053 const struct server_id pid,
1054 const int argc, const char **argv)
1056 TDB_CONTEXT *tdb;
1057 char *db_path;
1059 if (argc != 1) {
1060 fprintf(stderr, "Usage: smbcontrol winbindd online\n");
1061 return False;
1064 db_path = state_path("winbindd_cache.tdb");
1065 if (db_path == NULL) {
1066 return false;
1069 /* Remove the entry in the winbindd_cache tdb to tell a later
1070 starting winbindd that we're online. */
1072 tdb = tdb_open_log(db_path, 0, TDB_DEFAULT, O_RDWR, 0600);
1073 if (!tdb) {
1074 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
1075 db_path);
1076 TALLOC_FREE(db_path);
1077 return False;
1080 TALLOC_FREE(db_path);
1081 tdb_delete_bystring(tdb, "WINBINDD_OFFLINE");
1082 tdb_close(tdb);
1084 return send_message(msg_ctx, pid, MSG_WINBIND_ONLINE, NULL, 0);
1087 static bool do_winbind_offline(struct tevent_context *ev_ctx,
1088 struct messaging_context *msg_ctx,
1089 const struct server_id pid,
1090 const int argc, const char **argv)
1092 TDB_CONTEXT *tdb;
1093 bool ret = False;
1094 int retry = 0;
1095 char *db_path;
1097 if (argc != 1) {
1098 fprintf(stderr, "Usage: smbcontrol winbindd offline\n");
1099 return False;
1102 db_path = state_path("winbindd_cache.tdb");
1103 if (db_path == NULL) {
1104 return false;
1107 /* Create an entry in the winbindd_cache tdb to tell a later
1108 starting winbindd that we're offline. We may actually create
1109 it here... */
1111 tdb = tdb_open_log(db_path,
1112 WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
1113 TDB_DEFAULT|TDB_INCOMPATIBLE_HASH /* TDB_CLEAR_IF_FIRST */,
1114 O_RDWR|O_CREAT, 0600);
1116 if (!tdb) {
1117 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
1118 db_path);
1119 TALLOC_FREE(db_path);
1120 return False;
1122 TALLOC_FREE(db_path);
1124 /* There's a potential race condition that if a child
1125 winbindd detects a domain is online at the same time
1126 we're trying to tell it to go offline that it might
1127 delete the record we add between us adding it and
1128 sending the message. Minimize this by retrying up to
1129 5 times. */
1131 for (retry = 0; retry < 5; retry++) {
1132 uint8_t buf[4];
1133 TDB_DATA d = { .dptr = buf, .dsize = sizeof(buf) };
1135 SIVAL(buf, 0, time(NULL));
1137 tdb_store_bystring(tdb, "WINBINDD_OFFLINE", d, TDB_INSERT);
1139 ret = send_message(msg_ctx, pid, MSG_WINBIND_OFFLINE,
1140 NULL, 0);
1142 /* Check that the entry "WINBINDD_OFFLINE" still exists. */
1143 d = tdb_fetch_bystring( tdb, "WINBINDD_OFFLINE" );
1145 if (!d.dptr || d.dsize != 4) {
1146 SAFE_FREE(d.dptr);
1147 DEBUG(10,("do_winbind_offline: offline state not set - retrying.\n"));
1148 } else {
1149 SAFE_FREE(d.dptr);
1150 break;
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 struct server_id myid;
1165 myid = messaging_server_id(msg_ctx);
1167 if (argc != 1) {
1168 fprintf(stderr, "Usage: smbcontrol winbindd onlinestatus\n");
1169 return False;
1172 messaging_register(msg_ctx, NULL, MSG_WINBIND_ONLINESTATUS,
1173 print_pid_string_cb);
1175 if (!send_message(msg_ctx, pid, MSG_WINBIND_ONLINESTATUS, &myid,
1176 sizeof(myid)))
1177 return False;
1179 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
1181 /* No replies were received within the timeout period */
1183 if (num_replies == 0)
1184 printf("No replies received\n");
1186 messaging_deregister(msg_ctx, MSG_WINBIND_ONLINESTATUS, NULL);
1188 return num_replies;
1191 static bool do_dump_event_list(struct tevent_context *ev_ctx,
1192 struct messaging_context *msg_ctx,
1193 const struct server_id pid,
1194 const int argc, const char **argv)
1196 if (argc != 1) {
1197 fprintf(stderr, "Usage: smbcontrol <dest> dump-event-list\n");
1198 return False;
1201 return send_message(msg_ctx, pid, MSG_DUMP_EVENT_LIST, NULL, 0);
1204 static bool do_winbind_dump_domain_list(struct tevent_context *ev_ctx,
1205 struct messaging_context *msg_ctx,
1206 const struct server_id pid,
1207 const int argc, const char **argv)
1209 const char *domain = NULL;
1210 int domain_len = 0;
1211 struct server_id myid;
1212 uint8_t *buf = NULL;
1213 int buf_len = 0;
1215 myid = messaging_server_id(msg_ctx);
1217 if (argc < 1 || argc > 2) {
1218 fprintf(stderr, "Usage: smbcontrol <dest> dump-domain-list "
1219 "<domain>\n");
1220 return false;
1223 if (argc == 2) {
1224 domain = argv[1];
1225 domain_len = strlen(argv[1]) + 1;
1228 messaging_register(msg_ctx, NULL, MSG_WINBIND_DUMP_DOMAIN_LIST,
1229 print_pid_string_cb);
1231 buf_len = sizeof(myid)+domain_len;
1232 buf = SMB_MALLOC_ARRAY(uint8_t, buf_len);
1233 if (!buf) {
1234 return false;
1237 memcpy(buf, &myid, sizeof(myid));
1238 memcpy(&buf[sizeof(myid)], domain, domain_len);
1240 if (!send_message(msg_ctx, pid, MSG_WINBIND_DUMP_DOMAIN_LIST,
1241 buf, buf_len))
1243 SAFE_FREE(buf);
1244 return false;
1247 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
1249 /* No replies were received within the timeout period */
1251 SAFE_FREE(buf);
1252 if (num_replies == 0) {
1253 printf("No replies received\n");
1256 messaging_deregister(msg_ctx, MSG_WINBIND_DUMP_DOMAIN_LIST, NULL);
1258 return num_replies;
1261 static void winbind_validate_cache_cb(struct messaging_context *msg,
1262 void *private_data,
1263 uint32_t msg_type,
1264 struct server_id pid,
1265 DATA_BLOB *data)
1267 struct server_id_buf src_string;
1268 printf("Winbindd cache is %svalid. (answer from pid %s)\n",
1269 (*(data->data) == 0 ? "" : "NOT "),
1270 server_id_str_buf(pid, &src_string));
1271 num_replies++;
1274 static bool do_winbind_validate_cache(struct tevent_context *ev_ctx,
1275 struct messaging_context *msg_ctx,
1276 const struct server_id pid,
1277 const int argc, const char **argv)
1279 struct server_id myid;
1281 myid = messaging_server_id(msg_ctx);
1283 if (argc != 1) {
1284 fprintf(stderr, "Usage: smbcontrol winbindd validate-cache\n");
1285 return False;
1288 messaging_register(msg_ctx, NULL, MSG_WINBIND_VALIDATE_CACHE,
1289 winbind_validate_cache_cb);
1291 if (!send_message(msg_ctx, pid, MSG_WINBIND_VALIDATE_CACHE, &myid,
1292 sizeof(myid))) {
1293 return False;
1296 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
1298 if (num_replies == 0) {
1299 printf("No replies received\n");
1302 messaging_deregister(msg_ctx, MSG_WINBIND_VALIDATE_CACHE, NULL);
1304 return num_replies;
1307 static bool do_reload_config(struct tevent_context *ev_ctx,
1308 struct messaging_context *msg_ctx,
1309 const struct server_id pid,
1310 const int argc, const char **argv)
1312 if (argc != 1) {
1313 fprintf(stderr, "Usage: smbcontrol <dest> reload-config\n");
1314 return False;
1317 return send_message(msg_ctx, pid, MSG_SMB_CONF_UPDATED, NULL, 0);
1320 static bool do_reload_printers(struct tevent_context *ev_ctx,
1321 struct messaging_context *msg_ctx,
1322 const struct server_id pid,
1323 const int argc, const char **argv)
1325 if (argc != 1) {
1326 fprintf(stderr, "Usage: smbcontrol <dest> reload-printers\n");
1327 return False;
1330 return send_message(msg_ctx, pid, MSG_PRINTER_PCAP, NULL, 0);
1333 static void my_make_nmb_name( struct nmb_name *n, const char *name, int type)
1335 fstring unix_name;
1336 memset( (char *)n, '\0', sizeof(struct nmb_name) );
1337 fstrcpy(unix_name, name);
1338 (void)strupper_m(unix_name);
1339 push_ascii(n->name, unix_name, sizeof(n->name), STR_TERMINATE);
1340 n->name_type = (unsigned int)type & 0xFF;
1341 push_ascii(n->scope, lp_netbios_scope(), 64, STR_TERMINATE);
1344 static bool do_nodestatus(struct tevent_context *ev_ctx,
1345 struct messaging_context *msg_ctx,
1346 const struct server_id pid,
1347 const int argc, const char **argv)
1349 struct packet_struct p;
1351 if (argc != 2) {
1352 fprintf(stderr, "Usage: smbcontrol nmbd nodestatus <ip>\n");
1353 return False;
1356 ZERO_STRUCT(p);
1358 p.ip = interpret_addr2(argv[1]);
1359 p.port = 137;
1360 p.packet_type = NMB_PACKET;
1362 p.packet.nmb.header.name_trn_id = 10;
1363 p.packet.nmb.header.opcode = 0;
1364 p.packet.nmb.header.response = False;
1365 p.packet.nmb.header.nm_flags.bcast = False;
1366 p.packet.nmb.header.nm_flags.recursion_available = False;
1367 p.packet.nmb.header.nm_flags.recursion_desired = False;
1368 p.packet.nmb.header.nm_flags.trunc = False;
1369 p.packet.nmb.header.nm_flags.authoritative = False;
1370 p.packet.nmb.header.rcode = 0;
1371 p.packet.nmb.header.qdcount = 1;
1372 p.packet.nmb.header.ancount = 0;
1373 p.packet.nmb.header.nscount = 0;
1374 p.packet.nmb.header.arcount = 0;
1375 my_make_nmb_name(&p.packet.nmb.question.question_name, "*", 0x00);
1376 p.packet.nmb.question.question_type = 0x21;
1377 p.packet.nmb.question.question_class = 0x1;
1379 return send_message(msg_ctx, pid, MSG_SEND_PACKET, &p, sizeof(p));
1382 static bool do_notify_cleanup(struct tevent_context *ev_ctx,
1383 struct messaging_context *msg_ctx,
1384 const struct server_id pid,
1385 const int argc, const char **argv)
1387 if (argc != 1) {
1388 fprintf(stderr, "Usage: smbcontrol smbd notify-cleanup\n");
1389 return false;
1391 return send_message(msg_ctx, pid, MSG_SMB_NOTIFY_CLEANUP, NULL, 0);
1394 /* A list of message type supported */
1396 static const struct {
1397 const char *name; /* Option name */
1398 bool (*fn)(struct tevent_context *ev_ctx,
1399 struct messaging_context *msg_ctx,
1400 const struct server_id pid,
1401 const int argc, const char **argv);
1402 const char *help; /* Short help text */
1403 } msg_types[] = {
1404 { "debug", do_debug, "Set debuglevel" },
1405 { "idmap", do_idmap, "Manipulate idmap cache" },
1406 { "force-election", do_election,
1407 "Force a browse election" },
1408 { "ping", do_ping, "Elicit a response" },
1409 { "profile", do_profile, "" },
1410 { "inject", do_inject_fault,
1411 "Inject a fatal signal into a running smbd"},
1412 { "stacktrace", do_daemon_stack_trace,
1413 "Display a stack trace of a daemon" },
1414 { "profilelevel", do_profilelevel, "" },
1415 { "debuglevel", do_debuglevel, "Display current debuglevels" },
1416 { "printnotify", do_printnotify, "Send a print notify message" },
1417 { "close-share", do_closeshare, "Forcibly disconnect a share" },
1418 { "kill-client-ip", do_kill_client_by_ip,
1419 "Forcibly disconnect a client with a specific IP address" },
1420 { "ip-dropped", do_ip_dropped, "Tell winbind that an IP got dropped" },
1421 { "lockretry", do_lockretry, "Force a blocking lock retry" },
1422 { "brl-revalidate", do_brl_revalidate, "Revalidate all brl entries" },
1423 { "pool-usage", do_poolusage, "Display talloc memory usage" },
1424 { "ringbuf-log", do_ringbuflog, "Display ringbuf log" },
1425 { "dmalloc-mark", do_dmalloc_mark, "" },
1426 { "dmalloc-log-changed", do_dmalloc_changed, "" },
1427 { "shutdown", do_shutdown, "Shut down daemon" },
1428 { "drvupgrade", do_drvupgrade, "Notify a printer driver has changed" },
1429 { "reload-config", do_reload_config, "Force smbd or winbindd to reload config file"},
1430 { "reload-printers", do_reload_printers, "Force smbd to reload printers"},
1431 { "nodestatus", do_nodestatus, "Ask nmbd to do a node status request"},
1432 { "online", do_winbind_online, "Ask winbind to go into online state"},
1433 { "offline", do_winbind_offline, "Ask winbind to go into offline state"},
1434 { "onlinestatus", do_winbind_onlinestatus, "Request winbind online status"},
1435 { "dump-event-list", do_dump_event_list, "Dump event list"},
1436 { "validate-cache" , do_winbind_validate_cache,
1437 "Validate winbind's credential cache" },
1438 { "dump-domain-list", do_winbind_dump_domain_list, "Dump winbind domain list"},
1439 { "notify-cleanup", do_notify_cleanup },
1440 { "num-children", do_num_children,
1441 "Print number of smbd child processes" },
1442 { "msg-cleanup", do_msg_cleanup },
1443 { "noop", do_noop, "Do nothing" },
1444 { NULL }
1447 /* Display usage information */
1449 static void usage(poptContext pc)
1451 int i;
1453 poptPrintHelp(pc, stderr, 0);
1455 fprintf(stderr, "\n");
1456 fprintf(stderr, "<destination> is one of \"nmbd\", \"smbd\", \"winbindd\" or a "
1457 "process ID\n");
1459 fprintf(stderr, "\n");
1460 fprintf(stderr, "<message-type> is one of:\n");
1462 for (i = 0; msg_types[i].name; i++)
1463 fprintf(stderr, "\t%-30s%s\n", msg_types[i].name,
1464 msg_types[i].help);
1466 fprintf(stderr, "\n");
1468 exit(1);
1471 /* Return the pid number for a string destination */
1473 static struct server_id parse_dest(struct messaging_context *msg,
1474 const char *dest)
1476 struct server_id result = {-1};
1477 pid_t pid;
1479 /* Zero is a special return value for broadcast to all processes */
1481 if (strequal(dest, "all")) {
1482 return interpret_pid(MSG_BROADCAST_PID_STR);
1485 /* Try self - useful for testing */
1487 if (strequal(dest, "self")) {
1488 return messaging_server_id(msg);
1491 /* Fix winbind typo. */
1492 if (strequal(dest, "winbind")) {
1493 dest = "winbindd";
1496 /* Check for numeric pid number */
1497 result = interpret_pid(dest);
1499 /* Zero isn't valid if not "all". */
1500 if (result.pid && procid_valid(&result)) {
1501 return result;
1504 /* Look up other destinations in pidfile directory */
1506 if ((pid = pidfile_pid(lp_pid_directory(), dest)) != 0) {
1507 return pid_to_procid(pid);
1510 fprintf(stderr,"Can't find pid for destination '%s'\n", dest);
1512 return result;
1515 /* Execute smbcontrol command */
1517 static bool do_command(struct tevent_context *ev_ctx,
1518 struct messaging_context *msg_ctx,
1519 int argc, const char **argv)
1521 const char *dest = argv[0], *command = argv[1];
1522 struct server_id pid;
1523 int i;
1525 /* Check destination */
1527 pid = parse_dest(msg_ctx, dest);
1528 if (!procid_valid(&pid)) {
1529 return False;
1532 /* Check command */
1534 for (i = 0; msg_types[i].name; i++) {
1535 if (strequal(command, msg_types[i].name))
1536 return msg_types[i].fn(ev_ctx, msg_ctx, pid,
1537 argc - 1, argv + 1);
1540 fprintf(stderr, "smbcontrol: unknown command '%s'\n", command);
1542 return False;
1545 static void smbcontrol_help(poptContext pc,
1546 enum poptCallbackReason preason,
1547 struct poptOption * poption,
1548 const char * parg,
1549 void * pdata)
1551 if (poption->shortName != '?') {
1552 poptPrintUsage(pc, stdout, 0);
1553 } else {
1554 usage(pc);
1557 exit(0);
1560 struct poptOption help_options[] = {
1561 { NULL, '\0', POPT_ARG_CALLBACK, (void *)&smbcontrol_help, '\0',
1562 NULL, NULL },
1563 { "help", '?', 0, NULL, '?', "Show this help message", NULL },
1564 { "usage", '\0', 0, NULL, 'u', "Display brief usage message", NULL },
1565 { NULL }
1568 /* Main program */
1570 int main(int argc, const char **argv)
1572 poptContext pc;
1573 int opt;
1574 struct tevent_context *evt_ctx;
1575 struct messaging_context *msg_ctx;
1577 static struct poptOption long_options[] = {
1578 /* POPT_AUTOHELP */
1579 { NULL, '\0', POPT_ARG_INCLUDE_TABLE, help_options,
1580 0, "Help options:", NULL },
1581 { "timeout", 't', POPT_ARG_INT, &timeout, 't',
1582 "Set timeout value in seconds", "TIMEOUT" },
1584 POPT_COMMON_SAMBA
1585 POPT_TABLEEND
1587 TALLOC_CTX *frame = talloc_stackframe();
1588 int ret = 0;
1590 smb_init_locale();
1592 setup_logging(argv[0], DEBUG_STDOUT);
1593 lp_set_cmdline("log level", "0");
1595 /* Parse command line arguments using popt */
1597 pc = poptGetContext(
1598 "smbcontrol", argc, (const char **)argv, long_options, 0);
1600 poptSetOtherOptionHelp(pc, "[OPTION...] <destination> <message-type> "
1601 "<parameters>");
1603 if (argc == 1)
1604 usage(pc);
1606 while ((opt = poptGetNextOpt(pc)) != -1) {
1607 switch(opt) {
1608 case 't': /* --timeout */
1609 break;
1610 default:
1611 fprintf(stderr, "Invalid option\n");
1612 poptPrintHelp(pc, stderr, 0);
1613 break;
1617 /* We should now have the remaining command line arguments in
1618 argv. The argc parameter should have been decremented to the
1619 correct value in the above switch statement. */
1621 argv = (const char **)poptGetArgs(pc);
1622 argc = 0;
1623 if (argv != NULL) {
1624 while (argv[argc] != NULL) {
1625 argc++;
1629 if (argc <= 1)
1630 usage(pc);
1632 lp_load_global(get_dyn_CONFIGFILE());
1634 /* Need to invert sense of return code -- samba
1635 * routines mostly return True==1 for success, but
1636 * shell needs 0. */
1638 if (!(evt_ctx = samba_tevent_context_init(NULL)) ||
1639 !(msg_ctx = messaging_init(NULL, evt_ctx))) {
1640 fprintf(stderr, "could not init messaging context\n");
1641 TALLOC_FREE(frame);
1642 exit(1);
1645 ret = !do_command(evt_ctx, msg_ctx, argc, argv);
1646 TALLOC_FREE(msg_ctx);
1647 TALLOC_FREE(frame);
1648 return ret;