messaging3: Make messaging_dgm_cleanup return 0/errno
[Samba.git] / source3 / utils / smbcontrol.c
blobd11adc666e5ad2481f7ef3e9a9f38824ed054b64
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 "popt_common.h"
29 #include "librpc/gen_ndr/spoolss.h"
30 #include "nt_printing.h"
31 #include "printing/notify.h"
32 #include "libsmb/nmblib.h"
33 #include "messages.h"
34 #include "util_tdb.h"
35 #include "../lib/util/pidfile.h"
36 #include "serverid.h"
38 #if HAVE_LIBUNWIND_H
39 #include <libunwind.h>
40 #endif
42 #if HAVE_LIBUNWIND_PTRACE_H
43 #include <libunwind-ptrace.h>
44 #endif
46 #if HAVE_SYS_PTRACE_H
47 #include <sys/ptrace.h>
48 #endif
50 /* Default timeout value when waiting for replies (in seconds) */
52 #define DEFAULT_TIMEOUT 10
54 static int timeout = DEFAULT_TIMEOUT;
55 static int num_replies; /* Used by message callback fns */
57 /* Send a message to a destination pid. Zero means broadcast smbd. */
59 static bool send_message(struct messaging_context *msg_ctx,
60 struct server_id pid, int msg_type,
61 const void *buf, int len)
63 bool ret;
64 int n_sent = 0;
66 if (procid_to_pid(&pid) != 0)
67 return NT_STATUS_IS_OK(
68 messaging_send_buf(msg_ctx, pid, msg_type,
69 (const uint8 *)buf, len));
71 ret = message_send_all(msg_ctx, msg_type, buf, len, &n_sent);
72 DEBUG(10,("smbcontrol/send_message: broadcast message to "
73 "%d processes\n", n_sent));
75 return ret;
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 char *pidstr;
126 pidstr = server_id_str(talloc_tos(), &pid);
127 printf("PID %s: %.*s", pidstr, (int)data->length,
128 (const char *)data->data);
129 TALLOC_FREE(pidstr);
130 num_replies++;
133 /* Message handler callback that displays a string on stdout */
135 static void print_string_cb(struct messaging_context *msg,
136 void *private_data,
137 uint32_t msg_type,
138 struct server_id pid,
139 DATA_BLOB *data)
141 printf("%*s", (int)data->length, (const char *)data->data);
142 num_replies++;
145 /* Send no message. Useful for testing. */
147 static bool do_noop(struct tevent_context *ev_ctx,
148 struct messaging_context *msg_ctx,
149 const struct server_id pid,
150 const int argc, const char **argv)
152 if (argc != 1) {
153 fprintf(stderr, "Usage: smbcontrol <dest> noop\n");
154 return False;
157 /* Move along, nothing to see here */
159 return True;
162 /* Send a debug string */
164 static bool do_debug(struct tevent_context *ev_ctx,
165 struct messaging_context *msg_ctx,
166 const struct server_id pid,
167 const int argc, const char **argv)
169 if (argc != 2) {
170 fprintf(stderr, "Usage: smbcontrol <dest> debug "
171 "<debug-string>\n");
172 return False;
175 return send_message(msg_ctx, pid, MSG_DEBUG, argv[1],
176 strlen(argv[1]) + 1);
180 static bool do_idmap(struct tevent_context *ev,
181 struct messaging_context *msg_ctx,
182 const struct server_id pid,
183 const int argc, const char **argv)
185 static const char* usage = "Usage: "
186 "smbcontrol <dest> idmap <cmd> [arg]\n"
187 "\tcmd:"
188 "\tdelete \"UID <uid>\"|\"GID <gid>\"|<sid>\n"
189 "\t\tkill \"UID <uid>\"|\"GID <gid>\"|<sid>\n";
190 const char* arg = NULL;
191 int arglen = 0;
192 int msg_type;
194 switch (argc) {
195 case 2:
196 break;
197 case 3:
198 arg = argv[2];
199 arglen = strlen(arg) + 1;
200 break;
201 default:
202 fprintf(stderr, "%s", usage);
203 return false;
206 if (strcmp(argv[1], "delete") == 0) {
207 msg_type = ID_CACHE_DELETE;
209 else if (strcmp(argv[1], "kill") == 0) {
210 msg_type = ID_CACHE_KILL;
212 else if (strcmp(argv[1], "help") == 0) {
213 fprintf(stdout, "%s", usage);
214 return true;
216 else {
217 fprintf(stderr, "%s", usage);
218 return false;
221 return send_message(msg_ctx, pid, msg_type, arg, arglen);
225 #if defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE)
227 /* Return the name of a process given it's PID. This will only work on Linux,
228 * but that's probably moot since this whole stack tracing implementatino is
229 * Linux-specific anyway.
231 static const char * procname(pid_t pid, char * buf, size_t bufsz)
233 char path[64];
234 FILE * fp;
236 snprintf(path, sizeof(path), "/proc/%llu/cmdline",
237 (unsigned long long)pid);
238 if ((fp = fopen(path, "r")) == NULL) {
239 return NULL;
242 fgets(buf, bufsz, fp);
244 fclose(fp);
245 return buf;
248 static void print_stack_trace(pid_t pid, int * count)
250 void * pinfo = NULL;
251 unw_addr_space_t aspace = NULL;
252 unw_cursor_t cursor;
253 unw_word_t ip, sp;
255 char nbuf[256];
256 unw_word_t off;
258 int ret;
260 if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) {
261 fprintf(stderr,
262 "Failed to attach to process %llu: %s\n",
263 (unsigned long long)pid, strerror(errno));
264 return;
267 /* Wait until the attach is complete. */
268 waitpid(pid, NULL, 0);
270 if (((pinfo = _UPT_create(pid)) == NULL) ||
271 ((aspace = unw_create_addr_space(&_UPT_accessors, 0)) == NULL)) {
272 /* Probably out of memory. */
273 fprintf(stderr,
274 "Unable to initialize stack unwind for process %llu\n",
275 (unsigned long long)pid);
276 goto cleanup;
279 if ((ret = unw_init_remote(&cursor, aspace, pinfo))) {
280 fprintf(stderr,
281 "Unable to unwind stack for process %llu: %s\n",
282 (unsigned long long)pid, unw_strerror(ret));
283 goto cleanup;
286 if (*count > 0) {
287 printf("\n");
290 if (procname(pid, nbuf, sizeof(nbuf))) {
291 printf("Stack trace for process %llu (%s):\n",
292 (unsigned long long)pid, nbuf);
293 } else {
294 printf("Stack trace for process %llu:\n",
295 (unsigned long long)pid);
298 while (unw_step(&cursor) > 0) {
299 ip = sp = off = 0;
300 unw_get_reg(&cursor, UNW_REG_IP, &ip);
301 unw_get_reg(&cursor, UNW_REG_SP, &sp);
303 ret = unw_get_proc_name(&cursor, nbuf, sizeof(nbuf), &off);
304 if (ret != 0 && ret != -UNW_ENOMEM) {
305 snprintf(nbuf, sizeof(nbuf), "<unknown symbol>");
307 printf(" %s + %#llx [ip=%#llx] [sp=%#llx]\n",
308 nbuf, (long long)off, (long long)ip,
309 (long long)sp);
312 (*count)++;
314 cleanup:
315 if (aspace) {
316 unw_destroy_addr_space(aspace);
319 if (pinfo) {
320 _UPT_destroy(pinfo);
323 ptrace(PTRACE_DETACH, pid, NULL, NULL);
326 static int stack_trace_server(const struct server_id *id,
327 uint32_t msg_flags,
328 void *priv)
330 if (id->vnn == get_my_vnn()) {
331 print_stack_trace(procid_to_pid(id), (int *)priv);
333 return 0;
336 static bool do_daemon_stack_trace(struct tevent_context *ev_ctx,
337 struct messaging_context *msg_ctx,
338 const struct server_id pid,
339 const int argc, const char **argv)
341 pid_t dest;
342 int count = 0;
344 if (argc != 1) {
345 fprintf(stderr, "Usage: smbcontrol <dest> stacktrace\n");
346 return False;
349 dest = procid_to_pid(&pid);
351 if (dest != 0) {
352 /* It would be nice to be able to make sure that this PID is
353 * the PID of a smbd/winbind/nmbd process, not some random PID
354 * the user liked the look of. It doesn't seem like it's worth
355 * the effort at the moment, however.
357 print_stack_trace(dest, &count);
358 } else {
359 serverid_traverse_read(stack_trace_server, &count);
362 return True;
365 #else /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
367 static bool do_daemon_stack_trace(struct tevent_context *ev_ctx,
368 struct messaging_context *msg_ctx,
369 const struct server_id pid,
370 const int argc, const char **argv)
372 fprintf(stderr,
373 "Daemon stack tracing is not supported on this platform\n");
374 return False;
377 #endif /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
379 /* Inject a fault (fatal signal) into a running smbd */
381 static bool do_inject_fault(struct tevent_context *ev_ctx,
382 struct messaging_context *msg_ctx,
383 const struct server_id pid,
384 const int argc, const char **argv)
386 if (argc != 2) {
387 fprintf(stderr, "Usage: smbcontrol <dest> inject "
388 "<bus|hup|term|internal|segv>\n");
389 return False;
392 #ifndef DEVELOPER
393 fprintf(stderr, "Fault injection is only available in "
394 "developer builds\n");
395 return False;
396 #else /* DEVELOPER */
398 int sig = 0;
400 if (strcmp(argv[1], "bus") == 0) {
401 sig = SIGBUS;
402 } else if (strcmp(argv[1], "hup") == 0) {
403 sig = SIGHUP;
404 } else if (strcmp(argv[1], "term") == 0) {
405 sig = SIGTERM;
406 } else if (strcmp(argv[1], "segv") == 0) {
407 sig = SIGSEGV;
408 } else if (strcmp(argv[1], "internal") == 0) {
409 /* Force an internal error, ie. an unclean exit. */
410 sig = -1;
411 } else {
412 fprintf(stderr, "Unknown signal name '%s'\n", argv[1]);
413 return False;
416 return send_message(msg_ctx, pid, MSG_SMB_INJECT_FAULT,
417 &sig, sizeof(int));
419 #endif /* DEVELOPER */
422 /* Force a browser election */
424 static bool do_election(struct tevent_context *ev_ctx,
425 struct messaging_context *msg_ctx,
426 const struct server_id pid,
427 const int argc, const char **argv)
429 if (argc != 1) {
430 fprintf(stderr, "Usage: smbcontrol <dest> force-election\n");
431 return False;
434 return send_message(msg_ctx, pid, MSG_FORCE_ELECTION, NULL, 0);
437 /* Ping a samba daemon process */
439 static void pong_cb(struct messaging_context *msg,
440 void *private_data,
441 uint32_t msg_type,
442 struct server_id pid,
443 DATA_BLOB *data)
445 char *src_string = server_id_str(NULL, &pid);
446 printf("PONG from pid %s\n", src_string);
447 TALLOC_FREE(src_string);
448 num_replies++;
451 static bool do_ping(struct tevent_context *ev_ctx,
452 struct messaging_context *msg_ctx,
453 const struct server_id pid,
454 const int argc, const char **argv)
456 if (argc != 1) {
457 fprintf(stderr, "Usage: smbcontrol <dest> ping\n");
458 return False;
461 /* Send a message and register our interest in a reply */
463 if (!send_message(msg_ctx, pid, MSG_PING, NULL, 0))
464 return False;
466 messaging_register(msg_ctx, NULL, MSG_PONG, pong_cb);
468 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
470 /* No replies were received within the timeout period */
472 if (num_replies == 0)
473 printf("No replies received\n");
475 messaging_deregister(msg_ctx, MSG_PONG, NULL);
477 return num_replies;
480 /* Set profiling options */
482 static bool do_profile(struct tevent_context *ev_ctx,
483 struct messaging_context *msg_ctx,
484 const struct server_id pid,
485 const int argc, const char **argv)
487 int v;
489 if (argc != 2) {
490 fprintf(stderr, "Usage: smbcontrol <dest> profile "
491 "<off|count|on|flush>\n");
492 return False;
495 if (strcmp(argv[1], "off") == 0) {
496 v = 0;
497 } else if (strcmp(argv[1], "count") == 0) {
498 v = 1;
499 } else if (strcmp(argv[1], "on") == 0) {
500 v = 2;
501 } else if (strcmp(argv[1], "flush") == 0) {
502 v = 3;
503 } else {
504 fprintf(stderr, "Unknown profile command '%s'\n", argv[1]);
505 return False;
508 return send_message(msg_ctx, pid, MSG_PROFILE, &v, sizeof(int));
511 /* Return the profiling level */
513 static void profilelevel_cb(struct messaging_context *msg_ctx,
514 void *private_data,
515 uint32_t msg_type,
516 struct server_id pid,
517 DATA_BLOB *data)
519 int level;
520 const char *s;
522 num_replies++;
524 if (data->length != sizeof(int)) {
525 fprintf(stderr, "invalid message length %ld returned\n",
526 (unsigned long)data->length);
527 return;
530 memcpy(&level, data->data, sizeof(int));
532 switch (level) {
533 case 0:
534 s = "not enabled";
535 break;
536 case 1:
537 s = "off";
538 break;
539 case 3:
540 s = "count only";
541 break;
542 case 7:
543 s = "count and time";
544 break;
545 default:
546 s = "BOGUS";
547 break;
550 printf("Profiling %s on pid %u\n",s,(unsigned int)procid_to_pid(&pid));
553 static void profilelevel_rqst(struct messaging_context *msg_ctx,
554 void *private_data,
555 uint32_t msg_type,
556 struct server_id pid,
557 DATA_BLOB *data)
559 int v = 0;
561 /* Send back a dummy reply */
563 send_message(msg_ctx, pid, MSG_PROFILELEVEL, &v, sizeof(int));
566 static bool do_profilelevel(struct tevent_context *ev_ctx,
567 struct messaging_context *msg_ctx,
568 const struct server_id pid,
569 const int argc, const char **argv)
571 if (argc != 1) {
572 fprintf(stderr, "Usage: smbcontrol <dest> profilelevel\n");
573 return False;
576 /* Send a message and register our interest in a reply */
578 if (!send_message(msg_ctx, pid, MSG_REQ_PROFILELEVEL, NULL, 0))
579 return False;
581 messaging_register(msg_ctx, NULL, MSG_PROFILELEVEL, profilelevel_cb);
582 messaging_register(msg_ctx, NULL, MSG_REQ_PROFILELEVEL,
583 profilelevel_rqst);
585 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
587 /* No replies were received within the timeout period */
589 if (num_replies == 0)
590 printf("No replies received\n");
592 messaging_deregister(msg_ctx, MSG_PROFILE, NULL);
594 return num_replies;
597 /* Display debug level settings */
599 static bool do_debuglevel(struct tevent_context *ev_ctx,
600 struct messaging_context *msg_ctx,
601 const struct server_id pid,
602 const int argc, const char **argv)
604 if (argc != 1) {
605 fprintf(stderr, "Usage: smbcontrol <dest> debuglevel\n");
606 return False;
609 /* Send a message and register our interest in a reply */
611 if (!send_message(msg_ctx, pid, MSG_REQ_DEBUGLEVEL, NULL, 0))
612 return False;
614 messaging_register(msg_ctx, NULL, MSG_DEBUGLEVEL, print_pid_string_cb);
616 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
618 /* No replies were received within the timeout period */
620 if (num_replies == 0)
621 printf("No replies received\n");
623 messaging_deregister(msg_ctx, MSG_DEBUGLEVEL, NULL);
625 return num_replies;
628 /* Send a print notify message */
630 static bool do_printnotify(struct tevent_context *ev_ctx,
631 struct messaging_context *msg_ctx,
632 const struct server_id pid,
633 const int argc, const char **argv)
635 const char *cmd;
637 /* Check for subcommand */
639 if (argc == 1) {
640 fprintf(stderr, "Must specify subcommand:\n");
641 fprintf(stderr, "\tqueuepause <printername>\n");
642 fprintf(stderr, "\tqueueresume <printername>\n");
643 fprintf(stderr, "\tjobpause <printername> <unix jobid>\n");
644 fprintf(stderr, "\tjobresume <printername> <unix jobid>\n");
645 fprintf(stderr, "\tjobdelete <printername> <unix jobid>\n");
646 fprintf(stderr, "\tprinter <printername> <comment|port|"
647 "driver> <value>\n");
649 return False;
652 cmd = argv[1];
654 if (strcmp(cmd, "queuepause") == 0) {
656 if (argc != 3) {
657 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
658 " queuepause <printername>\n");
659 return False;
662 notify_printer_status_byname(ev_ctx, msg_ctx, argv[2],
663 PRINTER_STATUS_PAUSED);
665 goto send;
667 } else if (strcmp(cmd, "queueresume") == 0) {
669 if (argc != 3) {
670 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
671 " queuereume <printername>\n");
672 return False;
675 notify_printer_status_byname(ev_ctx, msg_ctx, argv[2],
676 PRINTER_STATUS_OK);
678 goto send;
680 } else if (strcmp(cmd, "jobpause") == 0) {
681 int jobid;
683 if (argc != 4) {
684 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
685 " jobpause <printername> <unix-jobid>\n");
686 return False;
689 jobid = atoi(argv[3]);
691 notify_job_status_byname(
692 ev_ctx, msg_ctx,
693 argv[2], jobid, JOB_STATUS_PAUSED,
694 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
696 goto send;
698 } else if (strcmp(cmd, "jobresume") == 0) {
699 int jobid;
701 if (argc != 4) {
702 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
703 " jobpause <printername> <unix-jobid>\n");
704 return False;
707 jobid = atoi(argv[3]);
709 notify_job_status_byname(
710 ev_ctx, msg_ctx,
711 argv[2], jobid, JOB_STATUS_QUEUED,
712 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
714 goto send;
716 } else if (strcmp(cmd, "jobdelete") == 0) {
717 int jobid;
719 if (argc != 4) {
720 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
721 " jobpause <printername> <unix-jobid>\n");
722 return False;
725 jobid = atoi(argv[3]);
727 notify_job_status_byname(
728 ev_ctx, msg_ctx,
729 argv[2], jobid, JOB_STATUS_DELETING,
730 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
732 notify_job_status_byname(
733 ev_ctx, msg_ctx,
734 argv[2], jobid, JOB_STATUS_DELETING|
735 JOB_STATUS_DELETED,
736 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
738 goto send;
740 } else if (strcmp(cmd, "printer") == 0) {
741 uint32 attribute;
743 if (argc != 5) {
744 fprintf(stderr, "Usage: smbcontrol <dest> printnotify "
745 "printer <printername> <comment|port|driver> "
746 "<value>\n");
747 return False;
750 if (strcmp(argv[3], "comment") == 0) {
751 attribute = PRINTER_NOTIFY_FIELD_COMMENT;
752 } else if (strcmp(argv[3], "port") == 0) {
753 attribute = PRINTER_NOTIFY_FIELD_PORT_NAME;
754 } else if (strcmp(argv[3], "driver") == 0) {
755 attribute = PRINTER_NOTIFY_FIELD_DRIVER_NAME;
756 } else {
757 fprintf(stderr, "Invalid printer command '%s'\n",
758 argv[3]);
759 return False;
762 notify_printer_byname(ev_ctx, msg_ctx, argv[2], attribute,
763 discard_const_p(char, argv[4]));
765 goto send;
768 fprintf(stderr, "Invalid subcommand '%s'\n", cmd);
769 return False;
771 send:
772 print_notify_send_messages(msg_ctx, 0);
773 return True;
776 /* Close a share */
778 static bool do_closeshare(struct tevent_context *ev_ctx,
779 struct messaging_context *msg_ctx,
780 const struct server_id pid,
781 const int argc, const char **argv)
783 if (argc != 2) {
784 fprintf(stderr, "Usage: smbcontrol <dest> close-share "
785 "<sharename>\n");
786 return False;
789 return send_message(msg_ctx, pid, MSG_SMB_FORCE_TDIS, argv[1],
790 strlen(argv[1]) + 1);
793 /* Kill a client by IP address */
794 static bool do_kill_client_by_ip(struct tevent_context *ev_ctx,
795 struct messaging_context *msg_ctx,
796 const struct server_id pid,
797 const int argc, const char **argv)
799 if (argc != 2) {
800 fprintf(stderr, "Usage: smbcontrol <dest> kill-client-ip "
801 "<IP address>\n");
802 return false;
805 if (!is_ipaddress_v4(argv[1]) && !is_ipaddress_v6(argv[1])) {
806 fprintf(stderr, "%s is not a valid IP address!\n", argv[1]);
807 return false;
810 return send_message(msg_ctx, pid, MSG_SMB_KILL_CLIENT_IP,
811 argv[1], strlen(argv[1]) + 1);
814 /* Tell winbindd an IP got dropped */
816 static bool do_ip_dropped(struct tevent_context *ev_ctx,
817 struct messaging_context *msg_ctx,
818 const struct server_id pid,
819 const int argc, const char **argv)
821 if (argc != 2) {
822 fprintf(stderr, "Usage: smbcontrol <dest> ip-dropped "
823 "<ip-address>\n");
824 return False;
827 return send_message(msg_ctx, pid, MSG_WINBIND_IP_DROPPED, argv[1],
828 strlen(argv[1]) + 1);
831 /* force a blocking lock retry */
833 static bool do_lockretry(struct tevent_context *ev_ctx,
834 struct messaging_context *msg_ctx,
835 const struct server_id pid,
836 const int argc, const char **argv)
838 if (argc != 1) {
839 fprintf(stderr, "Usage: smbcontrol <dest> lockretry\n");
840 return False;
843 return send_message(msg_ctx, pid, MSG_SMB_UNLOCK, NULL, 0);
846 /* force a validation of all brl entries, including re-sends. */
848 static bool do_brl_revalidate(struct tevent_context *ev_ctx,
849 struct messaging_context *msg_ctx,
850 const struct server_id pid,
851 const int argc, const char **argv)
853 if (argc != 1) {
854 fprintf(stderr, "Usage: smbcontrol <dest> brl-revalidate\n");
855 return False;
858 return send_message(msg_ctx, pid, MSG_SMB_BRL_VALIDATE, NULL, 0);
861 /* Display talloc pool usage */
863 static bool do_poolusage(struct tevent_context *ev_ctx,
864 struct messaging_context *msg_ctx,
865 const struct server_id pid,
866 const int argc, const char **argv)
868 if (argc != 1) {
869 fprintf(stderr, "Usage: smbcontrol <dest> pool-usage\n");
870 return False;
873 messaging_register(msg_ctx, NULL, MSG_POOL_USAGE, print_string_cb);
875 /* Send a message and register our interest in a reply */
877 if (!send_message(msg_ctx, pid, MSG_REQ_POOL_USAGE, NULL, 0))
878 return False;
880 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
882 /* No replies were received within the timeout period */
884 if (num_replies == 0)
885 printf("No replies received\n");
887 messaging_deregister(msg_ctx, MSG_POOL_USAGE, NULL);
889 return num_replies;
892 /* Perform a dmalloc mark */
894 static bool do_dmalloc_mark(struct tevent_context *ev_ctx,
895 struct messaging_context *msg_ctx,
896 const struct server_id pid,
897 const int argc, const char **argv)
899 if (argc != 1) {
900 fprintf(stderr, "Usage: smbcontrol <dest> dmalloc-mark\n");
901 return False;
904 return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_MARK, NULL, 0);
907 /* Perform a dmalloc changed */
909 static bool do_dmalloc_changed(struct tevent_context *ev_ctx,
910 struct messaging_context *msg_ctx,
911 const struct server_id pid,
912 const int argc, const char **argv)
914 if (argc != 1) {
915 fprintf(stderr, "Usage: smbcontrol <dest> "
916 "dmalloc-log-changed\n");
917 return False;
920 return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_LOG_CHANGED,
921 NULL, 0);
924 static void print_uint32_cb(struct messaging_context *msg, void *private_data,
925 uint32_t msg_type, struct server_id pid,
926 DATA_BLOB *data)
928 uint32_t num_children;
930 if (data->length != sizeof(uint32_t)) {
931 printf("Invalid response: %d bytes long\n",
932 (int)data->length);
933 goto done;
935 num_children = IVAL(data->data, 0);
936 printf("%u children\n", (unsigned)num_children);
937 done:
938 num_replies++;
941 static bool do_num_children(struct tevent_context *ev_ctx,
942 struct messaging_context *msg_ctx,
943 const struct server_id pid,
944 const int argc, const char **argv)
946 if (argc != 1) {
947 fprintf(stderr, "Usage: smbcontrol <dest> num-children\n");
948 return False;
951 messaging_register(msg_ctx, NULL, MSG_SMB_NUM_CHILDREN,
952 print_uint32_cb);
954 /* Send a message and register our interest in a reply */
956 if (!send_message(msg_ctx, pid, MSG_SMB_TELL_NUM_CHILDREN, NULL, 0))
957 return false;
959 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
961 /* No replies were received within the timeout period */
963 if (num_replies == 0)
964 printf("No replies received\n");
966 messaging_deregister(msg_ctx, MSG_SMB_NUM_CHILDREN, NULL);
968 return num_replies;
971 static bool do_dgm_cleanup(struct tevent_context *ev_ctx,
972 struct messaging_context *msg_ctx,
973 const struct server_id pid,
974 const int argc, const char **argv)
976 NTSTATUS status = NT_STATUS_OK;
978 if (pid.pid != 0) {
979 int ret;
980 ret = messaging_dgm_cleanup(msg_ctx, pid.pid);
981 if (ret != 0) {
982 status = map_nt_error_from_unix(ret);
984 } else {
985 status = messaging_dgm_wipe(msg_ctx);
988 printf("cleanup(%u) returned %s\n", (unsigned)pid.pid,
989 nt_errstr(status));
991 return NT_STATUS_IS_OK(status);
994 /* Shutdown a server process */
996 static bool do_shutdown(struct tevent_context *ev_ctx,
997 struct messaging_context *msg_ctx,
998 const struct server_id pid,
999 const int argc, const char **argv)
1001 if (argc != 1) {
1002 fprintf(stderr, "Usage: smbcontrol <dest> shutdown\n");
1003 return False;
1006 return send_message(msg_ctx, pid, MSG_SHUTDOWN, NULL, 0);
1009 /* Notify a driver upgrade */
1011 static bool do_drvupgrade(struct tevent_context *ev_ctx,
1012 struct messaging_context *msg_ctx,
1013 const struct server_id pid,
1014 const int argc, const char **argv)
1016 if (argc != 2) {
1017 fprintf(stderr, "Usage: smbcontrol <dest> drvupgrade "
1018 "<driver-name>\n");
1019 return False;
1022 return send_message(msg_ctx, pid, MSG_PRINTER_DRVUPGRADE, argv[1],
1023 strlen(argv[1]) + 1);
1026 static bool do_winbind_online(struct tevent_context *ev_ctx,
1027 struct messaging_context *msg_ctx,
1028 const struct server_id pid,
1029 const int argc, const char **argv)
1031 TDB_CONTEXT *tdb;
1033 if (argc != 1) {
1034 fprintf(stderr, "Usage: smbcontrol winbindd online\n");
1035 return False;
1038 /* Remove the entry in the winbindd_cache tdb to tell a later
1039 starting winbindd that we're online. */
1041 tdb = tdb_open_log(state_path("winbindd_cache.tdb"), 0, TDB_DEFAULT, O_RDWR, 0600);
1042 if (!tdb) {
1043 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
1044 state_path("winbindd_cache.tdb"));
1045 return False;
1048 tdb_delete_bystring(tdb, "WINBINDD_OFFLINE");
1049 tdb_close(tdb);
1051 return send_message(msg_ctx, pid, MSG_WINBIND_ONLINE, NULL, 0);
1054 static bool do_winbind_offline(struct tevent_context *ev_ctx,
1055 struct messaging_context *msg_ctx,
1056 const struct server_id pid,
1057 const int argc, const char **argv)
1059 TDB_CONTEXT *tdb;
1060 bool ret = False;
1061 int retry = 0;
1063 if (argc != 1) {
1064 fprintf(stderr, "Usage: smbcontrol winbindd offline\n");
1065 return False;
1068 /* Create an entry in the winbindd_cache tdb to tell a later
1069 starting winbindd that we're offline. We may actually create
1070 it here... */
1072 tdb = tdb_open_log(state_path("winbindd_cache.tdb"),
1073 WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
1074 TDB_DEFAULT|TDB_INCOMPATIBLE_HASH /* TDB_CLEAR_IF_FIRST */,
1075 O_RDWR|O_CREAT, 0600);
1077 if (!tdb) {
1078 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
1079 state_path("winbindd_cache.tdb"));
1080 return False;
1083 /* There's a potential race condition that if a child
1084 winbindd detects a domain is online at the same time
1085 we're trying to tell it to go offline that it might
1086 delete the record we add between us adding it and
1087 sending the message. Minimize this by retrying up to
1088 5 times. */
1090 for (retry = 0; retry < 5; retry++) {
1091 TDB_DATA d;
1092 uint8 buf[4];
1094 ZERO_STRUCT(d);
1096 SIVAL(buf, 0, time(NULL));
1097 d.dptr = buf;
1098 d.dsize = 4;
1100 tdb_store_bystring(tdb, "WINBINDD_OFFLINE", d, TDB_INSERT);
1102 ret = send_message(msg_ctx, pid, MSG_WINBIND_OFFLINE,
1103 NULL, 0);
1105 /* Check that the entry "WINBINDD_OFFLINE" still exists. */
1106 d = tdb_fetch_bystring( tdb, "WINBINDD_OFFLINE" );
1108 if (!d.dptr || d.dsize != 4) {
1109 SAFE_FREE(d.dptr);
1110 DEBUG(10,("do_winbind_offline: offline state not set - retrying.\n"));
1111 } else {
1112 SAFE_FREE(d.dptr);
1113 break;
1117 tdb_close(tdb);
1118 return ret;
1121 static bool do_winbind_onlinestatus(struct tevent_context *ev_ctx,
1122 struct messaging_context *msg_ctx,
1123 const struct server_id pid,
1124 const int argc, const char **argv)
1126 struct server_id myid;
1128 myid = messaging_server_id(msg_ctx);
1130 if (argc != 1) {
1131 fprintf(stderr, "Usage: smbcontrol winbindd onlinestatus\n");
1132 return False;
1135 messaging_register(msg_ctx, NULL, MSG_WINBIND_ONLINESTATUS,
1136 print_pid_string_cb);
1138 if (!send_message(msg_ctx, pid, MSG_WINBIND_ONLINESTATUS, &myid,
1139 sizeof(myid)))
1140 return False;
1142 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
1144 /* No replies were received within the timeout period */
1146 if (num_replies == 0)
1147 printf("No replies received\n");
1149 messaging_deregister(msg_ctx, MSG_WINBIND_ONLINESTATUS, NULL);
1151 return num_replies;
1154 static bool do_dump_event_list(struct tevent_context *ev_ctx,
1155 struct messaging_context *msg_ctx,
1156 const struct server_id pid,
1157 const int argc, const char **argv)
1159 if (argc != 1) {
1160 fprintf(stderr, "Usage: smbcontrol <dest> dump-event-list\n");
1161 return False;
1164 return send_message(msg_ctx, pid, MSG_DUMP_EVENT_LIST, NULL, 0);
1167 static bool do_winbind_dump_domain_list(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 const char *domain = NULL;
1173 int domain_len = 0;
1174 struct server_id myid;
1175 uint8_t *buf = NULL;
1176 int buf_len = 0;
1178 myid = messaging_server_id(msg_ctx);
1180 if (argc < 1 || argc > 2) {
1181 fprintf(stderr, "Usage: smbcontrol <dest> dump-domain-list "
1182 "<domain>\n");
1183 return false;
1186 if (argc == 2) {
1187 domain = argv[1];
1188 domain_len = strlen(argv[1]) + 1;
1191 messaging_register(msg_ctx, NULL, MSG_WINBIND_DUMP_DOMAIN_LIST,
1192 print_pid_string_cb);
1194 buf_len = sizeof(myid)+domain_len;
1195 buf = SMB_MALLOC_ARRAY(uint8_t, buf_len);
1196 if (!buf) {
1197 return false;
1200 memcpy(buf, &myid, sizeof(myid));
1201 memcpy(&buf[sizeof(myid)], domain, domain_len);
1203 if (!send_message(msg_ctx, pid, MSG_WINBIND_DUMP_DOMAIN_LIST,
1204 buf, buf_len))
1206 SAFE_FREE(buf);
1207 return false;
1210 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
1212 /* No replies were received within the timeout period */
1214 SAFE_FREE(buf);
1215 if (num_replies == 0) {
1216 printf("No replies received\n");
1219 messaging_deregister(msg_ctx, MSG_WINBIND_DUMP_DOMAIN_LIST, NULL);
1221 return num_replies;
1224 static void winbind_validate_cache_cb(struct messaging_context *msg,
1225 void *private_data,
1226 uint32_t msg_type,
1227 struct server_id pid,
1228 DATA_BLOB *data)
1230 char *src_string = server_id_str(NULL, &pid);
1231 printf("Winbindd cache is %svalid. (answer from pid %s)\n",
1232 (*(data->data) == 0 ? "" : "NOT "), src_string);
1233 TALLOC_FREE(src_string);
1234 num_replies++;
1237 static bool do_winbind_validate_cache(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 struct server_id myid;
1244 myid = messaging_server_id(msg_ctx);
1246 if (argc != 1) {
1247 fprintf(stderr, "Usage: smbcontrol winbindd validate-cache\n");
1248 return False;
1251 messaging_register(msg_ctx, NULL, MSG_WINBIND_VALIDATE_CACHE,
1252 winbind_validate_cache_cb);
1254 if (!send_message(msg_ctx, pid, MSG_WINBIND_VALIDATE_CACHE, &myid,
1255 sizeof(myid))) {
1256 return False;
1259 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
1261 if (num_replies == 0) {
1262 printf("No replies received\n");
1265 messaging_deregister(msg_ctx, MSG_WINBIND_VALIDATE_CACHE, NULL);
1267 return num_replies;
1270 static bool do_reload_config(struct tevent_context *ev_ctx,
1271 struct messaging_context *msg_ctx,
1272 const struct server_id pid,
1273 const int argc, const char **argv)
1275 if (argc != 1) {
1276 fprintf(stderr, "Usage: smbcontrol <dest> reload-config\n");
1277 return False;
1280 return send_message(msg_ctx, pid, MSG_SMB_CONF_UPDATED, NULL, 0);
1283 static bool do_reload_printers(struct tevent_context *ev_ctx,
1284 struct messaging_context *msg_ctx,
1285 const struct server_id pid,
1286 const int argc, const char **argv)
1288 if (argc != 1) {
1289 fprintf(stderr, "Usage: smbcontrol <dest> reload-printers\n");
1290 return False;
1293 return send_message(msg_ctx, pid, MSG_PRINTER_PCAP, NULL, 0);
1296 static void my_make_nmb_name( struct nmb_name *n, const char *name, int type)
1298 fstring unix_name;
1299 memset( (char *)n, '\0', sizeof(struct nmb_name) );
1300 fstrcpy(unix_name, name);
1301 (void)strupper_m(unix_name);
1302 push_ascii(n->name, unix_name, sizeof(n->name), STR_TERMINATE);
1303 n->name_type = (unsigned int)type & 0xFF;
1304 push_ascii(n->scope, lp_netbios_scope(), 64, STR_TERMINATE);
1307 static bool do_nodestatus(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 struct packet_struct p;
1314 if (argc != 2) {
1315 fprintf(stderr, "Usage: smbcontrol nmbd nodestatus <ip>\n");
1316 return False;
1319 ZERO_STRUCT(p);
1321 p.ip = interpret_addr2(argv[1]);
1322 p.port = 137;
1323 p.packet_type = NMB_PACKET;
1325 p.packet.nmb.header.name_trn_id = 10;
1326 p.packet.nmb.header.opcode = 0;
1327 p.packet.nmb.header.response = False;
1328 p.packet.nmb.header.nm_flags.bcast = False;
1329 p.packet.nmb.header.nm_flags.recursion_available = False;
1330 p.packet.nmb.header.nm_flags.recursion_desired = False;
1331 p.packet.nmb.header.nm_flags.trunc = False;
1332 p.packet.nmb.header.nm_flags.authoritative = False;
1333 p.packet.nmb.header.rcode = 0;
1334 p.packet.nmb.header.qdcount = 1;
1335 p.packet.nmb.header.ancount = 0;
1336 p.packet.nmb.header.nscount = 0;
1337 p.packet.nmb.header.arcount = 0;
1338 my_make_nmb_name(&p.packet.nmb.question.question_name, "*", 0x00);
1339 p.packet.nmb.question.question_type = 0x21;
1340 p.packet.nmb.question.question_class = 0x1;
1342 return send_message(msg_ctx, pid, MSG_SEND_PACKET, &p, sizeof(p));
1345 static bool do_notify_cleanup(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 smbd notify-cleanup\n");
1352 return false;
1354 return send_message(msg_ctx, pid, MSG_SMB_NOTIFY_CLEANUP, NULL, 0);
1357 /* A list of message type supported */
1359 static const struct {
1360 const char *name; /* Option name */
1361 bool (*fn)(struct tevent_context *ev_ctx,
1362 struct messaging_context *msg_ctx,
1363 const struct server_id pid,
1364 const int argc, const char **argv);
1365 const char *help; /* Short help text */
1366 } msg_types[] = {
1367 { "debug", do_debug, "Set debuglevel" },
1368 { "idmap", do_idmap, "Manipulate idmap cache" },
1369 { "force-election", do_election,
1370 "Force a browse election" },
1371 { "ping", do_ping, "Elicit a response" },
1372 { "profile", do_profile, "" },
1373 { "inject", do_inject_fault,
1374 "Inject a fatal signal into a running smbd"},
1375 { "stacktrace", do_daemon_stack_trace,
1376 "Display a stack trace of a daemon" },
1377 { "profilelevel", do_profilelevel, "" },
1378 { "debuglevel", do_debuglevel, "Display current debuglevels" },
1379 { "printnotify", do_printnotify, "Send a print notify message" },
1380 { "close-share", do_closeshare, "Forcibly disconnect a share" },
1381 { "kill-client-ip", do_kill_client_by_ip,
1382 "Forcibly disconnect a client with a specific IP address" },
1383 { "ip-dropped", do_ip_dropped, "Tell winbind that an IP got dropped" },
1384 { "lockretry", do_lockretry, "Force a blocking lock retry" },
1385 { "brl-revalidate", do_brl_revalidate, "Revalidate all brl entries" },
1386 { "pool-usage", do_poolusage, "Display talloc memory usage" },
1387 { "dmalloc-mark", do_dmalloc_mark, "" },
1388 { "dmalloc-log-changed", do_dmalloc_changed, "" },
1389 { "shutdown", do_shutdown, "Shut down daemon" },
1390 { "drvupgrade", do_drvupgrade, "Notify a printer driver has changed" },
1391 { "reload-config", do_reload_config, "Force smbd or winbindd to reload config file"},
1392 { "reload-printers", do_reload_printers, "Force smbd to reload printers"},
1393 { "nodestatus", do_nodestatus, "Ask nmbd to do a node status request"},
1394 { "online", do_winbind_online, "Ask winbind to go into online state"},
1395 { "offline", do_winbind_offline, "Ask winbind to go into offline state"},
1396 { "onlinestatus", do_winbind_onlinestatus, "Request winbind online status"},
1397 { "dump-event-list", do_dump_event_list, "Dump event list"},
1398 { "validate-cache" , do_winbind_validate_cache,
1399 "Validate winbind's credential cache" },
1400 { "dump-domain-list", do_winbind_dump_domain_list, "Dump winbind domain list"},
1401 { "notify-cleanup", do_notify_cleanup },
1402 { "num-children", do_num_children,
1403 "Print number of smbd child processes" },
1404 { "dgm-cleanup", do_dgm_cleanup },
1405 { "noop", do_noop, "Do nothing" },
1406 { NULL }
1409 /* Display usage information */
1411 static void usage(poptContext pc)
1413 int i;
1415 poptPrintHelp(pc, stderr, 0);
1417 fprintf(stderr, "\n");
1418 fprintf(stderr, "<destination> is one of \"nmbd\", \"smbd\", \"winbindd\" or a "
1419 "process ID\n");
1421 fprintf(stderr, "\n");
1422 fprintf(stderr, "<message-type> is one of:\n");
1424 for (i = 0; msg_types[i].name; i++)
1425 fprintf(stderr, "\t%-30s%s\n", msg_types[i].name,
1426 msg_types[i].help);
1428 fprintf(stderr, "\n");
1430 exit(1);
1433 /* Return the pid number for a string destination */
1435 static struct server_id parse_dest(struct messaging_context *msg,
1436 const char *dest)
1438 struct server_id result = {-1};
1439 pid_t pid;
1441 /* Zero is a special return value for broadcast to all processes */
1443 if (strequal(dest, "all")) {
1444 return interpret_pid(MSG_BROADCAST_PID_STR);
1447 /* Try self - useful for testing */
1449 if (strequal(dest, "self")) {
1450 return messaging_server_id(msg);
1453 /* Fix winbind typo. */
1454 if (strequal(dest, "winbind")) {
1455 dest = "winbindd";
1458 /* Check for numeric pid number */
1459 result = interpret_pid(dest);
1461 /* Zero isn't valid if not "all". */
1462 if (result.pid && procid_valid(&result)) {
1463 return result;
1466 /* Look up other destinations in pidfile directory */
1468 if ((pid = pidfile_pid(lp_pid_directory(), dest)) != 0) {
1469 return pid_to_procid(pid);
1472 fprintf(stderr,"Can't find pid for destination '%s'\n", dest);
1474 return result;
1477 /* Execute smbcontrol command */
1479 static bool do_command(struct tevent_context *ev_ctx,
1480 struct messaging_context *msg_ctx,
1481 int argc, const char **argv)
1483 const char *dest = argv[0], *command = argv[1];
1484 struct server_id pid;
1485 int i;
1487 /* Check destination */
1489 pid = parse_dest(msg_ctx, dest);
1490 if (!procid_valid(&pid)) {
1491 return False;
1494 /* Check command */
1496 for (i = 0; msg_types[i].name; i++) {
1497 if (strequal(command, msg_types[i].name))
1498 return msg_types[i].fn(ev_ctx, msg_ctx, pid,
1499 argc - 1, argv + 1);
1502 fprintf(stderr, "smbcontrol: unknown command '%s'\n", command);
1504 return False;
1507 static void smbcontrol_help(poptContext pc,
1508 enum poptCallbackReason preason,
1509 struct poptOption * poption,
1510 const char * parg,
1511 void * pdata)
1513 if (poption->shortName != '?') {
1514 poptPrintUsage(pc, stdout, 0);
1515 } else {
1516 usage(pc);
1519 exit(0);
1522 struct poptOption help_options[] = {
1523 { NULL, '\0', POPT_ARG_CALLBACK, (void *)&smbcontrol_help, '\0',
1524 NULL, NULL },
1525 { "help", '?', 0, NULL, '?', "Show this help message", NULL },
1526 { "usage", '\0', 0, NULL, 'u', "Display brief usage message", NULL },
1527 { NULL }
1530 /* Main program */
1532 int main(int argc, const char **argv)
1534 poptContext pc;
1535 int opt;
1536 struct tevent_context *evt_ctx;
1537 struct messaging_context *msg_ctx;
1539 static struct poptOption long_options[] = {
1540 /* POPT_AUTOHELP */
1541 { NULL, '\0', POPT_ARG_INCLUDE_TABLE, help_options,
1542 0, "Help options:", NULL },
1543 { "timeout", 't', POPT_ARG_INT, &timeout, 't',
1544 "Set timeout value in seconds", "TIMEOUT" },
1546 POPT_COMMON_SAMBA
1547 POPT_TABLEEND
1549 TALLOC_CTX *frame = talloc_stackframe();
1550 int ret = 0;
1552 load_case_tables();
1554 setup_logging(argv[0], DEBUG_STDOUT);
1556 /* Parse command line arguments using popt */
1558 pc = poptGetContext(
1559 "smbcontrol", argc, (const char **)argv, long_options, 0);
1561 poptSetOtherOptionHelp(pc, "[OPTION...] <destination> <message-type> "
1562 "<parameters>");
1564 if (argc == 1)
1565 usage(pc);
1567 while ((opt = poptGetNextOpt(pc)) != -1) {
1568 switch(opt) {
1569 case 't': /* --timeout */
1570 break;
1571 default:
1572 fprintf(stderr, "Invalid option\n");
1573 poptPrintHelp(pc, stderr, 0);
1574 break;
1578 /* We should now have the remaining command line arguments in
1579 argv. The argc parameter should have been decremented to the
1580 correct value in the above switch statement. */
1582 argv = (const char **)poptGetArgs(pc);
1583 argc = 0;
1584 if (argv != NULL) {
1585 while (argv[argc] != NULL) {
1586 argc++;
1590 if (argc <= 1)
1591 usage(pc);
1593 lp_load_global(get_dyn_CONFIGFILE());
1595 /* Need to invert sense of return code -- samba
1596 * routines mostly return True==1 for success, but
1597 * shell needs 0. */
1599 if (!(evt_ctx = samba_tevent_context_init(NULL)) ||
1600 !(msg_ctx = messaging_init(NULL, evt_ctx))) {
1601 fprintf(stderr, "could not init messaging context\n");
1602 TALLOC_FREE(frame);
1603 exit(1);
1606 ret = !do_command(evt_ctx, msg_ctx, argc, argv);
1607 TALLOC_FREE(msg_ctx);
1608 TALLOC_FREE(frame);
1609 return ret;