VERSION: Disable GIT_SNAPSHOT for the 4.11.8 release.
[Samba.git] / source3 / utils / smbcontrol.c
blob1a8e59a95e2095ca653ae72e51a3fac65f7da675
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 #ifdef HAVE_LIBUNWIND_H
41 #include <libunwind.h>
42 #endif
44 #ifdef HAVE_LIBUNWIND_PTRACE_H
45 #include <libunwind-ptrace.h>
46 #endif
48 #ifdef 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 #if !defined(DEVELOPER) && !defined(ENABLE_SELFTEST)
384 fprintf(stderr, "Fault injection is only available in "
385 "developer and self test builds\n");
386 return False;
387 #else /* DEVELOPER || ENABLE_SELFTEST */
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 || ENABLE_SELFTEST */
413 static bool do_sleep(struct tevent_context *ev_ctx,
414 struct messaging_context *msg_ctx,
415 const struct server_id pid,
416 const int argc, const char **argv)
418 #if defined(DEVELOPER) || defined(ENABLE_SELFTEST)
419 unsigned int seconds;
420 long input;
421 const long MAX_SLEEP = 60 * 60; /* One hour maximum sleep */
422 #endif
424 if (argc != 2) {
425 fprintf(stderr, "Usage: smbcontrol <dest> sleep seconds\n");
426 return False;
429 #if !defined(DEVELOPER) && !defined(ENABLE_SELFTEST)
430 fprintf(stderr, "Sleep is only available in "
431 "developer and self test builds\n");
432 return False;
433 #else /* DEVELOPER || ENABLE_SELFTEST */
435 input = atol(argv[1]);
436 if (input < 1 || input > MAX_SLEEP) {
437 fprintf(stderr,
438 "Invalid duration for sleep '%s'\n"
439 "It should be at least 1 second and no more than %ld\n",
440 argv[1],
441 MAX_SLEEP);
442 return False;
444 seconds = input;
445 return send_message(msg_ctx, pid,
446 MSG_SMB_SLEEP,
447 &seconds,
448 sizeof(unsigned int));
449 #endif /* DEVELOPER || ENABLE_SELFTEST */
452 /* Force a browser election */
454 static bool do_election(struct tevent_context *ev_ctx,
455 struct messaging_context *msg_ctx,
456 const struct server_id pid,
457 const int argc, const char **argv)
459 if (argc != 1) {
460 fprintf(stderr, "Usage: smbcontrol <dest> force-election\n");
461 return False;
464 return send_message(msg_ctx, pid, MSG_FORCE_ELECTION, NULL, 0);
467 /* Ping a samba daemon process */
469 static void pong_cb(struct messaging_context *msg,
470 void *private_data,
471 uint32_t msg_type,
472 struct server_id pid,
473 DATA_BLOB *data)
475 struct server_id_buf src_string;
476 printf("PONG from pid %s\n", server_id_str_buf(pid, &src_string));
477 num_replies++;
480 static bool do_ping(struct tevent_context *ev_ctx,
481 struct messaging_context *msg_ctx,
482 const struct server_id pid,
483 const int argc, const char **argv)
485 if (argc != 1) {
486 fprintf(stderr, "Usage: smbcontrol <dest> ping\n");
487 return False;
490 /* Send a message and register our interest in a reply */
492 if (!send_message(msg_ctx, pid, MSG_PING, NULL, 0))
493 return False;
495 messaging_register(msg_ctx, NULL, MSG_PONG, pong_cb);
497 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
499 /* No replies were received within the timeout period */
501 if (num_replies == 0)
502 printf("No replies received\n");
504 messaging_deregister(msg_ctx, MSG_PONG, NULL);
506 return num_replies;
509 /* Set profiling options */
511 static bool do_profile(struct tevent_context *ev_ctx,
512 struct messaging_context *msg_ctx,
513 const struct server_id pid,
514 const int argc, const char **argv)
516 int v;
518 if (argc != 2) {
519 fprintf(stderr, "Usage: smbcontrol <dest> profile "
520 "<off|count|on|flush>\n");
521 return False;
524 if (strcmp(argv[1], "off") == 0) {
525 v = 0;
526 } else if (strcmp(argv[1], "count") == 0) {
527 v = 1;
528 } else if (strcmp(argv[1], "on") == 0) {
529 v = 2;
530 } else if (strcmp(argv[1], "flush") == 0) {
531 v = 3;
532 } else {
533 fprintf(stderr, "Unknown profile command '%s'\n", argv[1]);
534 return False;
537 return send_message(msg_ctx, pid, MSG_PROFILE, &v, sizeof(int));
540 /* Return the profiling level */
542 static void profilelevel_cb(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 level;
549 const char *s;
551 num_replies++;
553 if (data->length != sizeof(int)) {
554 fprintf(stderr, "invalid message length %ld returned\n",
555 (unsigned long)data->length);
556 return;
559 memcpy(&level, data->data, sizeof(int));
561 switch (level) {
562 case 0:
563 s = "not enabled";
564 break;
565 case 1:
566 s = "off";
567 break;
568 case 3:
569 s = "count only";
570 break;
571 case 7:
572 s = "count and time";
573 break;
574 default:
575 s = "BOGUS";
576 break;
579 printf("Profiling %s on pid %u\n",s,(unsigned int)procid_to_pid(&pid));
582 static void profilelevel_rqst(struct messaging_context *msg_ctx,
583 void *private_data,
584 uint32_t msg_type,
585 struct server_id pid,
586 DATA_BLOB *data)
588 int v = 0;
590 /* Send back a dummy reply */
592 send_message(msg_ctx, pid, MSG_PROFILELEVEL, &v, sizeof(int));
595 static bool do_profilelevel(struct tevent_context *ev_ctx,
596 struct messaging_context *msg_ctx,
597 const struct server_id pid,
598 const int argc, const char **argv)
600 if (argc != 1) {
601 fprintf(stderr, "Usage: smbcontrol <dest> profilelevel\n");
602 return False;
605 /* Send a message and register our interest in a reply */
607 if (!send_message(msg_ctx, pid, MSG_REQ_PROFILELEVEL, NULL, 0))
608 return False;
610 messaging_register(msg_ctx, NULL, MSG_PROFILELEVEL, profilelevel_cb);
611 messaging_register(msg_ctx, NULL, MSG_REQ_PROFILELEVEL,
612 profilelevel_rqst);
614 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
616 /* No replies were received within the timeout period */
618 if (num_replies == 0)
619 printf("No replies received\n");
621 messaging_deregister(msg_ctx, MSG_PROFILE, NULL);
623 return num_replies;
626 /* Display debug level settings */
628 static bool do_debuglevel(struct tevent_context *ev_ctx,
629 struct messaging_context *msg_ctx,
630 const struct server_id pid,
631 const int argc, const char **argv)
633 if (argc != 1) {
634 fprintf(stderr, "Usage: smbcontrol <dest> debuglevel\n");
635 return False;
638 /* Send a message and register our interest in a reply */
640 if (!send_message(msg_ctx, pid, MSG_REQ_DEBUGLEVEL, NULL, 0))
641 return False;
643 messaging_register(msg_ctx, NULL, MSG_DEBUGLEVEL, print_pid_string_cb);
645 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
647 /* No replies were received within the timeout period */
649 if (num_replies == 0)
650 printf("No replies received\n");
652 messaging_deregister(msg_ctx, MSG_DEBUGLEVEL, NULL);
654 return num_replies;
657 /* Send a print notify message */
659 static bool do_printnotify(struct tevent_context *ev_ctx,
660 struct messaging_context *msg_ctx,
661 const struct server_id pid,
662 const int argc, const char **argv)
664 const char *cmd;
666 /* Check for subcommand */
668 if (argc == 1) {
669 fprintf(stderr, "Must specify subcommand:\n");
670 fprintf(stderr, "\tqueuepause <printername>\n");
671 fprintf(stderr, "\tqueueresume <printername>\n");
672 fprintf(stderr, "\tjobpause <printername> <unix jobid>\n");
673 fprintf(stderr, "\tjobresume <printername> <unix jobid>\n");
674 fprintf(stderr, "\tjobdelete <printername> <unix jobid>\n");
675 fprintf(stderr, "\tprinter <printername> <comment|port|"
676 "driver> <value>\n");
678 return False;
681 cmd = argv[1];
683 if (strcmp(cmd, "queuepause") == 0) {
685 if (argc != 3) {
686 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
687 " queuepause <printername>\n");
688 return False;
691 notify_printer_status_byname(ev_ctx, msg_ctx, argv[2],
692 PRINTER_STATUS_PAUSED);
694 goto send;
696 } else if (strcmp(cmd, "queueresume") == 0) {
698 if (argc != 3) {
699 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
700 " queuereume <printername>\n");
701 return False;
704 notify_printer_status_byname(ev_ctx, msg_ctx, argv[2],
705 PRINTER_STATUS_OK);
707 goto send;
709 } else if (strcmp(cmd, "jobpause") == 0) {
710 int jobid;
712 if (argc != 4) {
713 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
714 " jobpause <printername> <unix-jobid>\n");
715 return False;
718 jobid = atoi(argv[3]);
720 notify_job_status_byname(
721 ev_ctx, msg_ctx,
722 argv[2], jobid, JOB_STATUS_PAUSED,
723 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
725 goto send;
727 } else if (strcmp(cmd, "jobresume") == 0) {
728 int jobid;
730 if (argc != 4) {
731 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
732 " jobpause <printername> <unix-jobid>\n");
733 return False;
736 jobid = atoi(argv[3]);
738 notify_job_status_byname(
739 ev_ctx, msg_ctx,
740 argv[2], jobid, JOB_STATUS_QUEUED,
741 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
743 goto send;
745 } else if (strcmp(cmd, "jobdelete") == 0) {
746 int jobid;
748 if (argc != 4) {
749 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
750 " jobpause <printername> <unix-jobid>\n");
751 return False;
754 jobid = atoi(argv[3]);
756 notify_job_status_byname(
757 ev_ctx, msg_ctx,
758 argv[2], jobid, JOB_STATUS_DELETING,
759 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
761 notify_job_status_byname(
762 ev_ctx, msg_ctx,
763 argv[2], jobid, JOB_STATUS_DELETING|
764 JOB_STATUS_DELETED,
765 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
767 goto send;
769 } else if (strcmp(cmd, "printer") == 0) {
770 uint32_t attribute;
772 if (argc != 5) {
773 fprintf(stderr, "Usage: smbcontrol <dest> printnotify "
774 "printer <printername> <comment|port|driver> "
775 "<value>\n");
776 return False;
779 if (strcmp(argv[3], "comment") == 0) {
780 attribute = PRINTER_NOTIFY_FIELD_COMMENT;
781 } else if (strcmp(argv[3], "port") == 0) {
782 attribute = PRINTER_NOTIFY_FIELD_PORT_NAME;
783 } else if (strcmp(argv[3], "driver") == 0) {
784 attribute = PRINTER_NOTIFY_FIELD_DRIVER_NAME;
785 } else {
786 fprintf(stderr, "Invalid printer command '%s'\n",
787 argv[3]);
788 return False;
791 notify_printer_byname(ev_ctx, msg_ctx, argv[2], attribute,
792 discard_const_p(char, argv[4]));
794 goto send;
797 fprintf(stderr, "Invalid subcommand '%s'\n", cmd);
798 return False;
800 send:
801 print_notify_send_messages(msg_ctx, 0);
802 return True;
805 /* Close a share */
807 static bool do_closeshare(struct tevent_context *ev_ctx,
808 struct messaging_context *msg_ctx,
809 const struct server_id pid,
810 const int argc, const char **argv)
812 if (argc != 2) {
813 fprintf(stderr, "Usage: smbcontrol <dest> close-share "
814 "<sharename>\n");
815 return False;
818 return send_message(msg_ctx, pid, MSG_SMB_FORCE_TDIS, argv[1],
819 strlen(argv[1]) + 1);
822 /* Kill a client by IP address */
823 static bool do_kill_client_by_ip(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 != 2) {
829 fprintf(stderr, "Usage: smbcontrol <dest> kill-client-ip "
830 "<IP address>\n");
831 return false;
834 if (!is_ipaddress_v4(argv[1]) && !is_ipaddress_v6(argv[1])) {
835 fprintf(stderr, "%s is not a valid IP address!\n", argv[1]);
836 return false;
839 return send_message(msg_ctx, pid, MSG_SMB_KILL_CLIENT_IP,
840 argv[1], strlen(argv[1]) + 1);
843 /* Tell winbindd an IP got dropped */
845 static bool do_ip_dropped(struct tevent_context *ev_ctx,
846 struct messaging_context *msg_ctx,
847 const struct server_id pid,
848 const int argc, const char **argv)
850 if (argc != 2) {
851 fprintf(stderr, "Usage: smbcontrol <dest> ip-dropped "
852 "<ip-address>\n");
853 return False;
856 return send_message(msg_ctx, pid, MSG_WINBIND_IP_DROPPED, argv[1],
857 strlen(argv[1]) + 1);
860 /* Display talloc pool usage */
862 static bool do_poolusage(struct tevent_context *ev_ctx,
863 struct messaging_context *msg_ctx,
864 const struct server_id pid,
865 const int argc, const char **argv)
867 if (argc != 1) {
868 fprintf(stderr, "Usage: smbcontrol <dest> pool-usage\n");
869 return False;
872 messaging_register(msg_ctx, NULL, MSG_POOL_USAGE, print_string_cb);
874 /* Send a message and register our interest in a reply */
876 if (!send_message(msg_ctx, pid, MSG_REQ_POOL_USAGE, NULL, 0))
877 return False;
879 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
881 /* No replies were received within the timeout period */
883 if (num_replies == 0)
884 printf("No replies received\n");
886 messaging_deregister(msg_ctx, MSG_POOL_USAGE, NULL);
888 return num_replies;
891 /* Fetch and print the ringbuf log */
893 static void print_ringbuf_log_cb(struct messaging_context *msg,
894 void *private_data,
895 uint32_t msg_type,
896 struct server_id pid,
897 DATA_BLOB *data)
899 printf("%s", (const char *)data->data);
900 num_replies++;
903 static bool do_ringbuflog(struct tevent_context *ev_ctx,
904 struct messaging_context *msg_ctx,
905 const struct server_id pid,
906 const int argc, const char **argv)
908 if (argc != 1) {
909 fprintf(stderr, "Usage: smbcontrol <dest> ringbuf-log\n");
910 return false;
913 messaging_register(msg_ctx, NULL, MSG_RINGBUF_LOG,
914 print_ringbuf_log_cb);
916 /* Send a message and register our interest in a reply */
918 if (!send_message(msg_ctx, pid, MSG_REQ_RINGBUF_LOG, NULL, 0)) {
919 return false;
922 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
924 /* No replies were received within the timeout period */
926 if (num_replies == 0) {
927 printf("No replies received\n");
930 messaging_deregister(msg_ctx, MSG_RINGBUF_LOG, NULL);
932 return num_replies != 0;
935 /* Perform a dmalloc mark */
937 static bool do_dmalloc_mark(struct tevent_context *ev_ctx,
938 struct messaging_context *msg_ctx,
939 const struct server_id pid,
940 const int argc, const char **argv)
942 if (argc != 1) {
943 fprintf(stderr, "Usage: smbcontrol <dest> dmalloc-mark\n");
944 return False;
947 return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_MARK, NULL, 0);
950 /* Perform a dmalloc changed */
952 static bool do_dmalloc_changed(struct tevent_context *ev_ctx,
953 struct messaging_context *msg_ctx,
954 const struct server_id pid,
955 const int argc, const char **argv)
957 if (argc != 1) {
958 fprintf(stderr, "Usage: smbcontrol <dest> "
959 "dmalloc-log-changed\n");
960 return False;
963 return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_LOG_CHANGED,
964 NULL, 0);
967 static void print_uint32_cb(struct messaging_context *msg, void *private_data,
968 uint32_t msg_type, struct server_id pid,
969 DATA_BLOB *data)
971 uint32_t num_children;
973 if (data->length != sizeof(uint32_t)) {
974 printf("Invalid response: %d bytes long\n",
975 (int)data->length);
976 goto done;
978 num_children = IVAL(data->data, 0);
979 printf("%u children\n", (unsigned)num_children);
980 done:
981 num_replies++;
984 static bool do_num_children(struct tevent_context *ev_ctx,
985 struct messaging_context *msg_ctx,
986 const struct server_id pid,
987 const int argc, const char **argv)
989 if (argc != 1) {
990 fprintf(stderr, "Usage: smbcontrol <dest> num-children\n");
991 return False;
994 messaging_register(msg_ctx, NULL, MSG_SMB_NUM_CHILDREN,
995 print_uint32_cb);
997 /* Send a message and register our interest in a reply */
999 if (!send_message(msg_ctx, pid, MSG_SMB_TELL_NUM_CHILDREN, NULL, 0))
1000 return false;
1002 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
1004 /* No replies were received within the timeout period */
1006 if (num_replies == 0)
1007 printf("No replies received\n");
1009 messaging_deregister(msg_ctx, MSG_SMB_NUM_CHILDREN, NULL);
1011 return num_replies;
1014 static bool do_msg_cleanup(struct tevent_context *ev_ctx,
1015 struct messaging_context *msg_ctx,
1016 const struct server_id pid,
1017 const int argc, const char **argv)
1019 int ret;
1021 ret = messaging_cleanup(msg_ctx, pid.pid);
1023 printf("cleanup(%u) returned %s\n", (unsigned)pid.pid,
1024 ret ? strerror(ret) : "ok");
1026 return (ret == 0);
1029 /* Shutdown a server process */
1031 static bool do_shutdown(struct tevent_context *ev_ctx,
1032 struct messaging_context *msg_ctx,
1033 const struct server_id pid,
1034 const int argc, const char **argv)
1036 if (argc != 1) {
1037 fprintf(stderr, "Usage: smbcontrol <dest> shutdown\n");
1038 return False;
1041 return send_message(msg_ctx, pid, MSG_SHUTDOWN, NULL, 0);
1044 /* Notify a driver upgrade */
1046 static bool do_drvupgrade(struct tevent_context *ev_ctx,
1047 struct messaging_context *msg_ctx,
1048 const struct server_id pid,
1049 const int argc, const char **argv)
1051 if (argc != 2) {
1052 fprintf(stderr, "Usage: smbcontrol <dest> drvupgrade "
1053 "<driver-name>\n");
1054 return False;
1057 return send_message(msg_ctx, pid, MSG_PRINTER_DRVUPGRADE, argv[1],
1058 strlen(argv[1]) + 1);
1061 static bool do_winbind_online(struct tevent_context *ev_ctx,
1062 struct messaging_context *msg_ctx,
1063 const struct server_id pid,
1064 const int argc, const char **argv)
1066 TDB_CONTEXT *tdb;
1067 char *db_path;
1069 if (argc != 1) {
1070 fprintf(stderr, "Usage: smbcontrol winbindd online\n");
1071 return False;
1074 db_path = state_path(talloc_tos(), "winbindd_cache.tdb");
1075 if (db_path == NULL) {
1076 return false;
1079 /* Remove the entry in the winbindd_cache tdb to tell a later
1080 starting winbindd that we're online. */
1082 tdb = tdb_open_log(db_path, 0, TDB_DEFAULT, O_RDWR, 0600);
1083 if (!tdb) {
1084 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
1085 db_path);
1086 TALLOC_FREE(db_path);
1087 return False;
1090 TALLOC_FREE(db_path);
1091 tdb_delete_bystring(tdb, "WINBINDD_OFFLINE");
1092 tdb_close(tdb);
1094 return send_message(msg_ctx, pid, MSG_WINBIND_ONLINE, NULL, 0);
1097 static bool do_winbind_offline(struct tevent_context *ev_ctx,
1098 struct messaging_context *msg_ctx,
1099 const struct server_id pid,
1100 const int argc, const char **argv)
1102 TDB_CONTEXT *tdb;
1103 bool ret = False;
1104 int retry = 0;
1105 char *db_path;
1107 if (argc != 1) {
1108 fprintf(stderr, "Usage: smbcontrol winbindd offline\n");
1109 return False;
1112 db_path = state_path(talloc_tos(), "winbindd_cache.tdb");
1113 if (db_path == NULL) {
1114 return false;
1117 /* Create an entry in the winbindd_cache tdb to tell a later
1118 starting winbindd that we're offline. We may actually create
1119 it here... */
1121 tdb = tdb_open_log(db_path,
1122 WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
1123 TDB_DEFAULT|TDB_INCOMPATIBLE_HASH /* TDB_CLEAR_IF_FIRST */,
1124 O_RDWR|O_CREAT, 0600);
1126 if (!tdb) {
1127 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
1128 db_path);
1129 TALLOC_FREE(db_path);
1130 return False;
1132 TALLOC_FREE(db_path);
1134 /* There's a potential race condition that if a child
1135 winbindd detects a domain is online at the same time
1136 we're trying to tell it to go offline that it might
1137 delete the record we add between us adding it and
1138 sending the message. Minimize this by retrying up to
1139 5 times. */
1141 for (retry = 0; retry < 5; retry++) {
1142 uint8_t buf[4];
1143 TDB_DATA d = { .dptr = buf, .dsize = sizeof(buf) };
1145 SIVAL(buf, 0, time(NULL));
1147 tdb_store_bystring(tdb, "WINBINDD_OFFLINE", d, TDB_INSERT);
1149 ret = send_message(msg_ctx, pid, MSG_WINBIND_OFFLINE,
1150 NULL, 0);
1152 /* Check that the entry "WINBINDD_OFFLINE" still exists. */
1153 d = tdb_fetch_bystring( tdb, "WINBINDD_OFFLINE" );
1154 if (d.dptr != NULL && d.dsize == 4) {
1155 SAFE_FREE(d.dptr);
1156 break;
1159 SAFE_FREE(d.dptr);
1160 DEBUG(10,("do_winbind_offline: offline state not set - retrying.\n"));
1163 tdb_close(tdb);
1164 return ret;
1167 static bool do_winbind_onlinestatus(struct tevent_context *ev_ctx,
1168 struct messaging_context *msg_ctx,
1169 const struct server_id pid,
1170 const int argc, const char **argv)
1172 if (argc != 1) {
1173 fprintf(stderr, "Usage: smbcontrol winbindd onlinestatus\n");
1174 return False;
1177 messaging_register(msg_ctx, NULL, MSG_WINBIND_ONLINESTATUS,
1178 print_pid_string_cb);
1180 if (!send_message(msg_ctx, pid, MSG_WINBIND_ONLINESTATUS, NULL, 0)) {
1181 return False;
1184 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
1186 /* No replies were received within the timeout period */
1188 if (num_replies == 0)
1189 printf("No replies received\n");
1191 messaging_deregister(msg_ctx, MSG_WINBIND_ONLINESTATUS, NULL);
1193 return num_replies;
1196 static bool do_winbind_dump_domain_list(struct tevent_context *ev_ctx,
1197 struct messaging_context *msg_ctx,
1198 const struct server_id pid,
1199 const int argc, const char **argv)
1201 const char *domain = NULL;
1202 int domain_len = 0;
1204 if (argc < 1 || argc > 2) {
1205 fprintf(stderr, "Usage: smbcontrol <dest> dump-domain-list "
1206 "<domain>\n");
1207 return false;
1210 if (argc == 2) {
1211 domain = argv[1];
1212 domain_len = strlen(argv[1]) + 1;
1215 messaging_register(msg_ctx, NULL, MSG_WINBIND_DUMP_DOMAIN_LIST,
1216 print_pid_string_cb);
1218 if (!send_message(msg_ctx, pid, MSG_WINBIND_DUMP_DOMAIN_LIST,
1219 domain, domain_len))
1221 return false;
1224 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
1226 /* No replies were received within the timeout period */
1228 if (num_replies == 0) {
1229 printf("No replies received\n");
1232 messaging_deregister(msg_ctx, MSG_WINBIND_DUMP_DOMAIN_LIST, NULL);
1234 return num_replies;
1237 static bool do_msg_disconnect_dc(struct tevent_context *ev_ctx,
1238 struct messaging_context *msg_ctx,
1239 const struct server_id pid,
1240 const int argc, const char **argv)
1242 if (argc != 1) {
1243 fprintf(stderr, "Usage: smbcontrol <dest> disconnect-dc\n");
1244 return False;
1247 return send_message(msg_ctx, pid, MSG_WINBIND_DISCONNECT_DC, NULL, 0);
1250 static void winbind_validate_cache_cb(struct messaging_context *msg,
1251 void *private_data,
1252 uint32_t msg_type,
1253 struct server_id pid,
1254 DATA_BLOB *data)
1256 struct server_id_buf src_string;
1257 printf("Winbindd cache is %svalid. (answer from pid %s)\n",
1258 (*(data->data) == 0 ? "" : "NOT "),
1259 server_id_str_buf(pid, &src_string));
1260 num_replies++;
1263 static bool do_winbind_validate_cache(struct tevent_context *ev_ctx,
1264 struct messaging_context *msg_ctx,
1265 const struct server_id pid,
1266 const int argc, const char **argv)
1268 struct server_id myid;
1270 myid = messaging_server_id(msg_ctx);
1272 if (argc != 1) {
1273 fprintf(stderr, "Usage: smbcontrol winbindd validate-cache\n");
1274 return False;
1277 messaging_register(msg_ctx, NULL, MSG_WINBIND_VALIDATE_CACHE,
1278 winbind_validate_cache_cb);
1280 if (!send_message(msg_ctx, pid, MSG_WINBIND_VALIDATE_CACHE, &myid,
1281 sizeof(myid))) {
1282 return False;
1285 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
1287 if (num_replies == 0) {
1288 printf("No replies received\n");
1291 messaging_deregister(msg_ctx, MSG_WINBIND_VALIDATE_CACHE, NULL);
1293 return num_replies;
1296 static bool do_reload_config(struct tevent_context *ev_ctx,
1297 struct messaging_context *msg_ctx,
1298 const struct server_id pid,
1299 const int argc, const char **argv)
1301 if (argc != 1) {
1302 fprintf(stderr, "Usage: smbcontrol <dest> reload-config\n");
1303 return False;
1306 return send_message(msg_ctx, pid, MSG_SMB_CONF_UPDATED, NULL, 0);
1309 static bool do_reload_printers(struct tevent_context *ev_ctx,
1310 struct messaging_context *msg_ctx,
1311 const struct server_id pid,
1312 const int argc, const char **argv)
1314 if (argc != 1) {
1315 fprintf(stderr, "Usage: smbcontrol <dest> reload-printers\n");
1316 return False;
1319 return send_message(msg_ctx, pid, MSG_PRINTER_PCAP, NULL, 0);
1322 static void my_make_nmb_name( struct nmb_name *n, const char *name, int type)
1324 fstring unix_name;
1325 memset( (char *)n, '\0', sizeof(struct nmb_name) );
1326 fstrcpy(unix_name, name);
1327 (void)strupper_m(unix_name);
1328 push_ascii(n->name, unix_name, sizeof(n->name), STR_TERMINATE);
1329 n->name_type = (unsigned int)type & 0xFF;
1330 push_ascii(n->scope, lp_netbios_scope(), 64, STR_TERMINATE);
1333 static bool do_nodestatus(struct tevent_context *ev_ctx,
1334 struct messaging_context *msg_ctx,
1335 const struct server_id pid,
1336 const int argc, const char **argv)
1338 struct packet_struct p;
1340 if (argc != 2) {
1341 fprintf(stderr, "Usage: smbcontrol nmbd nodestatus <ip>\n");
1342 return False;
1345 ZERO_STRUCT(p);
1347 p.ip = interpret_addr2(argv[1]);
1348 p.port = 137;
1349 p.packet_type = NMB_PACKET;
1351 p.packet.nmb.header.name_trn_id = 10;
1352 p.packet.nmb.header.opcode = 0;
1353 p.packet.nmb.header.response = False;
1354 p.packet.nmb.header.nm_flags.bcast = False;
1355 p.packet.nmb.header.nm_flags.recursion_available = False;
1356 p.packet.nmb.header.nm_flags.recursion_desired = False;
1357 p.packet.nmb.header.nm_flags.trunc = False;
1358 p.packet.nmb.header.nm_flags.authoritative = False;
1359 p.packet.nmb.header.rcode = 0;
1360 p.packet.nmb.header.qdcount = 1;
1361 p.packet.nmb.header.ancount = 0;
1362 p.packet.nmb.header.nscount = 0;
1363 p.packet.nmb.header.arcount = 0;
1364 my_make_nmb_name(&p.packet.nmb.question.question_name, "*", 0x00);
1365 p.packet.nmb.question.question_type = 0x21;
1366 p.packet.nmb.question.question_class = 0x1;
1368 return send_message(msg_ctx, pid, MSG_SEND_PACKET, &p, sizeof(p));
1371 static bool do_notify_cleanup(struct tevent_context *ev_ctx,
1372 struct messaging_context *msg_ctx,
1373 const struct server_id pid,
1374 const int argc, const char **argv)
1376 if (argc != 1) {
1377 fprintf(stderr, "Usage: smbcontrol smbd notify-cleanup\n");
1378 return false;
1380 return send_message(msg_ctx, pid, MSG_SMB_NOTIFY_CLEANUP, NULL, 0);
1383 /* A list of message type supported */
1385 static const struct {
1386 const char *name; /* Option name */
1387 bool (*fn)(struct tevent_context *ev_ctx,
1388 struct messaging_context *msg_ctx,
1389 const struct server_id pid,
1390 const int argc, const char **argv);
1391 const char *help; /* Short help text */
1392 } msg_types[] = {
1394 .name = "debug",
1395 .fn = do_debug,
1396 .help = "Set debuglevel",
1399 .name = "idmap",
1400 .fn = do_idmap,
1401 .help = "Manipulate idmap cache",
1404 .name = "force-election",
1405 .fn = do_election,
1406 .help = "Force a browse election",
1409 .name = "ping",
1410 .fn = do_ping,
1411 .help = "Elicit a response",
1414 .name = "profile",
1415 .fn = do_profile,
1416 .help = "",
1419 .name = "inject",
1420 .fn = do_inject_fault,
1421 .help = "Inject a fatal signal into a running smbd"},
1423 .name = "stacktrace",
1424 .fn = do_daemon_stack_trace,
1425 .help = "Display a stack trace of a daemon",
1428 .name = "profilelevel",
1429 .fn = do_profilelevel,
1430 .help = "",
1433 .name = "debuglevel",
1434 .fn = do_debuglevel,
1435 .help = "Display current debuglevels",
1438 .name = "printnotify",
1439 .fn = do_printnotify,
1440 .help = "Send a print notify message",
1443 .name = "close-share",
1444 .fn = do_closeshare,
1445 .help = "Forcibly disconnect a share",
1448 .name = "kill-client-ip",
1449 .fn = do_kill_client_by_ip,
1450 .help = "Forcibly disconnect a client with a specific IP address",
1453 .name = "ip-dropped",
1454 .fn = do_ip_dropped,
1455 .help = "Tell winbind that an IP got dropped",
1458 .name = "pool-usage",
1459 .fn = do_poolusage,
1460 .help = "Display talloc memory usage",
1463 .name = "ringbuf-log",
1464 .fn = do_ringbuflog,
1465 .help = "Display ringbuf log",
1468 .name = "dmalloc-mark",
1469 .fn = do_dmalloc_mark,
1470 .help = "",
1473 .name = "dmalloc-log-changed",
1474 .fn = do_dmalloc_changed,
1475 .help = "",
1478 .name = "shutdown",
1479 .fn = do_shutdown,
1480 .help = "Shut down daemon",
1483 .name = "drvupgrade",
1484 .fn = do_drvupgrade,
1485 .help = "Notify a printer driver has changed",
1488 .name = "reload-config",
1489 .fn = do_reload_config,
1490 .help = "Force smbd or winbindd to reload config file"},
1492 .name = "reload-printers",
1493 .fn = do_reload_printers,
1494 .help = "Force smbd to reload printers"},
1496 .name = "nodestatus",
1497 .fn = do_nodestatus,
1498 .help = "Ask nmbd to do a node status request"},
1500 .name = "online",
1501 .fn = do_winbind_online,
1502 .help = "Ask winbind to go into online state"},
1504 .name = "offline",
1505 .fn = do_winbind_offline,
1506 .help = "Ask winbind to go into offline state"},
1508 .name = "onlinestatus",
1509 .fn = do_winbind_onlinestatus,
1510 .help = "Request winbind online status"},
1512 .name = "validate-cache" ,
1513 .fn = do_winbind_validate_cache,
1514 .help = "Validate winbind's credential cache",
1517 .name = "dump-domain-list",
1518 .fn = do_winbind_dump_domain_list,
1519 .help = "Dump winbind domain list"},
1521 .name = "disconnect-dc",
1522 .fn = do_msg_disconnect_dc,
1525 .name = "notify-cleanup",
1526 .fn = do_notify_cleanup,
1529 .name = "num-children",
1530 .fn = do_num_children,
1531 .help = "Print number of smbd child processes",
1534 .name = "msg-cleanup",
1535 .fn = do_msg_cleanup,
1538 .name = "noop",
1539 .fn = do_noop,
1540 .help = "Do nothing",
1543 .name = "sleep",
1544 .fn = do_sleep,
1545 .help = "Cause the target process to sleep",
1547 { .name = NULL, },
1550 /* Display usage information */
1552 static void usage(poptContext pc)
1554 int i;
1556 poptPrintHelp(pc, stderr, 0);
1558 fprintf(stderr, "\n");
1559 fprintf(stderr, "<destination> is one of \"nmbd\", \"smbd\", \"winbindd\" or a "
1560 "process ID\n");
1562 fprintf(stderr, "\n");
1563 fprintf(stderr, "<message-type> is one of:\n");
1565 for (i = 0; msg_types[i].name; i++)
1566 fprintf(stderr, "\t%-30s%s\n", msg_types[i].name,
1567 msg_types[i].help);
1569 fprintf(stderr, "\n");
1571 exit(1);
1574 /* Return the pid number for a string destination */
1576 static struct server_id parse_dest(struct messaging_context *msg,
1577 const char *dest)
1579 struct server_id result = {
1580 .pid = (uint64_t)-1,
1582 pid_t pid;
1584 /* Zero is a special return value for broadcast to all processes */
1586 if (strequal(dest, "all")) {
1587 return interpret_pid(MSG_BROADCAST_PID_STR);
1590 /* Try self - useful for testing */
1592 if (strequal(dest, "self")) {
1593 return messaging_server_id(msg);
1596 /* Fix winbind typo. */
1597 if (strequal(dest, "winbind")) {
1598 dest = "winbindd";
1601 /* Check for numeric pid number */
1602 result = interpret_pid(dest);
1604 /* Zero isn't valid if not "all". */
1605 if (result.pid && procid_valid(&result)) {
1606 return result;
1609 /* Look up other destinations in pidfile directory */
1611 if ((pid = pidfile_pid(lp_pid_directory(), dest)) != 0) {
1612 return pid_to_procid(pid);
1615 fprintf(stderr,"Can't find pid for destination '%s'\n", dest);
1617 return result;
1620 /* Execute smbcontrol command */
1622 static bool do_command(struct tevent_context *ev_ctx,
1623 struct messaging_context *msg_ctx,
1624 int argc, const char **argv)
1626 const char *dest = argv[0], *command = argv[1];
1627 struct server_id pid;
1628 int i;
1630 /* Check destination */
1632 pid = parse_dest(msg_ctx, dest);
1633 if (!procid_valid(&pid)) {
1634 return False;
1637 /* Check command */
1639 for (i = 0; msg_types[i].name; i++) {
1640 if (strequal(command, msg_types[i].name))
1641 return msg_types[i].fn(ev_ctx, msg_ctx, pid,
1642 argc - 1, argv + 1);
1645 fprintf(stderr, "smbcontrol: unknown command '%s'\n", command);
1647 return False;
1650 static void smbcontrol_help(poptContext pc,
1651 enum poptCallbackReason preason,
1652 struct poptOption * poption,
1653 const char * parg,
1654 void * pdata)
1656 if (poption->shortName != '?') {
1657 poptPrintUsage(pc, stdout, 0);
1658 } else {
1659 usage(pc);
1662 exit(0);
1665 struct poptOption help_options[] = {
1666 { NULL, '\0', POPT_ARG_CALLBACK, (void *)&smbcontrol_help, '\0',
1667 NULL, NULL },
1668 { "help", '?', 0, NULL, '?', "Show this help message", NULL },
1669 { "usage", '\0', 0, NULL, 'u', "Display brief usage message", NULL },
1670 { NULL }
1673 /* Main program */
1675 int main(int argc, const char **argv)
1677 poptContext pc;
1678 int opt;
1679 struct tevent_context *evt_ctx;
1680 struct messaging_context *msg_ctx;
1682 static struct poptOption long_options[] = {
1683 /* POPT_AUTOHELP */
1684 { NULL, '\0', POPT_ARG_INCLUDE_TABLE, help_options,
1685 0, "Help options:", NULL },
1686 { "timeout", 't', POPT_ARG_INT, &timeout, 't',
1687 "Set timeout value in seconds", "TIMEOUT" },
1689 POPT_COMMON_SAMBA
1690 POPT_TABLEEND
1692 TALLOC_CTX *frame = talloc_stackframe();
1693 int ret = 0;
1695 smb_init_locale();
1697 setup_logging(argv[0], DEBUG_STDOUT);
1698 lp_set_cmdline("log level", "0");
1700 /* Parse command line arguments using popt */
1702 pc = poptGetContext(
1703 "smbcontrol", argc, (const char **)argv, long_options, 0);
1705 poptSetOtherOptionHelp(pc, "[OPTION...] <destination> <message-type> "
1706 "<parameters>");
1708 if (argc == 1)
1709 usage(pc);
1711 while ((opt = poptGetNextOpt(pc)) != -1) {
1712 switch(opt) {
1713 case 't': /* --timeout */
1714 break;
1715 default:
1716 fprintf(stderr, "Invalid option\n");
1717 poptPrintHelp(pc, stderr, 0);
1718 break;
1722 /* We should now have the remaining command line arguments in
1723 argv. The argc parameter should have been decremented to the
1724 correct value in the above switch statement. */
1726 argv = (const char **)poptGetArgs(pc);
1727 argc = 0;
1728 if (argv != NULL) {
1729 while (argv[argc] != NULL) {
1730 argc++;
1734 if (argc <= 1)
1735 usage(pc);
1737 msg_ctx = cmdline_messaging_context(get_dyn_CONFIGFILE());
1738 if (msg_ctx == NULL) {
1739 fprintf(stderr,
1740 "Could not init messaging context, not root?\n");
1741 TALLOC_FREE(frame);
1742 exit(1);
1745 evt_ctx = global_event_context();
1747 lp_load_global(get_dyn_CONFIGFILE());
1749 /* Need to invert sense of return code -- samba
1750 * routines mostly return True==1 for success, but
1751 * shell needs 0. */
1753 ret = !do_command(evt_ctx, msg_ctx, argc, argv);
1754 TALLOC_FREE(frame);
1755 return ret;