s3:smbcontrol: improve destination resolution using names db
[Samba.git] / source3 / utils / smbcontrol.c
blobb85dceca60565e61981871065f0664e7dcad6d7f
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 "lib/cmdline/cmdline.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 "lib/util/server_id_db.h"
39 #include "cmdline_contexts.h"
40 #include "lib/util/string_wrappers.h"
41 #include "lib/global_contexts.h"
43 #ifdef HAVE_LIBUNWIND_H
44 #include <libunwind.h>
45 #endif
47 #ifdef HAVE_LIBUNWIND_PTRACE_H
48 #include <libunwind-ptrace.h>
49 #endif
51 #ifdef HAVE_SYS_PTRACE_H
52 #include <sys/ptrace.h>
53 #endif
55 /* Default timeout value when waiting for replies (in seconds) */
57 #define DEFAULT_TIMEOUT 10
59 static int timeout = DEFAULT_TIMEOUT;
60 static int num_replies; /* Used by message callback fns */
62 /* Send a message to a destination pid. Zero means broadcast smbd. */
64 static bool send_message(struct messaging_context *msg_ctx,
65 struct server_id pid, int msg_type,
66 const void *buf, int len)
68 if (procid_to_pid(&pid) != 0)
69 return NT_STATUS_IS_OK(
70 messaging_send_buf(msg_ctx, pid, msg_type,
71 (const uint8_t *)buf, len));
73 messaging_send_all(msg_ctx, msg_type, buf, len);
75 return true;
78 static void smbcontrol_timeout(struct tevent_context *event_ctx,
79 struct tevent_timer *te,
80 struct timeval now,
81 void *private_data)
83 bool *timed_out = (bool *)private_data;
84 TALLOC_FREE(te);
85 *timed_out = True;
88 /* Wait for one or more reply messages */
90 static void wait_replies(struct tevent_context *ev_ctx,
91 struct messaging_context *msg_ctx,
92 bool multiple_replies)
94 struct tevent_timer *te;
95 bool timed_out = False;
97 te = tevent_add_timer(ev_ctx, NULL,
98 timeval_current_ofs(timeout, 0),
99 smbcontrol_timeout, (void *)&timed_out);
100 if (te == NULL) {
101 DEBUG(0, ("tevent_add_timer failed\n"));
102 return;
105 while (!timed_out) {
106 int ret;
107 if (num_replies > 0 && !multiple_replies)
108 break;
109 ret = tevent_loop_once(ev_ctx);
110 if (ret != 0) {
111 break;
116 /* Message handler callback that displays the PID and a string on stdout */
118 static void print_pid_string_cb(struct messaging_context *msg,
119 void *private_data,
120 uint32_t msg_type,
121 struct server_id pid,
122 DATA_BLOB *data)
124 struct server_id_buf pidstr;
126 printf("PID %s: %.*s", server_id_str_buf(pid, &pidstr),
127 (int)data->length, (const char *)data->data);
128 num_replies++;
131 /* Send no message. Useful for testing. */
133 static bool do_noop(struct tevent_context *ev_ctx,
134 struct messaging_context *msg_ctx,
135 const struct server_id pid,
136 const int argc, const char **argv)
138 if (argc != 1) {
139 fprintf(stderr, "Usage: smbcontrol <dest> noop\n");
140 return False;
143 /* Move along, nothing to see here */
145 return True;
148 /* Send a debug string */
150 static bool do_debug(struct tevent_context *ev_ctx,
151 struct messaging_context *msg_ctx,
152 const struct server_id pid,
153 const int argc, const char **argv)
155 if (argc != 2) {
156 fprintf(stderr, "Usage: smbcontrol <dest> debug "
157 "<debug-string>\n");
158 return False;
161 return send_message(msg_ctx, pid, MSG_DEBUG, argv[1],
162 strlen(argv[1]) + 1);
166 static bool do_idmap(struct tevent_context *ev,
167 struct messaging_context *msg_ctx,
168 const struct server_id pid,
169 const int argc, const char **argv)
171 static const char* usage = "Usage: "
172 "smbcontrol <dest> idmap <cmd> [arg]\n"
173 "\tcmd:"
174 "\tdelete \"UID <uid>\"|\"GID <gid>\"|<sid>\n"
175 "\t\tkill \"UID <uid>\"|\"GID <gid>\"|<sid>\n";
176 const char* arg = NULL;
177 int arglen = 0;
178 int msg_type;
180 switch (argc) {
181 case 2:
182 break;
183 case 3:
184 arg = argv[2];
185 arglen = strlen(arg) + 1;
186 break;
187 default:
188 fprintf(stderr, "%s", usage);
189 return false;
192 if (strcmp(argv[1], "delete") == 0) {
193 msg_type = ID_CACHE_DELETE;
195 else if (strcmp(argv[1], "kill") == 0) {
196 msg_type = ID_CACHE_KILL;
198 else if (strcmp(argv[1], "help") == 0) {
199 fprintf(stdout, "%s", usage);
200 return true;
202 else {
203 fprintf(stderr, "%s", usage);
204 return false;
207 return send_message(msg_ctx, pid, msg_type, arg, arglen);
211 #if defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE)
213 /* Return the name of a process given it's PID. This will only work on Linux,
214 * but that's probably moot since this whole stack tracing implementation is
215 * Linux-specific anyway.
217 static const char * procname(pid_t pid, char * buf, size_t bufsz)
219 char path[64];
220 FILE * fp;
222 snprintf(path, sizeof(path), "/proc/%llu/cmdline",
223 (unsigned long long)pid);
224 if ((fp = fopen(path, "r")) == NULL) {
225 return NULL;
228 fgets(buf, bufsz, fp);
230 fclose(fp);
231 return buf;
234 static void print_stack_trace(pid_t pid, int * count)
236 void * pinfo = NULL;
237 unw_addr_space_t aspace = NULL;
238 unw_cursor_t cursor;
239 unw_word_t ip, sp;
241 char nbuf[256];
242 unw_word_t off;
244 int ret;
246 if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) {
247 fprintf(stderr,
248 "Failed to attach to process %llu: %s\n",
249 (unsigned long long)pid, strerror(errno));
250 return;
253 /* Wait until the attach is complete. */
254 waitpid(pid, NULL, 0);
256 if (((pinfo = _UPT_create(pid)) == NULL) ||
257 ((aspace = unw_create_addr_space(&_UPT_accessors, 0)) == NULL)) {
258 /* Probably out of memory. */
259 fprintf(stderr,
260 "Unable to initialize stack unwind for process %llu\n",
261 (unsigned long long)pid);
262 goto cleanup;
265 if ((ret = unw_init_remote(&cursor, aspace, pinfo))) {
266 fprintf(stderr,
267 "Unable to unwind stack for process %llu: %s\n",
268 (unsigned long long)pid, unw_strerror(ret));
269 goto cleanup;
272 if (*count > 0) {
273 printf("\n");
276 if (procname(pid, nbuf, sizeof(nbuf))) {
277 printf("Stack trace for process %llu (%s):\n",
278 (unsigned long long)pid, nbuf);
279 } else {
280 printf("Stack trace for process %llu:\n",
281 (unsigned long long)pid);
284 while (unw_step(&cursor) > 0) {
285 ip = sp = off = 0;
286 unw_get_reg(&cursor, UNW_REG_IP, &ip);
287 unw_get_reg(&cursor, UNW_REG_SP, &sp);
289 ret = unw_get_proc_name(&cursor, nbuf, sizeof(nbuf), &off);
290 if (ret != 0 && ret != -UNW_ENOMEM) {
291 snprintf(nbuf, sizeof(nbuf), "<unknown symbol>");
293 printf(" %s + %#llx [ip=%#llx] [sp=%#llx]\n",
294 nbuf, (long long)off, (long long)ip,
295 (long long)sp);
298 (*count)++;
300 cleanup:
301 if (aspace) {
302 unw_destroy_addr_space(aspace);
305 if (pinfo) {
306 _UPT_destroy(pinfo);
309 ptrace(PTRACE_DETACH, pid, NULL, NULL);
312 static int stack_trace_server(pid_t pid, void *priv)
314 print_stack_trace(pid, (int *)priv);
315 return 0;
318 static bool do_daemon_stack_trace(struct tevent_context *ev_ctx,
319 struct messaging_context *msg_ctx,
320 const struct server_id pid,
321 const int argc, const char **argv)
323 pid_t dest;
324 int count = 0;
326 if (argc != 1) {
327 fprintf(stderr, "Usage: smbcontrol <dest> stacktrace\n");
328 return False;
331 dest = procid_to_pid(&pid);
333 if (dest != 0) {
334 /* It would be nice to be able to make sure that this PID is
335 * the PID of a smbd/winbind/nmbd process, not some random PID
336 * the user liked the look of. It doesn't seem like it's worth
337 * the effort at the moment, however.
339 print_stack_trace(dest, &count);
340 } else {
341 messaging_dgm_forall(stack_trace_server, &count);
344 return True;
347 #else /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
349 static bool do_daemon_stack_trace(struct tevent_context *ev_ctx,
350 struct messaging_context *msg_ctx,
351 const struct server_id pid,
352 const int argc, const char **argv)
354 fprintf(stderr,
355 "Daemon stack tracing is not supported on this platform\n");
356 return False;
359 #endif /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
361 /* Inject a fault (fatal signal) into a running smbd */
363 static bool do_inject_fault(struct tevent_context *ev_ctx,
364 struct messaging_context *msg_ctx,
365 const struct server_id pid,
366 const int argc, const char **argv)
368 if (argc != 2) {
369 fprintf(stderr, "Usage: smbcontrol <dest> inject "
370 "<bus|hup|term|internal|segv>\n");
371 return False;
374 #if !defined(DEVELOPER) && !defined(ENABLE_SELFTEST)
375 fprintf(stderr, "Fault injection is only available in "
376 "developer and self test builds\n");
377 return False;
378 #else /* DEVELOPER || ENABLE_SELFTEST */
380 int sig = 0;
382 if (strcmp(argv[1], "bus") == 0) {
383 sig = SIGBUS;
384 } else if (strcmp(argv[1], "hup") == 0) {
385 sig = SIGHUP;
386 } else if (strcmp(argv[1], "term") == 0) {
387 sig = SIGTERM;
388 } else if (strcmp(argv[1], "segv") == 0) {
389 sig = SIGSEGV;
390 } else if (strcmp(argv[1], "internal") == 0) {
391 /* Force an internal error, ie. an unclean exit. */
392 sig = -1;
393 } else {
394 fprintf(stderr, "Unknown signal name '%s'\n", argv[1]);
395 return False;
398 return send_message(msg_ctx, pid, MSG_SMB_INJECT_FAULT,
399 &sig, sizeof(int));
401 #endif /* DEVELOPER || ENABLE_SELFTEST */
404 static bool do_sleep(struct tevent_context *ev_ctx,
405 struct messaging_context *msg_ctx,
406 const struct server_id pid,
407 const int argc, const char **argv)
409 #if defined(DEVELOPER) || defined(ENABLE_SELFTEST)
410 unsigned int seconds;
411 long input;
412 const long MAX_SLEEP = 60 * 60; /* One hour maximum sleep */
413 #endif
415 if (argc != 2) {
416 fprintf(stderr, "Usage: smbcontrol <dest> sleep seconds\n");
417 return False;
420 #if !defined(DEVELOPER) && !defined(ENABLE_SELFTEST)
421 fprintf(stderr, "Sleep is only available in "
422 "developer and self test builds\n");
423 return False;
424 #else /* DEVELOPER || ENABLE_SELFTEST */
426 input = atol(argv[1]);
427 if (input < 1 || input > MAX_SLEEP) {
428 fprintf(stderr,
429 "Invalid duration for sleep '%s'\n"
430 "It should be at least 1 second and no more than %ld\n",
431 argv[1],
432 MAX_SLEEP);
433 return False;
435 seconds = input;
436 return send_message(msg_ctx, pid,
437 MSG_SMB_SLEEP,
438 &seconds,
439 sizeof(unsigned int));
440 #endif /* DEVELOPER || ENABLE_SELFTEST */
443 /* Force a browser election */
445 static bool do_election(struct tevent_context *ev_ctx,
446 struct messaging_context *msg_ctx,
447 const struct server_id pid,
448 const int argc, const char **argv)
450 if (argc != 1) {
451 fprintf(stderr, "Usage: smbcontrol <dest> force-election\n");
452 return False;
455 return send_message(msg_ctx, pid, MSG_FORCE_ELECTION, NULL, 0);
458 /* Ping a samba daemon process */
460 static void pong_cb(struct messaging_context *msg,
461 void *private_data,
462 uint32_t msg_type,
463 struct server_id pid,
464 DATA_BLOB *data)
466 struct server_id_buf src_string;
467 printf("PONG from pid %s\n", server_id_str_buf(pid, &src_string));
468 num_replies++;
471 static bool do_ping(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 if (argc != 1) {
477 fprintf(stderr, "Usage: smbcontrol <dest> ping\n");
478 return False;
481 /* Send a message and register our interest in a reply */
483 if (!send_message(msg_ctx, pid, MSG_PING, NULL, 0))
484 return False;
486 messaging_register(msg_ctx, NULL, MSG_PONG, pong_cb);
488 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
490 /* No replies were received within the timeout period */
492 if (num_replies == 0)
493 printf("No replies received\n");
495 messaging_deregister(msg_ctx, MSG_PONG, NULL);
497 return num_replies;
500 /* Set profiling options */
502 static bool do_profile(struct tevent_context *ev_ctx,
503 struct messaging_context *msg_ctx,
504 const struct server_id pid,
505 const int argc, const char **argv)
507 int v;
509 if (argc != 2) {
510 fprintf(stderr, "Usage: smbcontrol <dest> profile "
511 "<off|count|on|flush>\n");
512 return False;
515 if (strcmp(argv[1], "off") == 0) {
516 v = 0;
517 } else if (strcmp(argv[1], "count") == 0) {
518 v = 1;
519 } else if (strcmp(argv[1], "on") == 0) {
520 v = 2;
521 } else if (strcmp(argv[1], "flush") == 0) {
522 v = 3;
523 } else {
524 fprintf(stderr, "Unknown profile command '%s'\n", argv[1]);
525 return False;
528 return send_message(msg_ctx, pid, MSG_PROFILE, &v, sizeof(int));
531 /* Return the profiling level */
533 static void profilelevel_cb(struct messaging_context *msg_ctx,
534 void *private_data,
535 uint32_t msg_type,
536 struct server_id pid,
537 DATA_BLOB *data)
539 int level;
540 const char *s;
542 num_replies++;
544 if (data->length != sizeof(int)) {
545 fprintf(stderr, "invalid message length %ld returned\n",
546 (unsigned long)data->length);
547 return;
550 memcpy(&level, data->data, sizeof(int));
552 switch (level) {
553 case 0:
554 s = "not enabled";
555 break;
556 case 1:
557 s = "off";
558 break;
559 case 3:
560 s = "count only";
561 break;
562 case 7:
563 s = "count and time";
564 break;
565 default:
566 s = "BOGUS";
567 break;
570 printf("Profiling %s on pid %u\n",s,(unsigned int)procid_to_pid(&pid));
573 static void profilelevel_rqst(struct messaging_context *msg_ctx,
574 void *private_data,
575 uint32_t msg_type,
576 struct server_id pid,
577 DATA_BLOB *data)
579 int v = 0;
581 /* Send back a dummy reply */
583 send_message(msg_ctx, pid, MSG_PROFILELEVEL, &v, sizeof(int));
586 static bool do_profilelevel(struct tevent_context *ev_ctx,
587 struct messaging_context *msg_ctx,
588 const struct server_id pid,
589 const int argc, const char **argv)
591 if (argc != 1) {
592 fprintf(stderr, "Usage: smbcontrol <dest> profilelevel\n");
593 return False;
596 /* Send a message and register our interest in a reply */
598 if (!send_message(msg_ctx, pid, MSG_REQ_PROFILELEVEL, NULL, 0))
599 return False;
601 messaging_register(msg_ctx, NULL, MSG_PROFILELEVEL, profilelevel_cb);
602 messaging_register(msg_ctx, NULL, MSG_REQ_PROFILELEVEL,
603 profilelevel_rqst);
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_PROFILE, NULL);
614 return num_replies;
617 /* Display debug level settings */
619 static bool do_debuglevel(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 if (argc != 1) {
625 fprintf(stderr, "Usage: smbcontrol <dest> debuglevel\n");
626 return False;
629 /* Send a message and register our interest in a reply */
631 if (!send_message(msg_ctx, pid, MSG_REQ_DEBUGLEVEL, NULL, 0))
632 return False;
634 messaging_register(msg_ctx, NULL, MSG_DEBUGLEVEL, print_pid_string_cb);
636 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
638 /* No replies were received within the timeout period */
640 if (num_replies == 0)
641 printf("No replies received\n");
643 messaging_deregister(msg_ctx, MSG_DEBUGLEVEL, NULL);
645 return num_replies;
648 /* Send a print notify message */
650 static bool do_printnotify(struct tevent_context *ev_ctx,
651 struct messaging_context *msg_ctx,
652 const struct server_id pid,
653 const int argc, const char **argv)
655 const char *cmd;
657 /* Check for subcommand */
659 if (argc == 1) {
660 fprintf(stderr, "Must specify subcommand:\n");
661 fprintf(stderr, "\tqueuepause <printername>\n");
662 fprintf(stderr, "\tqueueresume <printername>\n");
663 fprintf(stderr, "\tjobpause <printername> <unix jobid>\n");
664 fprintf(stderr, "\tjobresume <printername> <unix jobid>\n");
665 fprintf(stderr, "\tjobdelete <printername> <unix jobid>\n");
666 fprintf(stderr, "\tprinter <printername> <comment|port|"
667 "driver> <value>\n");
669 return False;
672 cmd = argv[1];
674 if (strcmp(cmd, "queuepause") == 0) {
676 if (argc != 3) {
677 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
678 " queuepause <printername>\n");
679 return False;
682 notify_printer_status_byname(ev_ctx, msg_ctx, argv[2],
683 PRINTER_STATUS_PAUSED);
685 goto send;
687 } else if (strcmp(cmd, "queueresume") == 0) {
689 if (argc != 3) {
690 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
691 " queuereume <printername>\n");
692 return False;
695 notify_printer_status_byname(ev_ctx, msg_ctx, argv[2],
696 PRINTER_STATUS_OK);
698 goto send;
700 } else if (strcmp(cmd, "jobpause") == 0) {
701 int jobid;
703 if (argc != 4) {
704 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
705 " jobpause <printername> <unix-jobid>\n");
706 return False;
709 jobid = atoi(argv[3]);
711 notify_job_status_byname(
712 ev_ctx, msg_ctx,
713 argv[2], jobid, JOB_STATUS_PAUSED,
714 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
716 goto send;
718 } else if (strcmp(cmd, "jobresume") == 0) {
719 int jobid;
721 if (argc != 4) {
722 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
723 " jobpause <printername> <unix-jobid>\n");
724 return False;
727 jobid = atoi(argv[3]);
729 notify_job_status_byname(
730 ev_ctx, msg_ctx,
731 argv[2], jobid, JOB_STATUS_QUEUED,
732 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
734 goto send;
736 } else if (strcmp(cmd, "jobdelete") == 0) {
737 int jobid;
739 if (argc != 4) {
740 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
741 " jobpause <printername> <unix-jobid>\n");
742 return False;
745 jobid = atoi(argv[3]);
747 notify_job_status_byname(
748 ev_ctx, msg_ctx,
749 argv[2], jobid, JOB_STATUS_DELETING,
750 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
752 notify_job_status_byname(
753 ev_ctx, msg_ctx,
754 argv[2], jobid, JOB_STATUS_DELETING|
755 JOB_STATUS_DELETED,
756 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
758 goto send;
760 } else if (strcmp(cmd, "printer") == 0) {
761 uint32_t attribute;
763 if (argc != 5) {
764 fprintf(stderr, "Usage: smbcontrol <dest> printnotify "
765 "printer <printername> <comment|port|driver> "
766 "<value>\n");
767 return False;
770 if (strcmp(argv[3], "comment") == 0) {
771 attribute = PRINTER_NOTIFY_FIELD_COMMENT;
772 } else if (strcmp(argv[3], "port") == 0) {
773 attribute = PRINTER_NOTIFY_FIELD_PORT_NAME;
774 } else if (strcmp(argv[3], "driver") == 0) {
775 attribute = PRINTER_NOTIFY_FIELD_DRIVER_NAME;
776 } else {
777 fprintf(stderr, "Invalid printer command '%s'\n",
778 argv[3]);
779 return False;
782 notify_printer_byname(ev_ctx, msg_ctx, argv[2], attribute,
783 discard_const_p(char, argv[4]));
785 goto send;
788 fprintf(stderr, "Invalid subcommand '%s'\n", cmd);
789 return False;
791 send:
792 print_notify_send_messages(msg_ctx, 0);
793 return True;
796 /* Close a share */
798 static bool do_closeshare(struct tevent_context *ev_ctx,
799 struct messaging_context *msg_ctx,
800 const struct server_id pid,
801 const int argc, const char **argv)
803 if (argc != 2) {
804 fprintf(stderr, "Usage: smbcontrol <dest> close-share "
805 "<sharename>\n");
806 return False;
809 return send_message(msg_ctx, pid, MSG_SMB_FORCE_TDIS, argv[1],
810 strlen(argv[1]) + 1);
814 * Close a share if access denied by now
817 static bool do_close_denied_share(
818 struct tevent_context *ev_ctx,
819 struct messaging_context *msg_ctx,
820 const struct server_id pid,
821 const int argc, const char **argv)
823 if (argc != 2) {
824 fprintf(stderr, "Usage: smbcontrol <dest> close-denied-share "
825 "<sharename>\n");
826 return False;
829 return send_message(
830 msg_ctx,
831 pid,
832 MSG_SMB_FORCE_TDIS_DENIED,
833 argv[1],
834 strlen(argv[1]) + 1);
837 /* Kill a client by IP address */
838 static bool do_kill_client_by_ip(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 != 2) {
844 fprintf(stderr, "Usage: smbcontrol <dest> kill-client-ip "
845 "<IP address>\n");
846 return false;
849 if (!is_ipaddress_v4(argv[1]) && !is_ipaddress_v6(argv[1])) {
850 fprintf(stderr, "%s is not a valid IP address!\n", argv[1]);
851 return false;
854 return send_message(msg_ctx, pid, MSG_SMB_KILL_CLIENT_IP,
855 argv[1], strlen(argv[1]) + 1);
858 /* Tell winbindd an IP got dropped */
860 static bool do_ip_dropped(struct tevent_context *ev_ctx,
861 struct messaging_context *msg_ctx,
862 const struct server_id pid,
863 const int argc, const char **argv)
865 if (argc != 2) {
866 fprintf(stderr, "Usage: smbcontrol <dest> ip-dropped "
867 "<ip-address>\n");
868 return False;
871 return send_message(msg_ctx, pid, MSG_WINBIND_IP_DROPPED, argv[1],
872 strlen(argv[1]) + 1);
875 /* Display talloc pool usage */
877 static bool do_poolusage(struct tevent_context *ev_ctx,
878 struct messaging_context *msg_ctx,
879 const struct server_id dst,
880 const int argc, const char **argv)
882 pid_t pid = procid_to_pid(&dst);
883 int stdout_fd = 1;
885 if (argc != 1) {
886 fprintf(stderr, "Usage: smbcontrol <dest> pool-usage\n");
887 return False;
890 if (pid == 0) {
891 fprintf(stderr, "Can only send to a specific PID\n");
892 return false;
895 messaging_send_iov(
896 msg_ctx,
897 dst,
898 MSG_REQ_POOL_USAGE,
899 NULL,
901 &stdout_fd,
904 return true;
907 static bool do_rpc_dump_status(
908 struct tevent_context *ev_ctx,
909 struct messaging_context *msg_ctx,
910 const struct server_id dst,
911 const int argc,
912 const char **argv)
914 pid_t pid = procid_to_pid(&dst);
915 int stdout_fd = 1;
917 if (argc != 1) {
918 fprintf(stderr,
919 "Usage: smbcontrol <dest> rpc-dump-status\n");
920 return False;
923 if (pid == 0) {
924 fprintf(stderr, "Can only send to a specific PID\n");
925 return false;
928 messaging_send_iov(
929 msg_ctx,
930 dst,
931 MSG_RPC_DUMP_STATUS,
932 NULL,
934 &stdout_fd,
937 return true;
940 /* Fetch and print the ringbuf log */
942 static void print_ringbuf_log_cb(struct messaging_context *msg,
943 void *private_data,
944 uint32_t msg_type,
945 struct server_id pid,
946 DATA_BLOB *data)
948 printf("%s", (const char *)data->data);
949 num_replies++;
952 static bool do_ringbuflog(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> ringbuf-log\n");
959 return false;
962 messaging_register(msg_ctx, NULL, MSG_RINGBUF_LOG,
963 print_ringbuf_log_cb);
965 /* Send a message and register our interest in a reply */
967 if (!send_message(msg_ctx, pid, MSG_REQ_RINGBUF_LOG, NULL, 0)) {
968 return false;
971 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
973 /* No replies were received within the timeout period */
975 if (num_replies == 0) {
976 printf("No replies received\n");
979 messaging_deregister(msg_ctx, MSG_RINGBUF_LOG, NULL);
981 return num_replies != 0;
984 /* Perform a dmalloc mark */
986 static bool do_dmalloc_mark(struct tevent_context *ev_ctx,
987 struct messaging_context *msg_ctx,
988 const struct server_id pid,
989 const int argc, const char **argv)
991 if (argc != 1) {
992 fprintf(stderr, "Usage: smbcontrol <dest> dmalloc-mark\n");
993 return False;
996 return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_MARK, NULL, 0);
999 /* Perform a dmalloc changed */
1001 static bool do_dmalloc_changed(struct tevent_context *ev_ctx,
1002 struct messaging_context *msg_ctx,
1003 const struct server_id pid,
1004 const int argc, const char **argv)
1006 if (argc != 1) {
1007 fprintf(stderr, "Usage: smbcontrol <dest> "
1008 "dmalloc-log-changed\n");
1009 return False;
1012 return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_LOG_CHANGED,
1013 NULL, 0);
1016 static void print_uint32_cb(struct messaging_context *msg, void *private_data,
1017 uint32_t msg_type, struct server_id pid,
1018 DATA_BLOB *data)
1020 uint32_t num_children;
1022 if (data->length != sizeof(uint32_t)) {
1023 printf("Invalid response: %d bytes long\n",
1024 (int)data->length);
1025 goto done;
1027 num_children = IVAL(data->data, 0);
1028 printf("%u children\n", (unsigned)num_children);
1029 done:
1030 num_replies++;
1033 static bool do_num_children(struct tevent_context *ev_ctx,
1034 struct messaging_context *msg_ctx,
1035 const struct server_id pid,
1036 const int argc, const char **argv)
1038 if (argc != 1) {
1039 fprintf(stderr, "Usage: smbcontrol <dest> num-children\n");
1040 return False;
1043 messaging_register(msg_ctx, NULL, MSG_SMB_NUM_CHILDREN,
1044 print_uint32_cb);
1046 /* Send a message and register our interest in a reply */
1048 if (!send_message(msg_ctx, pid, MSG_SMB_TELL_NUM_CHILDREN, NULL, 0))
1049 return false;
1051 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
1053 /* No replies were received within the timeout period */
1055 if (num_replies == 0)
1056 printf("No replies received\n");
1058 messaging_deregister(msg_ctx, MSG_SMB_NUM_CHILDREN, NULL);
1060 return num_replies;
1063 static bool do_msg_cleanup(struct tevent_context *ev_ctx,
1064 struct messaging_context *msg_ctx,
1065 const struct server_id pid,
1066 const int argc, const char **argv)
1068 int ret;
1070 ret = messaging_cleanup(msg_ctx, pid.pid);
1072 printf("cleanup(%u) returned %s\n", (unsigned)pid.pid,
1073 ret ? strerror(ret) : "ok");
1075 return (ret == 0);
1078 /* Shutdown a server process */
1080 static bool do_shutdown(struct tevent_context *ev_ctx,
1081 struct messaging_context *msg_ctx,
1082 const struct server_id pid,
1083 const int argc, const char **argv)
1085 if (argc != 1) {
1086 fprintf(stderr, "Usage: smbcontrol <dest> shutdown\n");
1087 return False;
1090 return send_message(msg_ctx, pid, MSG_SHUTDOWN, NULL, 0);
1093 /* Notify a driver upgrade */
1095 static bool do_drvupgrade(struct tevent_context *ev_ctx,
1096 struct messaging_context *msg_ctx,
1097 const struct server_id pid,
1098 const int argc, const char **argv)
1100 if (argc != 2) {
1101 fprintf(stderr, "Usage: smbcontrol <dest> drvupgrade "
1102 "<driver-name>\n");
1103 return False;
1106 return send_message(msg_ctx, pid, MSG_PRINTER_DRVUPGRADE, argv[1],
1107 strlen(argv[1]) + 1);
1110 static bool do_winbind_online(struct tevent_context *ev_ctx,
1111 struct messaging_context *msg_ctx,
1112 const struct server_id pid,
1113 const int argc, const char **argv)
1115 TDB_CONTEXT *tdb;
1116 char *db_path;
1118 if (argc != 1) {
1119 fprintf(stderr, "Usage: smbcontrol winbindd online\n");
1120 return False;
1123 db_path = state_path(talloc_tos(), "winbindd_cache.tdb");
1124 if (db_path == NULL) {
1125 return false;
1128 /* Remove the entry in the winbindd_cache tdb to tell a later
1129 starting winbindd that we're online. */
1131 tdb = tdb_open_log(db_path, 0, TDB_DEFAULT, O_RDWR, 0600);
1132 if (!tdb) {
1133 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
1134 db_path);
1135 TALLOC_FREE(db_path);
1136 return False;
1139 TALLOC_FREE(db_path);
1140 tdb_delete_bystring(tdb, "WINBINDD_OFFLINE");
1141 tdb_close(tdb);
1143 return send_message(msg_ctx, pid, MSG_WINBIND_ONLINE, NULL, 0);
1146 static bool do_winbind_offline(struct tevent_context *ev_ctx,
1147 struct messaging_context *msg_ctx,
1148 const struct server_id pid,
1149 const int argc, const char **argv)
1151 TDB_CONTEXT *tdb;
1152 bool ret = False;
1153 int retry = 0;
1154 char *db_path;
1156 if (argc != 1) {
1157 fprintf(stderr, "Usage: smbcontrol winbindd offline\n");
1158 return False;
1161 db_path = state_path(talloc_tos(), "winbindd_cache.tdb");
1162 if (db_path == NULL) {
1163 return false;
1166 /* Create an entry in the winbindd_cache tdb to tell a later
1167 starting winbindd that we're offline. We may actually create
1168 it here... */
1170 tdb = tdb_open_log(db_path,
1171 WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
1172 TDB_DEFAULT|TDB_INCOMPATIBLE_HASH /* TDB_CLEAR_IF_FIRST */,
1173 O_RDWR|O_CREAT, 0600);
1175 if (!tdb) {
1176 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
1177 db_path);
1178 TALLOC_FREE(db_path);
1179 return False;
1181 TALLOC_FREE(db_path);
1183 /* There's a potential race condition that if a child
1184 winbindd detects a domain is online at the same time
1185 we're trying to tell it to go offline that it might
1186 delete the record we add between us adding it and
1187 sending the message. Minimize this by retrying up to
1188 5 times. */
1190 for (retry = 0; retry < 5; retry++) {
1191 uint8_t buf[4];
1192 TDB_DATA d = { .dptr = buf, .dsize = sizeof(buf) };
1194 SIVAL(buf, 0, time(NULL));
1196 tdb_store_bystring(tdb, "WINBINDD_OFFLINE", d, TDB_INSERT);
1198 ret = send_message(msg_ctx, pid, MSG_WINBIND_OFFLINE,
1199 NULL, 0);
1201 /* Check that the entry "WINBINDD_OFFLINE" still exists. */
1202 d = tdb_fetch_bystring( tdb, "WINBINDD_OFFLINE" );
1203 if (d.dptr != NULL && d.dsize == 4) {
1204 SAFE_FREE(d.dptr);
1205 break;
1208 SAFE_FREE(d.dptr);
1209 DEBUG(10,("do_winbind_offline: offline state not set - retrying.\n"));
1212 tdb_close(tdb);
1213 return ret;
1216 static bool do_winbind_onlinestatus(struct tevent_context *ev_ctx,
1217 struct messaging_context *msg_ctx,
1218 const struct server_id pid,
1219 const int argc, const char **argv)
1221 if (argc != 1) {
1222 fprintf(stderr, "Usage: smbcontrol winbindd onlinestatus\n");
1223 return False;
1226 messaging_register(msg_ctx, NULL, MSG_WINBIND_ONLINESTATUS,
1227 print_pid_string_cb);
1229 if (!send_message(msg_ctx, pid, MSG_WINBIND_ONLINESTATUS, NULL, 0)) {
1230 return False;
1233 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
1235 /* No replies were received within the timeout period */
1237 if (num_replies == 0)
1238 printf("No replies received\n");
1240 messaging_deregister(msg_ctx, MSG_WINBIND_ONLINESTATUS, NULL);
1242 return num_replies;
1245 static bool do_winbind_dump_domain_list(struct tevent_context *ev_ctx,
1246 struct messaging_context *msg_ctx,
1247 const struct server_id pid,
1248 const int argc, const char **argv)
1250 const char *domain = NULL;
1251 int domain_len = 0;
1253 if (argc < 1 || argc > 2) {
1254 fprintf(stderr, "Usage: smbcontrol <dest> dump-domain-list "
1255 "<domain>\n");
1256 return false;
1259 if (argc == 2) {
1260 domain = argv[1];
1261 domain_len = strlen(argv[1]) + 1;
1264 messaging_register(msg_ctx, NULL, MSG_WINBIND_DUMP_DOMAIN_LIST,
1265 print_pid_string_cb);
1267 if (!send_message(msg_ctx, pid, MSG_WINBIND_DUMP_DOMAIN_LIST,
1268 domain, domain_len))
1270 return false;
1273 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
1275 /* No replies were received within the timeout period */
1277 if (num_replies == 0) {
1278 printf("No replies received\n");
1281 messaging_deregister(msg_ctx, MSG_WINBIND_DUMP_DOMAIN_LIST, NULL);
1283 return num_replies;
1286 static bool do_msg_disconnect_dc(struct tevent_context *ev_ctx,
1287 struct messaging_context *msg_ctx,
1288 const struct server_id pid,
1289 const int argc, const char **argv)
1291 if (argc != 1) {
1292 fprintf(stderr, "Usage: smbcontrol <dest> disconnect-dc\n");
1293 return False;
1296 return send_message(msg_ctx, pid, MSG_WINBIND_DISCONNECT_DC, NULL, 0);
1299 static void winbind_validate_cache_cb(struct messaging_context *msg,
1300 void *private_data,
1301 uint32_t msg_type,
1302 struct server_id pid,
1303 DATA_BLOB *data)
1305 struct server_id_buf src_string;
1306 printf("Winbindd cache is %svalid. (answer from pid %s)\n",
1307 (*(data->data) == 0 ? "" : "NOT "),
1308 server_id_str_buf(pid, &src_string));
1309 num_replies++;
1312 static bool do_winbind_validate_cache(struct tevent_context *ev_ctx,
1313 struct messaging_context *msg_ctx,
1314 const struct server_id pid,
1315 const int argc, const char **argv)
1317 struct server_id myid;
1319 myid = messaging_server_id(msg_ctx);
1321 if (argc != 1) {
1322 fprintf(stderr, "Usage: smbcontrol winbindd validate-cache\n");
1323 return False;
1326 messaging_register(msg_ctx, NULL, MSG_WINBIND_VALIDATE_CACHE,
1327 winbind_validate_cache_cb);
1329 if (!send_message(msg_ctx, pid, MSG_WINBIND_VALIDATE_CACHE, &myid,
1330 sizeof(myid))) {
1331 return False;
1334 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
1336 if (num_replies == 0) {
1337 printf("No replies received\n");
1340 messaging_deregister(msg_ctx, MSG_WINBIND_VALIDATE_CACHE, NULL);
1342 return num_replies;
1345 static bool do_reload_config(struct tevent_context *ev_ctx,
1346 struct messaging_context *msg_ctx,
1347 const struct server_id pid,
1348 const int argc, const char **argv)
1350 if (argc != 1) {
1351 fprintf(stderr, "Usage: smbcontrol <dest> reload-config\n");
1352 return False;
1355 return send_message(msg_ctx, pid, MSG_SMB_CONF_UPDATED, NULL, 0);
1358 static bool do_reload_printers(struct tevent_context *ev_ctx,
1359 struct messaging_context *msg_ctx,
1360 const struct server_id pid,
1361 const int argc, const char **argv)
1363 if (argc != 1) {
1364 fprintf(stderr, "Usage: smbcontrol <dest> reload-printers\n");
1365 return False;
1368 return send_message(msg_ctx, pid, MSG_PRINTER_PCAP, NULL, 0);
1371 static void my_make_nmb_name( struct nmb_name *n, const char *name, int type)
1373 fstring unix_name;
1374 memset( (char *)n, '\0', sizeof(struct nmb_name) );
1375 fstrcpy(unix_name, name);
1376 (void)strupper_m(unix_name);
1377 push_ascii(n->name, unix_name, sizeof(n->name), STR_TERMINATE);
1378 n->name_type = (unsigned int)type & 0xFF;
1379 push_ascii(n->scope, lp_netbios_scope(), 64, STR_TERMINATE);
1382 static bool do_nodestatus(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 struct packet_struct p;
1389 if (argc != 2) {
1390 fprintf(stderr, "Usage: smbcontrol nmbd nodestatus <ip>\n");
1391 return False;
1394 ZERO_STRUCT(p);
1396 p.ip = interpret_addr2(argv[1]);
1397 p.port = 137;
1398 p.packet_type = NMB_PACKET;
1400 p.packet.nmb.header.name_trn_id = 10;
1401 p.packet.nmb.header.opcode = 0;
1402 p.packet.nmb.header.response = False;
1403 p.packet.nmb.header.nm_flags.bcast = False;
1404 p.packet.nmb.header.nm_flags.recursion_available = False;
1405 p.packet.nmb.header.nm_flags.recursion_desired = False;
1406 p.packet.nmb.header.nm_flags.trunc = False;
1407 p.packet.nmb.header.nm_flags.authoritative = False;
1408 p.packet.nmb.header.rcode = 0;
1409 p.packet.nmb.header.qdcount = 1;
1410 p.packet.nmb.header.ancount = 0;
1411 p.packet.nmb.header.nscount = 0;
1412 p.packet.nmb.header.arcount = 0;
1413 my_make_nmb_name(&p.packet.nmb.question.question_name, "*", 0x00);
1414 p.packet.nmb.question.question_type = 0x21;
1415 p.packet.nmb.question.question_class = 0x1;
1417 return send_message(msg_ctx, pid, MSG_SEND_PACKET, &p, sizeof(p));
1420 static bool do_notify_cleanup(struct tevent_context *ev_ctx,
1421 struct messaging_context *msg_ctx,
1422 const struct server_id pid,
1423 const int argc, const char **argv)
1425 if (argc != 1) {
1426 fprintf(stderr, "Usage: smbcontrol smbd notify-cleanup\n");
1427 return false;
1429 return send_message(msg_ctx, pid, MSG_SMB_NOTIFY_CLEANUP, NULL, 0);
1432 /* A list of message type supported */
1434 static const struct {
1435 const char *name; /* Option name */
1436 bool (*fn)(struct tevent_context *ev_ctx,
1437 struct messaging_context *msg_ctx,
1438 const struct server_id pid,
1439 const int argc, const char **argv);
1440 const char *help; /* Short help text */
1441 } msg_types[] = {
1443 .name = "debug",
1444 .fn = do_debug,
1445 .help = "Set debuglevel",
1448 .name = "idmap",
1449 .fn = do_idmap,
1450 .help = "Manipulate idmap cache",
1453 .name = "force-election",
1454 .fn = do_election,
1455 .help = "Force a browse election",
1458 .name = "ping",
1459 .fn = do_ping,
1460 .help = "Elicit a response",
1463 .name = "profile",
1464 .fn = do_profile,
1465 .help = "",
1468 .name = "inject",
1469 .fn = do_inject_fault,
1470 .help = "Inject a fatal signal into a running smbd"},
1472 .name = "stacktrace",
1473 .fn = do_daemon_stack_trace,
1474 .help = "Display a stack trace of a daemon",
1477 .name = "profilelevel",
1478 .fn = do_profilelevel,
1479 .help = "",
1482 .name = "debuglevel",
1483 .fn = do_debuglevel,
1484 .help = "Display current debuglevels",
1487 .name = "printnotify",
1488 .fn = do_printnotify,
1489 .help = "Send a print notify message",
1492 .name = "close-share",
1493 .fn = do_closeshare,
1494 .help = "Forcibly disconnect a share",
1497 .name = "close-denied-share",
1498 .fn = do_close_denied_share,
1499 .help = "Forcibly disconnect users from shares disallowed now",
1502 .name = "kill-client-ip",
1503 .fn = do_kill_client_by_ip,
1504 .help = "Forcibly disconnect a client with a specific IP address",
1507 .name = "ip-dropped",
1508 .fn = do_ip_dropped,
1509 .help = "Tell winbind that an IP got dropped",
1512 .name = "pool-usage",
1513 .fn = do_poolusage,
1514 .help = "Display talloc memory usage",
1517 .name = "rpc-dump-status",
1518 .fn = do_rpc_dump_status,
1519 .help = "Display rpc status",
1522 .name = "ringbuf-log",
1523 .fn = do_ringbuflog,
1524 .help = "Display ringbuf log",
1527 .name = "dmalloc-mark",
1528 .fn = do_dmalloc_mark,
1529 .help = "",
1532 .name = "dmalloc-log-changed",
1533 .fn = do_dmalloc_changed,
1534 .help = "",
1537 .name = "shutdown",
1538 .fn = do_shutdown,
1539 .help = "Shut down daemon",
1542 .name = "drvupgrade",
1543 .fn = do_drvupgrade,
1544 .help = "Notify a printer driver has changed",
1547 .name = "reload-config",
1548 .fn = do_reload_config,
1549 .help = "Force smbd or winbindd to reload config file"},
1551 .name = "reload-printers",
1552 .fn = do_reload_printers,
1553 .help = "Force smbd to reload printers"},
1555 .name = "nodestatus",
1556 .fn = do_nodestatus,
1557 .help = "Ask nmbd to do a node status request"},
1559 .name = "online",
1560 .fn = do_winbind_online,
1561 .help = "Ask winbind to go into online state"},
1563 .name = "offline",
1564 .fn = do_winbind_offline,
1565 .help = "Ask winbind to go into offline state"},
1567 .name = "onlinestatus",
1568 .fn = do_winbind_onlinestatus,
1569 .help = "Request winbind online status"},
1571 .name = "validate-cache" ,
1572 .fn = do_winbind_validate_cache,
1573 .help = "Validate winbind's credential cache",
1576 .name = "dump-domain-list",
1577 .fn = do_winbind_dump_domain_list,
1578 .help = "Dump winbind domain list"},
1580 .name = "disconnect-dc",
1581 .fn = do_msg_disconnect_dc,
1584 .name = "notify-cleanup",
1585 .fn = do_notify_cleanup,
1588 .name = "num-children",
1589 .fn = do_num_children,
1590 .help = "Print number of smbd child processes",
1593 .name = "msg-cleanup",
1594 .fn = do_msg_cleanup,
1597 .name = "noop",
1598 .fn = do_noop,
1599 .help = "Do nothing",
1602 .name = "sleep",
1603 .fn = do_sleep,
1604 .help = "Cause the target process to sleep",
1606 { .name = NULL, },
1609 /* Display usage information */
1611 static void usage(poptContext pc)
1613 int i;
1615 poptPrintHelp(pc, stderr, 0);
1617 fprintf(stderr, "\n");
1618 fprintf(stderr, "<destination> is one of \"nmbd\", \"smbd\", \"winbindd\" or a "
1619 "process ID\n");
1621 fprintf(stderr, "\n");
1622 fprintf(stderr, "<message-type> is one of:\n");
1624 for (i = 0; msg_types[i].name; i++) {
1625 const char *help = msg_types[i].help;
1626 if (help == NULL) {
1627 help = "";
1629 fprintf(stderr, "\t%-30s%s\n", msg_types[i].name, help);
1632 fprintf(stderr, "\n");
1634 exit(1);
1637 /* Return the pid number for a string destination */
1639 static struct server_id parse_dest(struct messaging_context *msg,
1640 const char *dest)
1642 struct server_id result = {
1643 .pid = (uint64_t)-1,
1645 pid_t pid;
1646 struct server_id_db *names_db = NULL;
1647 bool ok;
1649 /* Zero is a special return value for broadcast to all processes */
1651 if (strequal(dest, "all")) {
1652 return interpret_pid(MSG_BROADCAST_PID_STR);
1655 /* Try self - useful for testing */
1657 if (strequal(dest, "self")) {
1658 return messaging_server_id(msg);
1661 /* Fix winbind typo. */
1662 if (strequal(dest, "winbind")) {
1663 dest = "winbindd";
1666 /* Check for numeric pid number */
1667 result = interpret_pid(dest);
1669 /* Zero isn't valid if not "all". */
1670 if (result.pid && procid_valid(&result)) {
1671 return result;
1674 /* Look up other destinations in pidfile directory */
1676 if ((pid = pidfile_pid(lp_pid_directory(), dest)) != 0) {
1677 return pid_to_procid(pid);
1680 names_db = messaging_names_db(msg);
1681 if (names_db == NULL) {
1682 goto fail;
1684 ok = server_id_db_lookup_one(names_db, dest, &result);
1685 if (ok) {
1686 return result;
1689 fail:
1690 fprintf(stderr,"Can't find pid for destination '%s'\n", dest);
1692 return result;
1695 /* Execute smbcontrol command */
1697 static bool do_command(struct tevent_context *ev_ctx,
1698 struct messaging_context *msg_ctx,
1699 int argc, const char **argv)
1701 const char *dest = argv[0], *command = argv[1];
1702 struct server_id pid;
1703 int i;
1705 /* Check destination */
1707 pid = parse_dest(msg_ctx, dest);
1708 if (!procid_valid(&pid)) {
1709 return False;
1712 /* Check command */
1714 for (i = 0; msg_types[i].name; i++) {
1715 if (strequal(command, msg_types[i].name))
1716 return msg_types[i].fn(ev_ctx, msg_ctx, pid,
1717 argc - 1, argv + 1);
1720 fprintf(stderr, "smbcontrol: unknown command '%s'\n", command);
1722 return False;
1725 static void smbcontrol_help(poptContext pc,
1726 enum poptCallbackReason preason,
1727 struct poptOption * poption,
1728 const char * parg,
1729 void * pdata)
1731 if (poption->shortName != '?') {
1732 poptPrintUsage(pc, stdout, 0);
1733 } else {
1734 usage(pc);
1737 exit(0);
1740 struct poptOption help_options[] = {
1741 { NULL, '\0', POPT_ARG_CALLBACK, (void *)&smbcontrol_help, '\0',
1742 NULL, NULL },
1743 { "help", '?', 0, NULL, '?', "Show this help message", NULL },
1744 { "usage", '\0', 0, NULL, 'u', "Display brief usage message", NULL },
1748 /* Main program */
1750 int main(int argc, const char **argv)
1752 poptContext pc;
1753 int opt;
1754 struct tevent_context *evt_ctx;
1755 struct messaging_context *msg_ctx;
1757 struct poptOption long_options[] = {
1758 /* POPT_AUTOHELP */
1759 { NULL, '\0', POPT_ARG_INCLUDE_TABLE, help_options,
1760 0, "Help options:", NULL },
1761 { "timeout", 't', POPT_ARG_INT, &timeout, 't',
1762 "Set timeout value in seconds", "TIMEOUT" },
1764 POPT_COMMON_SAMBA
1765 POPT_COMMON_VERSION
1766 POPT_TABLEEND
1768 TALLOC_CTX *frame = talloc_stackframe();
1769 int ret = 0;
1770 bool ok;
1772 smb_init_locale();
1774 ok = samba_cmdline_init(frame,
1775 SAMBA_CMDLINE_CONFIG_CLIENT,
1776 false /* require_smbconf */);
1777 if (!ok) {
1778 DBG_ERR("Failed to init cmdline parser!\n");
1779 TALLOC_FREE(frame);
1780 exit(1);
1782 lp_set_cmdline("log level", "0");
1784 /* Parse command line arguments using popt */
1786 pc = samba_popt_get_context(getprogname(),
1787 argc,
1788 argv,
1789 long_options,
1791 if (pc == NULL) {
1792 DBG_ERR("Failed to setup popt context!\n");
1793 TALLOC_FREE(frame);
1794 exit(1);
1797 poptSetOtherOptionHelp(pc, "[OPTION...] <destination> <message-type> "
1798 "<parameters>");
1800 if (argc == 1)
1801 usage(pc);
1803 while ((opt = poptGetNextOpt(pc)) != -1) {
1804 switch(opt) {
1805 case 't': /* --timeout */
1806 break;
1807 default:
1808 fprintf(stderr, "Invalid option\n");
1809 poptPrintHelp(pc, stderr, 0);
1810 break;
1814 /* We should now have the remaining command line arguments in
1815 argv. The argc parameter should have been decremented to the
1816 correct value in the above switch statement. */
1818 argv = (const char **)poptGetArgs(pc);
1819 argc = 0;
1820 if (argv != NULL) {
1821 while (argv[argc] != NULL) {
1822 argc++;
1826 if (argc <= 1)
1827 usage(pc);
1829 msg_ctx = cmdline_messaging_context(get_dyn_CONFIGFILE());
1830 if (msg_ctx == NULL) {
1831 fprintf(stderr,
1832 "Could not init messaging context, not root?\n");
1833 TALLOC_FREE(frame);
1834 exit(1);
1837 evt_ctx = global_event_context();
1839 /* Need to invert sense of return code -- samba
1840 * routines mostly return True==1 for success, but
1841 * shell needs 0. */
1843 ret = !do_command(evt_ctx, msg_ctx, argc, argv);
1845 cmdline_messaging_context_free();
1846 poptFreeContext(pc);
1847 TALLOC_FREE(frame);
1848 return ret;