uwrap: Add library constructor and move pthread_atfork inside.
[Samba.git] / source3 / utils / smbcontrol.c
blob9af0f3e25117303f9fa82acbff896c0b570bd7da
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 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 /* Message handler callback that displays a string on stdout */
133 static void print_string_cb(struct messaging_context *msg,
134 void *private_data,
135 uint32_t msg_type,
136 struct server_id pid,
137 DATA_BLOB *data)
139 printf("%*s", (int)data->length, (const char *)data->data);
140 num_replies++;
143 /* Send no message. Useful for testing. */
145 static bool do_noop(struct tevent_context *ev_ctx,
146 struct messaging_context *msg_ctx,
147 const struct server_id pid,
148 const int argc, const char **argv)
150 if (argc != 1) {
151 fprintf(stderr, "Usage: smbcontrol <dest> noop\n");
152 return False;
155 /* Move along, nothing to see here */
157 return True;
160 /* Send a debug string */
162 static bool do_debug(struct tevent_context *ev_ctx,
163 struct messaging_context *msg_ctx,
164 const struct server_id pid,
165 const int argc, const char **argv)
167 if (argc != 2) {
168 fprintf(stderr, "Usage: smbcontrol <dest> debug "
169 "<debug-string>\n");
170 return False;
173 return send_message(msg_ctx, pid, MSG_DEBUG, argv[1],
174 strlen(argv[1]) + 1);
178 static bool do_idmap(struct tevent_context *ev,
179 struct messaging_context *msg_ctx,
180 const struct server_id pid,
181 const int argc, const char **argv)
183 static const char* usage = "Usage: "
184 "smbcontrol <dest> idmap <cmd> [arg]\n"
185 "\tcmd:"
186 "\tdelete \"UID <uid>\"|\"GID <gid>\"|<sid>\n"
187 "\t\tkill \"UID <uid>\"|\"GID <gid>\"|<sid>\n";
188 const char* arg = NULL;
189 int arglen = 0;
190 int msg_type;
192 switch (argc) {
193 case 2:
194 break;
195 case 3:
196 arg = argv[2];
197 arglen = strlen(arg) + 1;
198 break;
199 default:
200 fprintf(stderr, "%s", usage);
201 return false;
204 if (strcmp(argv[1], "delete") == 0) {
205 msg_type = ID_CACHE_DELETE;
207 else if (strcmp(argv[1], "kill") == 0) {
208 msg_type = ID_CACHE_KILL;
210 else if (strcmp(argv[1], "help") == 0) {
211 fprintf(stdout, "%s", usage);
212 return true;
214 else {
215 fprintf(stderr, "%s", usage);
216 return false;
219 return send_message(msg_ctx, pid, msg_type, arg, arglen);
223 #if defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE)
225 /* Return the name of a process given it's PID. This will only work on Linux,
226 * but that's probably moot since this whole stack tracing implementation is
227 * Linux-specific anyway.
229 static const char * procname(pid_t pid, char * buf, size_t bufsz)
231 char path[64];
232 FILE * fp;
234 snprintf(path, sizeof(path), "/proc/%llu/cmdline",
235 (unsigned long long)pid);
236 if ((fp = fopen(path, "r")) == NULL) {
237 return NULL;
240 fgets(buf, bufsz, fp);
242 fclose(fp);
243 return buf;
246 static void print_stack_trace(pid_t pid, int * count)
248 void * pinfo = NULL;
249 unw_addr_space_t aspace = NULL;
250 unw_cursor_t cursor;
251 unw_word_t ip, sp;
253 char nbuf[256];
254 unw_word_t off;
256 int ret;
258 if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) {
259 fprintf(stderr,
260 "Failed to attach to process %llu: %s\n",
261 (unsigned long long)pid, strerror(errno));
262 return;
265 /* Wait until the attach is complete. */
266 waitpid(pid, NULL, 0);
268 if (((pinfo = _UPT_create(pid)) == NULL) ||
269 ((aspace = unw_create_addr_space(&_UPT_accessors, 0)) == NULL)) {
270 /* Probably out of memory. */
271 fprintf(stderr,
272 "Unable to initialize stack unwind for process %llu\n",
273 (unsigned long long)pid);
274 goto cleanup;
277 if ((ret = unw_init_remote(&cursor, aspace, pinfo))) {
278 fprintf(stderr,
279 "Unable to unwind stack for process %llu: %s\n",
280 (unsigned long long)pid, unw_strerror(ret));
281 goto cleanup;
284 if (*count > 0) {
285 printf("\n");
288 if (procname(pid, nbuf, sizeof(nbuf))) {
289 printf("Stack trace for process %llu (%s):\n",
290 (unsigned long long)pid, nbuf);
291 } else {
292 printf("Stack trace for process %llu:\n",
293 (unsigned long long)pid);
296 while (unw_step(&cursor) > 0) {
297 ip = sp = off = 0;
298 unw_get_reg(&cursor, UNW_REG_IP, &ip);
299 unw_get_reg(&cursor, UNW_REG_SP, &sp);
301 ret = unw_get_proc_name(&cursor, nbuf, sizeof(nbuf), &off);
302 if (ret != 0 && ret != -UNW_ENOMEM) {
303 snprintf(nbuf, sizeof(nbuf), "<unknown symbol>");
305 printf(" %s + %#llx [ip=%#llx] [sp=%#llx]\n",
306 nbuf, (long long)off, (long long)ip,
307 (long long)sp);
310 (*count)++;
312 cleanup:
313 if (aspace) {
314 unw_destroy_addr_space(aspace);
317 if (pinfo) {
318 _UPT_destroy(pinfo);
321 ptrace(PTRACE_DETACH, pid, NULL, NULL);
324 static int stack_trace_server(const struct server_id *id,
325 uint32_t msg_flags,
326 void *priv)
328 if (id->vnn == get_my_vnn()) {
329 print_stack_trace(procid_to_pid(id), (int *)priv);
331 return 0;
334 static bool do_daemon_stack_trace(struct tevent_context *ev_ctx,
335 struct messaging_context *msg_ctx,
336 const struct server_id pid,
337 const int argc, const char **argv)
339 pid_t dest;
340 int count = 0;
342 if (argc != 1) {
343 fprintf(stderr, "Usage: smbcontrol <dest> stacktrace\n");
344 return False;
347 dest = procid_to_pid(&pid);
349 if (dest != 0) {
350 /* It would be nice to be able to make sure that this PID is
351 * the PID of a smbd/winbind/nmbd process, not some random PID
352 * the user liked the look of. It doesn't seem like it's worth
353 * the effort at the moment, however.
355 print_stack_trace(dest, &count);
356 } else {
357 serverid_traverse_read(stack_trace_server, &count);
360 return True;
363 #else /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
365 static bool do_daemon_stack_trace(struct tevent_context *ev_ctx,
366 struct messaging_context *msg_ctx,
367 const struct server_id pid,
368 const int argc, const char **argv)
370 fprintf(stderr,
371 "Daemon stack tracing is not supported on this platform\n");
372 return False;
375 #endif /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
377 /* Inject a fault (fatal signal) into a running smbd */
379 static bool do_inject_fault(struct tevent_context *ev_ctx,
380 struct messaging_context *msg_ctx,
381 const struct server_id pid,
382 const int argc, const char **argv)
384 if (argc != 2) {
385 fprintf(stderr, "Usage: smbcontrol <dest> inject "
386 "<bus|hup|term|internal|segv>\n");
387 return False;
390 #ifndef DEVELOPER
391 fprintf(stderr, "Fault injection is only available in "
392 "developer builds\n");
393 return False;
394 #else /* DEVELOPER */
396 int sig = 0;
398 if (strcmp(argv[1], "bus") == 0) {
399 sig = SIGBUS;
400 } else if (strcmp(argv[1], "hup") == 0) {
401 sig = SIGHUP;
402 } else if (strcmp(argv[1], "term") == 0) {
403 sig = SIGTERM;
404 } else if (strcmp(argv[1], "segv") == 0) {
405 sig = SIGSEGV;
406 } else if (strcmp(argv[1], "internal") == 0) {
407 /* Force an internal error, ie. an unclean exit. */
408 sig = -1;
409 } else {
410 fprintf(stderr, "Unknown signal name '%s'\n", argv[1]);
411 return False;
414 return send_message(msg_ctx, pid, MSG_SMB_INJECT_FAULT,
415 &sig, sizeof(int));
417 #endif /* DEVELOPER */
420 /* Force a browser election */
422 static bool do_election(struct tevent_context *ev_ctx,
423 struct messaging_context *msg_ctx,
424 const struct server_id pid,
425 const int argc, const char **argv)
427 if (argc != 1) {
428 fprintf(stderr, "Usage: smbcontrol <dest> force-election\n");
429 return False;
432 return send_message(msg_ctx, pid, MSG_FORCE_ELECTION, NULL, 0);
435 /* Ping a samba daemon process */
437 static void pong_cb(struct messaging_context *msg,
438 void *private_data,
439 uint32_t msg_type,
440 struct server_id pid,
441 DATA_BLOB *data)
443 struct server_id_buf src_string;
444 printf("PONG from pid %s\n", server_id_str_buf(pid, &src_string));
445 num_replies++;
448 static bool do_ping(struct tevent_context *ev_ctx,
449 struct messaging_context *msg_ctx,
450 const struct server_id pid,
451 const int argc, const char **argv)
453 if (argc != 1) {
454 fprintf(stderr, "Usage: smbcontrol <dest> ping\n");
455 return False;
458 /* Send a message and register our interest in a reply */
460 if (!send_message(msg_ctx, pid, MSG_PING, NULL, 0))
461 return False;
463 messaging_register(msg_ctx, NULL, MSG_PONG, pong_cb);
465 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
467 /* No replies were received within the timeout period */
469 if (num_replies == 0)
470 printf("No replies received\n");
472 messaging_deregister(msg_ctx, MSG_PONG, NULL);
474 return num_replies;
477 /* Set profiling options */
479 static bool do_profile(struct tevent_context *ev_ctx,
480 struct messaging_context *msg_ctx,
481 const struct server_id pid,
482 const int argc, const char **argv)
484 int v;
486 if (argc != 2) {
487 fprintf(stderr, "Usage: smbcontrol <dest> profile "
488 "<off|count|on|flush>\n");
489 return False;
492 if (strcmp(argv[1], "off") == 0) {
493 v = 0;
494 } else if (strcmp(argv[1], "count") == 0) {
495 v = 1;
496 } else if (strcmp(argv[1], "on") == 0) {
497 v = 2;
498 } else if (strcmp(argv[1], "flush") == 0) {
499 v = 3;
500 } else {
501 fprintf(stderr, "Unknown profile command '%s'\n", argv[1]);
502 return False;
505 return send_message(msg_ctx, pid, MSG_PROFILE, &v, sizeof(int));
508 /* Return the profiling level */
510 static void profilelevel_cb(struct messaging_context *msg_ctx,
511 void *private_data,
512 uint32_t msg_type,
513 struct server_id pid,
514 DATA_BLOB *data)
516 int level;
517 const char *s;
519 num_replies++;
521 if (data->length != sizeof(int)) {
522 fprintf(stderr, "invalid message length %ld returned\n",
523 (unsigned long)data->length);
524 return;
527 memcpy(&level, data->data, sizeof(int));
529 switch (level) {
530 case 0:
531 s = "not enabled";
532 break;
533 case 1:
534 s = "off";
535 break;
536 case 3:
537 s = "count only";
538 break;
539 case 7:
540 s = "count and time";
541 break;
542 default:
543 s = "BOGUS";
544 break;
547 printf("Profiling %s on pid %u\n",s,(unsigned int)procid_to_pid(&pid));
550 static void profilelevel_rqst(struct messaging_context *msg_ctx,
551 void *private_data,
552 uint32_t msg_type,
553 struct server_id pid,
554 DATA_BLOB *data)
556 int v = 0;
558 /* Send back a dummy reply */
560 send_message(msg_ctx, pid, MSG_PROFILELEVEL, &v, sizeof(int));
563 static bool do_profilelevel(struct tevent_context *ev_ctx,
564 struct messaging_context *msg_ctx,
565 const struct server_id pid,
566 const int argc, const char **argv)
568 if (argc != 1) {
569 fprintf(stderr, "Usage: smbcontrol <dest> profilelevel\n");
570 return False;
573 /* Send a message and register our interest in a reply */
575 if (!send_message(msg_ctx, pid, MSG_REQ_PROFILELEVEL, NULL, 0))
576 return False;
578 messaging_register(msg_ctx, NULL, MSG_PROFILELEVEL, profilelevel_cb);
579 messaging_register(msg_ctx, NULL, MSG_REQ_PROFILELEVEL,
580 profilelevel_rqst);
582 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
584 /* No replies were received within the timeout period */
586 if (num_replies == 0)
587 printf("No replies received\n");
589 messaging_deregister(msg_ctx, MSG_PROFILE, NULL);
591 return num_replies;
594 /* Display debug level settings */
596 static bool do_debuglevel(struct tevent_context *ev_ctx,
597 struct messaging_context *msg_ctx,
598 const struct server_id pid,
599 const int argc, const char **argv)
601 if (argc != 1) {
602 fprintf(stderr, "Usage: smbcontrol <dest> debuglevel\n");
603 return False;
606 /* Send a message and register our interest in a reply */
608 if (!send_message(msg_ctx, pid, MSG_REQ_DEBUGLEVEL, NULL, 0))
609 return False;
611 messaging_register(msg_ctx, NULL, MSG_DEBUGLEVEL, print_pid_string_cb);
613 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
615 /* No replies were received within the timeout period */
617 if (num_replies == 0)
618 printf("No replies received\n");
620 messaging_deregister(msg_ctx, MSG_DEBUGLEVEL, NULL);
622 return num_replies;
625 /* Send a print notify message */
627 static bool do_printnotify(struct tevent_context *ev_ctx,
628 struct messaging_context *msg_ctx,
629 const struct server_id pid,
630 const int argc, const char **argv)
632 const char *cmd;
634 /* Check for subcommand */
636 if (argc == 1) {
637 fprintf(stderr, "Must specify subcommand:\n");
638 fprintf(stderr, "\tqueuepause <printername>\n");
639 fprintf(stderr, "\tqueueresume <printername>\n");
640 fprintf(stderr, "\tjobpause <printername> <unix jobid>\n");
641 fprintf(stderr, "\tjobresume <printername> <unix jobid>\n");
642 fprintf(stderr, "\tjobdelete <printername> <unix jobid>\n");
643 fprintf(stderr, "\tprinter <printername> <comment|port|"
644 "driver> <value>\n");
646 return False;
649 cmd = argv[1];
651 if (strcmp(cmd, "queuepause") == 0) {
653 if (argc != 3) {
654 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
655 " queuepause <printername>\n");
656 return False;
659 notify_printer_status_byname(ev_ctx, msg_ctx, argv[2],
660 PRINTER_STATUS_PAUSED);
662 goto send;
664 } else if (strcmp(cmd, "queueresume") == 0) {
666 if (argc != 3) {
667 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
668 " queuereume <printername>\n");
669 return False;
672 notify_printer_status_byname(ev_ctx, msg_ctx, argv[2],
673 PRINTER_STATUS_OK);
675 goto send;
677 } else if (strcmp(cmd, "jobpause") == 0) {
678 int jobid;
680 if (argc != 4) {
681 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
682 " jobpause <printername> <unix-jobid>\n");
683 return False;
686 jobid = atoi(argv[3]);
688 notify_job_status_byname(
689 ev_ctx, msg_ctx,
690 argv[2], jobid, JOB_STATUS_PAUSED,
691 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
693 goto send;
695 } else if (strcmp(cmd, "jobresume") == 0) {
696 int jobid;
698 if (argc != 4) {
699 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
700 " jobpause <printername> <unix-jobid>\n");
701 return False;
704 jobid = atoi(argv[3]);
706 notify_job_status_byname(
707 ev_ctx, msg_ctx,
708 argv[2], jobid, JOB_STATUS_QUEUED,
709 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
711 goto send;
713 } else if (strcmp(cmd, "jobdelete") == 0) {
714 int jobid;
716 if (argc != 4) {
717 fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
718 " jobpause <printername> <unix-jobid>\n");
719 return False;
722 jobid = atoi(argv[3]);
724 notify_job_status_byname(
725 ev_ctx, msg_ctx,
726 argv[2], jobid, JOB_STATUS_DELETING,
727 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
729 notify_job_status_byname(
730 ev_ctx, msg_ctx,
731 argv[2], jobid, JOB_STATUS_DELETING|
732 JOB_STATUS_DELETED,
733 SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
735 goto send;
737 } else if (strcmp(cmd, "printer") == 0) {
738 uint32 attribute;
740 if (argc != 5) {
741 fprintf(stderr, "Usage: smbcontrol <dest> printnotify "
742 "printer <printername> <comment|port|driver> "
743 "<value>\n");
744 return False;
747 if (strcmp(argv[3], "comment") == 0) {
748 attribute = PRINTER_NOTIFY_FIELD_COMMENT;
749 } else if (strcmp(argv[3], "port") == 0) {
750 attribute = PRINTER_NOTIFY_FIELD_PORT_NAME;
751 } else if (strcmp(argv[3], "driver") == 0) {
752 attribute = PRINTER_NOTIFY_FIELD_DRIVER_NAME;
753 } else {
754 fprintf(stderr, "Invalid printer command '%s'\n",
755 argv[3]);
756 return False;
759 notify_printer_byname(ev_ctx, msg_ctx, argv[2], attribute,
760 discard_const_p(char, argv[4]));
762 goto send;
765 fprintf(stderr, "Invalid subcommand '%s'\n", cmd);
766 return False;
768 send:
769 print_notify_send_messages(msg_ctx, 0);
770 return True;
773 /* Close a share */
775 static bool do_closeshare(struct tevent_context *ev_ctx,
776 struct messaging_context *msg_ctx,
777 const struct server_id pid,
778 const int argc, const char **argv)
780 if (argc != 2) {
781 fprintf(stderr, "Usage: smbcontrol <dest> close-share "
782 "<sharename>\n");
783 return False;
786 return send_message(msg_ctx, pid, MSG_SMB_FORCE_TDIS, argv[1],
787 strlen(argv[1]) + 1);
790 /* Kill a client by IP address */
791 static bool do_kill_client_by_ip(struct tevent_context *ev_ctx,
792 struct messaging_context *msg_ctx,
793 const struct server_id pid,
794 const int argc, const char **argv)
796 if (argc != 2) {
797 fprintf(stderr, "Usage: smbcontrol <dest> kill-client-ip "
798 "<IP address>\n");
799 return false;
802 if (!is_ipaddress_v4(argv[1]) && !is_ipaddress_v6(argv[1])) {
803 fprintf(stderr, "%s is not a valid IP address!\n", argv[1]);
804 return false;
807 return send_message(msg_ctx, pid, MSG_SMB_KILL_CLIENT_IP,
808 argv[1], strlen(argv[1]) + 1);
811 /* Tell winbindd an IP got dropped */
813 static bool do_ip_dropped(struct tevent_context *ev_ctx,
814 struct messaging_context *msg_ctx,
815 const struct server_id pid,
816 const int argc, const char **argv)
818 if (argc != 2) {
819 fprintf(stderr, "Usage: smbcontrol <dest> ip-dropped "
820 "<ip-address>\n");
821 return False;
824 return send_message(msg_ctx, pid, MSG_WINBIND_IP_DROPPED, argv[1],
825 strlen(argv[1]) + 1);
828 /* force a blocking lock retry */
830 static bool do_lockretry(struct tevent_context *ev_ctx,
831 struct messaging_context *msg_ctx,
832 const struct server_id pid,
833 const int argc, const char **argv)
835 if (argc != 1) {
836 fprintf(stderr, "Usage: smbcontrol <dest> lockretry\n");
837 return False;
840 return send_message(msg_ctx, pid, MSG_SMB_UNLOCK, NULL, 0);
843 /* force a validation of all brl entries, including re-sends. */
845 static bool do_brl_revalidate(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 != 1) {
851 fprintf(stderr, "Usage: smbcontrol <dest> brl-revalidate\n");
852 return False;
855 return send_message(msg_ctx, pid, MSG_SMB_BRL_VALIDATE, NULL, 0);
858 /* Display talloc pool usage */
860 static bool do_poolusage(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 != 1) {
866 fprintf(stderr, "Usage: smbcontrol <dest> pool-usage\n");
867 return False;
870 messaging_register(msg_ctx, NULL, MSG_POOL_USAGE, print_string_cb);
872 /* Send a message and register our interest in a reply */
874 if (!send_message(msg_ctx, pid, MSG_REQ_POOL_USAGE, NULL, 0))
875 return False;
877 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
879 /* No replies were received within the timeout period */
881 if (num_replies == 0)
882 printf("No replies received\n");
884 messaging_deregister(msg_ctx, MSG_POOL_USAGE, NULL);
886 return num_replies;
889 /* Perform a dmalloc mark */
891 static bool do_dmalloc_mark(struct tevent_context *ev_ctx,
892 struct messaging_context *msg_ctx,
893 const struct server_id pid,
894 const int argc, const char **argv)
896 if (argc != 1) {
897 fprintf(stderr, "Usage: smbcontrol <dest> dmalloc-mark\n");
898 return False;
901 return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_MARK, NULL, 0);
904 /* Perform a dmalloc changed */
906 static bool do_dmalloc_changed(struct tevent_context *ev_ctx,
907 struct messaging_context *msg_ctx,
908 const struct server_id pid,
909 const int argc, const char **argv)
911 if (argc != 1) {
912 fprintf(stderr, "Usage: smbcontrol <dest> "
913 "dmalloc-log-changed\n");
914 return False;
917 return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_LOG_CHANGED,
918 NULL, 0);
921 static void print_uint32_cb(struct messaging_context *msg, void *private_data,
922 uint32_t msg_type, struct server_id pid,
923 DATA_BLOB *data)
925 uint32_t num_children;
927 if (data->length != sizeof(uint32_t)) {
928 printf("Invalid response: %d bytes long\n",
929 (int)data->length);
930 goto done;
932 num_children = IVAL(data->data, 0);
933 printf("%u children\n", (unsigned)num_children);
934 done:
935 num_replies++;
938 static bool do_num_children(struct tevent_context *ev_ctx,
939 struct messaging_context *msg_ctx,
940 const struct server_id pid,
941 const int argc, const char **argv)
943 if (argc != 1) {
944 fprintf(stderr, "Usage: smbcontrol <dest> num-children\n");
945 return False;
948 messaging_register(msg_ctx, NULL, MSG_SMB_NUM_CHILDREN,
949 print_uint32_cb);
951 /* Send a message and register our interest in a reply */
953 if (!send_message(msg_ctx, pid, MSG_SMB_TELL_NUM_CHILDREN, NULL, 0))
954 return false;
956 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
958 /* No replies were received within the timeout period */
960 if (num_replies == 0)
961 printf("No replies received\n");
963 messaging_deregister(msg_ctx, MSG_SMB_NUM_CHILDREN, NULL);
965 return num_replies;
968 static bool do_msg_cleanup(struct tevent_context *ev_ctx,
969 struct messaging_context *msg_ctx,
970 const struct server_id pid,
971 const int argc, const char **argv)
973 int ret;
975 ret = messaging_cleanup(msg_ctx, pid.pid);
977 printf("cleanup(%u) returned %s\n", (unsigned)pid.pid,
978 ret ? strerror(ret) : "ok");
980 return (ret == 0);
983 /* Shutdown a server process */
985 static bool do_shutdown(struct tevent_context *ev_ctx,
986 struct messaging_context *msg_ctx,
987 const struct server_id pid,
988 const int argc, const char **argv)
990 if (argc != 1) {
991 fprintf(stderr, "Usage: smbcontrol <dest> shutdown\n");
992 return False;
995 return send_message(msg_ctx, pid, MSG_SHUTDOWN, NULL, 0);
998 /* Notify a driver upgrade */
1000 static bool do_drvupgrade(struct tevent_context *ev_ctx,
1001 struct messaging_context *msg_ctx,
1002 const struct server_id pid,
1003 const int argc, const char **argv)
1005 if (argc != 2) {
1006 fprintf(stderr, "Usage: smbcontrol <dest> drvupgrade "
1007 "<driver-name>\n");
1008 return False;
1011 return send_message(msg_ctx, pid, MSG_PRINTER_DRVUPGRADE, argv[1],
1012 strlen(argv[1]) + 1);
1015 static bool do_winbind_online(struct tevent_context *ev_ctx,
1016 struct messaging_context *msg_ctx,
1017 const struct server_id pid,
1018 const int argc, const char **argv)
1020 TDB_CONTEXT *tdb;
1021 char *db_path;
1023 if (argc != 1) {
1024 fprintf(stderr, "Usage: smbcontrol winbindd online\n");
1025 return False;
1028 db_path = state_path("winbindd_cache.tdb");
1029 if (db_path == NULL) {
1030 return false;
1033 /* Remove the entry in the winbindd_cache tdb to tell a later
1034 starting winbindd that we're online. */
1036 tdb = tdb_open_log(db_path, 0, TDB_DEFAULT, O_RDWR, 0600);
1037 if (!tdb) {
1038 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
1039 db_path);
1040 TALLOC_FREE(db_path);
1041 return False;
1044 TALLOC_FREE(db_path);
1045 tdb_delete_bystring(tdb, "WINBINDD_OFFLINE");
1046 tdb_close(tdb);
1048 return send_message(msg_ctx, pid, MSG_WINBIND_ONLINE, NULL, 0);
1051 static bool do_winbind_offline(struct tevent_context *ev_ctx,
1052 struct messaging_context *msg_ctx,
1053 const struct server_id pid,
1054 const int argc, const char **argv)
1056 TDB_CONTEXT *tdb;
1057 bool ret = False;
1058 int retry = 0;
1059 char *db_path;
1061 if (argc != 1) {
1062 fprintf(stderr, "Usage: smbcontrol winbindd offline\n");
1063 return False;
1066 db_path = state_path("winbindd_cache.tdb");
1067 if (db_path == NULL) {
1068 return false;
1071 /* Create an entry in the winbindd_cache tdb to tell a later
1072 starting winbindd that we're offline. We may actually create
1073 it here... */
1075 tdb = tdb_open_log(db_path,
1076 WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
1077 TDB_DEFAULT|TDB_INCOMPATIBLE_HASH /* TDB_CLEAR_IF_FIRST */,
1078 O_RDWR|O_CREAT, 0600);
1080 if (!tdb) {
1081 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
1082 db_path);
1083 TALLOC_FREE(db_path);
1084 return False;
1086 TALLOC_FREE(db_path);
1088 /* There's a potential race condition that if a child
1089 winbindd detects a domain is online at the same time
1090 we're trying to tell it to go offline that it might
1091 delete the record we add between us adding it and
1092 sending the message. Minimize this by retrying up to
1093 5 times. */
1095 for (retry = 0; retry < 5; retry++) {
1096 TDB_DATA d;
1097 uint8 buf[4];
1099 ZERO_STRUCT(d);
1101 SIVAL(buf, 0, time(NULL));
1102 d.dptr = buf;
1103 d.dsize = 4;
1105 tdb_store_bystring(tdb, "WINBINDD_OFFLINE", d, TDB_INSERT);
1107 ret = send_message(msg_ctx, pid, MSG_WINBIND_OFFLINE,
1108 NULL, 0);
1110 /* Check that the entry "WINBINDD_OFFLINE" still exists. */
1111 d = tdb_fetch_bystring( tdb, "WINBINDD_OFFLINE" );
1113 if (!d.dptr || d.dsize != 4) {
1114 SAFE_FREE(d.dptr);
1115 DEBUG(10,("do_winbind_offline: offline state not set - retrying.\n"));
1116 } else {
1117 SAFE_FREE(d.dptr);
1118 break;
1122 tdb_close(tdb);
1123 return ret;
1126 static bool do_winbind_onlinestatus(struct tevent_context *ev_ctx,
1127 struct messaging_context *msg_ctx,
1128 const struct server_id pid,
1129 const int argc, const char **argv)
1131 struct server_id myid;
1133 myid = messaging_server_id(msg_ctx);
1135 if (argc != 1) {
1136 fprintf(stderr, "Usage: smbcontrol winbindd onlinestatus\n");
1137 return False;
1140 messaging_register(msg_ctx, NULL, MSG_WINBIND_ONLINESTATUS,
1141 print_pid_string_cb);
1143 if (!send_message(msg_ctx, pid, MSG_WINBIND_ONLINESTATUS, &myid,
1144 sizeof(myid)))
1145 return False;
1147 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
1149 /* No replies were received within the timeout period */
1151 if (num_replies == 0)
1152 printf("No replies received\n");
1154 messaging_deregister(msg_ctx, MSG_WINBIND_ONLINESTATUS, NULL);
1156 return num_replies;
1159 static bool do_dump_event_list(struct tevent_context *ev_ctx,
1160 struct messaging_context *msg_ctx,
1161 const struct server_id pid,
1162 const int argc, const char **argv)
1164 if (argc != 1) {
1165 fprintf(stderr, "Usage: smbcontrol <dest> dump-event-list\n");
1166 return False;
1169 return send_message(msg_ctx, pid, MSG_DUMP_EVENT_LIST, NULL, 0);
1172 static bool do_winbind_dump_domain_list(struct tevent_context *ev_ctx,
1173 struct messaging_context *msg_ctx,
1174 const struct server_id pid,
1175 const int argc, const char **argv)
1177 const char *domain = NULL;
1178 int domain_len = 0;
1179 struct server_id myid;
1180 uint8_t *buf = NULL;
1181 int buf_len = 0;
1183 myid = messaging_server_id(msg_ctx);
1185 if (argc < 1 || argc > 2) {
1186 fprintf(stderr, "Usage: smbcontrol <dest> dump-domain-list "
1187 "<domain>\n");
1188 return false;
1191 if (argc == 2) {
1192 domain = argv[1];
1193 domain_len = strlen(argv[1]) + 1;
1196 messaging_register(msg_ctx, NULL, MSG_WINBIND_DUMP_DOMAIN_LIST,
1197 print_pid_string_cb);
1199 buf_len = sizeof(myid)+domain_len;
1200 buf = SMB_MALLOC_ARRAY(uint8_t, buf_len);
1201 if (!buf) {
1202 return false;
1205 memcpy(buf, &myid, sizeof(myid));
1206 memcpy(&buf[sizeof(myid)], domain, domain_len);
1208 if (!send_message(msg_ctx, pid, MSG_WINBIND_DUMP_DOMAIN_LIST,
1209 buf, buf_len))
1211 SAFE_FREE(buf);
1212 return false;
1215 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
1217 /* No replies were received within the timeout period */
1219 SAFE_FREE(buf);
1220 if (num_replies == 0) {
1221 printf("No replies received\n");
1224 messaging_deregister(msg_ctx, MSG_WINBIND_DUMP_DOMAIN_LIST, NULL);
1226 return num_replies;
1229 static void winbind_validate_cache_cb(struct messaging_context *msg,
1230 void *private_data,
1231 uint32_t msg_type,
1232 struct server_id pid,
1233 DATA_BLOB *data)
1235 struct server_id_buf src_string;
1236 printf("Winbindd cache is %svalid. (answer from pid %s)\n",
1237 (*(data->data) == 0 ? "" : "NOT "),
1238 server_id_str_buf(pid, &src_string));
1239 num_replies++;
1242 static bool do_winbind_validate_cache(struct tevent_context *ev_ctx,
1243 struct messaging_context *msg_ctx,
1244 const struct server_id pid,
1245 const int argc, const char **argv)
1247 struct server_id myid;
1249 myid = messaging_server_id(msg_ctx);
1251 if (argc != 1) {
1252 fprintf(stderr, "Usage: smbcontrol winbindd validate-cache\n");
1253 return False;
1256 messaging_register(msg_ctx, NULL, MSG_WINBIND_VALIDATE_CACHE,
1257 winbind_validate_cache_cb);
1259 if (!send_message(msg_ctx, pid, MSG_WINBIND_VALIDATE_CACHE, &myid,
1260 sizeof(myid))) {
1261 return False;
1264 wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
1266 if (num_replies == 0) {
1267 printf("No replies received\n");
1270 messaging_deregister(msg_ctx, MSG_WINBIND_VALIDATE_CACHE, NULL);
1272 return num_replies;
1275 static bool do_reload_config(struct tevent_context *ev_ctx,
1276 struct messaging_context *msg_ctx,
1277 const struct server_id pid,
1278 const int argc, const char **argv)
1280 if (argc != 1) {
1281 fprintf(stderr, "Usage: smbcontrol <dest> reload-config\n");
1282 return False;
1285 return send_message(msg_ctx, pid, MSG_SMB_CONF_UPDATED, NULL, 0);
1288 static bool do_reload_printers(struct tevent_context *ev_ctx,
1289 struct messaging_context *msg_ctx,
1290 const struct server_id pid,
1291 const int argc, const char **argv)
1293 if (argc != 1) {
1294 fprintf(stderr, "Usage: smbcontrol <dest> reload-printers\n");
1295 return False;
1298 return send_message(msg_ctx, pid, MSG_PRINTER_PCAP, NULL, 0);
1301 static void my_make_nmb_name( struct nmb_name *n, const char *name, int type)
1303 fstring unix_name;
1304 memset( (char *)n, '\0', sizeof(struct nmb_name) );
1305 fstrcpy(unix_name, name);
1306 (void)strupper_m(unix_name);
1307 push_ascii(n->name, unix_name, sizeof(n->name), STR_TERMINATE);
1308 n->name_type = (unsigned int)type & 0xFF;
1309 push_ascii(n->scope, lp_netbios_scope(), 64, STR_TERMINATE);
1312 static bool do_nodestatus(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 packet_struct p;
1319 if (argc != 2) {
1320 fprintf(stderr, "Usage: smbcontrol nmbd nodestatus <ip>\n");
1321 return False;
1324 ZERO_STRUCT(p);
1326 p.ip = interpret_addr2(argv[1]);
1327 p.port = 137;
1328 p.packet_type = NMB_PACKET;
1330 p.packet.nmb.header.name_trn_id = 10;
1331 p.packet.nmb.header.opcode = 0;
1332 p.packet.nmb.header.response = False;
1333 p.packet.nmb.header.nm_flags.bcast = False;
1334 p.packet.nmb.header.nm_flags.recursion_available = False;
1335 p.packet.nmb.header.nm_flags.recursion_desired = False;
1336 p.packet.nmb.header.nm_flags.trunc = False;
1337 p.packet.nmb.header.nm_flags.authoritative = False;
1338 p.packet.nmb.header.rcode = 0;
1339 p.packet.nmb.header.qdcount = 1;
1340 p.packet.nmb.header.ancount = 0;
1341 p.packet.nmb.header.nscount = 0;
1342 p.packet.nmb.header.arcount = 0;
1343 my_make_nmb_name(&p.packet.nmb.question.question_name, "*", 0x00);
1344 p.packet.nmb.question.question_type = 0x21;
1345 p.packet.nmb.question.question_class = 0x1;
1347 return send_message(msg_ctx, pid, MSG_SEND_PACKET, &p, sizeof(p));
1350 static bool do_notify_cleanup(struct tevent_context *ev_ctx,
1351 struct messaging_context *msg_ctx,
1352 const struct server_id pid,
1353 const int argc, const char **argv)
1355 if (argc != 1) {
1356 fprintf(stderr, "Usage: smbcontrol smbd notify-cleanup\n");
1357 return false;
1359 return send_message(msg_ctx, pid, MSG_SMB_NOTIFY_CLEANUP, NULL, 0);
1362 /* A list of message type supported */
1364 static const struct {
1365 const char *name; /* Option name */
1366 bool (*fn)(struct tevent_context *ev_ctx,
1367 struct messaging_context *msg_ctx,
1368 const struct server_id pid,
1369 const int argc, const char **argv);
1370 const char *help; /* Short help text */
1371 } msg_types[] = {
1372 { "debug", do_debug, "Set debuglevel" },
1373 { "idmap", do_idmap, "Manipulate idmap cache" },
1374 { "force-election", do_election,
1375 "Force a browse election" },
1376 { "ping", do_ping, "Elicit a response" },
1377 { "profile", do_profile, "" },
1378 { "inject", do_inject_fault,
1379 "Inject a fatal signal into a running smbd"},
1380 { "stacktrace", do_daemon_stack_trace,
1381 "Display a stack trace of a daemon" },
1382 { "profilelevel", do_profilelevel, "" },
1383 { "debuglevel", do_debuglevel, "Display current debuglevels" },
1384 { "printnotify", do_printnotify, "Send a print notify message" },
1385 { "close-share", do_closeshare, "Forcibly disconnect a share" },
1386 { "kill-client-ip", do_kill_client_by_ip,
1387 "Forcibly disconnect a client with a specific IP address" },
1388 { "ip-dropped", do_ip_dropped, "Tell winbind that an IP got dropped" },
1389 { "lockretry", do_lockretry, "Force a blocking lock retry" },
1390 { "brl-revalidate", do_brl_revalidate, "Revalidate all brl entries" },
1391 { "pool-usage", do_poolusage, "Display talloc memory usage" },
1392 { "dmalloc-mark", do_dmalloc_mark, "" },
1393 { "dmalloc-log-changed", do_dmalloc_changed, "" },
1394 { "shutdown", do_shutdown, "Shut down daemon" },
1395 { "drvupgrade", do_drvupgrade, "Notify a printer driver has changed" },
1396 { "reload-config", do_reload_config, "Force smbd or winbindd to reload config file"},
1397 { "reload-printers", do_reload_printers, "Force smbd to reload printers"},
1398 { "nodestatus", do_nodestatus, "Ask nmbd to do a node status request"},
1399 { "online", do_winbind_online, "Ask winbind to go into online state"},
1400 { "offline", do_winbind_offline, "Ask winbind to go into offline state"},
1401 { "onlinestatus", do_winbind_onlinestatus, "Request winbind online status"},
1402 { "dump-event-list", do_dump_event_list, "Dump event list"},
1403 { "validate-cache" , do_winbind_validate_cache,
1404 "Validate winbind's credential cache" },
1405 { "dump-domain-list", do_winbind_dump_domain_list, "Dump winbind domain list"},
1406 { "notify-cleanup", do_notify_cleanup },
1407 { "num-children", do_num_children,
1408 "Print number of smbd child processes" },
1409 { "msg-cleanup", do_msg_cleanup },
1410 { "noop", do_noop, "Do nothing" },
1411 { NULL }
1414 /* Display usage information */
1416 static void usage(poptContext pc)
1418 int i;
1420 poptPrintHelp(pc, stderr, 0);
1422 fprintf(stderr, "\n");
1423 fprintf(stderr, "<destination> is one of \"nmbd\", \"smbd\", \"winbindd\" or a "
1424 "process ID\n");
1426 fprintf(stderr, "\n");
1427 fprintf(stderr, "<message-type> is one of:\n");
1429 for (i = 0; msg_types[i].name; i++)
1430 fprintf(stderr, "\t%-30s%s\n", msg_types[i].name,
1431 msg_types[i].help);
1433 fprintf(stderr, "\n");
1435 exit(1);
1438 /* Return the pid number for a string destination */
1440 static struct server_id parse_dest(struct messaging_context *msg,
1441 const char *dest)
1443 struct server_id result = {-1};
1444 pid_t pid;
1446 /* Zero is a special return value for broadcast to all processes */
1448 if (strequal(dest, "all")) {
1449 return interpret_pid(MSG_BROADCAST_PID_STR);
1452 /* Try self - useful for testing */
1454 if (strequal(dest, "self")) {
1455 return messaging_server_id(msg);
1458 /* Fix winbind typo. */
1459 if (strequal(dest, "winbind")) {
1460 dest = "winbindd";
1463 /* Check for numeric pid number */
1464 result = interpret_pid(dest);
1466 /* Zero isn't valid if not "all". */
1467 if (result.pid && procid_valid(&result)) {
1468 return result;
1471 /* Look up other destinations in pidfile directory */
1473 if ((pid = pidfile_pid(lp_pid_directory(), dest)) != 0) {
1474 return pid_to_procid(pid);
1477 fprintf(stderr,"Can't find pid for destination '%s'\n", dest);
1479 return result;
1482 /* Execute smbcontrol command */
1484 static bool do_command(struct tevent_context *ev_ctx,
1485 struct messaging_context *msg_ctx,
1486 int argc, const char **argv)
1488 const char *dest = argv[0], *command = argv[1];
1489 struct server_id pid;
1490 int i;
1492 /* Check destination */
1494 pid = parse_dest(msg_ctx, dest);
1495 if (!procid_valid(&pid)) {
1496 return False;
1499 /* Check command */
1501 for (i = 0; msg_types[i].name; i++) {
1502 if (strequal(command, msg_types[i].name))
1503 return msg_types[i].fn(ev_ctx, msg_ctx, pid,
1504 argc - 1, argv + 1);
1507 fprintf(stderr, "smbcontrol: unknown command '%s'\n", command);
1509 return False;
1512 static void smbcontrol_help(poptContext pc,
1513 enum poptCallbackReason preason,
1514 struct poptOption * poption,
1515 const char * parg,
1516 void * pdata)
1518 if (poption->shortName != '?') {
1519 poptPrintUsage(pc, stdout, 0);
1520 } else {
1521 usage(pc);
1524 exit(0);
1527 struct poptOption help_options[] = {
1528 { NULL, '\0', POPT_ARG_CALLBACK, (void *)&smbcontrol_help, '\0',
1529 NULL, NULL },
1530 { "help", '?', 0, NULL, '?', "Show this help message", NULL },
1531 { "usage", '\0', 0, NULL, 'u', "Display brief usage message", NULL },
1532 { NULL }
1535 /* Main program */
1537 int main(int argc, const char **argv)
1539 poptContext pc;
1540 int opt;
1541 struct tevent_context *evt_ctx;
1542 struct messaging_context *msg_ctx;
1544 static struct poptOption long_options[] = {
1545 /* POPT_AUTOHELP */
1546 { NULL, '\0', POPT_ARG_INCLUDE_TABLE, help_options,
1547 0, "Help options:", NULL },
1548 { "timeout", 't', POPT_ARG_INT, &timeout, 't',
1549 "Set timeout value in seconds", "TIMEOUT" },
1551 POPT_COMMON_SAMBA
1552 POPT_TABLEEND
1554 TALLOC_CTX *frame = talloc_stackframe();
1555 int ret = 0;
1557 load_case_tables();
1559 setup_logging(argv[0], DEBUG_STDOUT);
1561 /* Parse command line arguments using popt */
1563 pc = poptGetContext(
1564 "smbcontrol", argc, (const char **)argv, long_options, 0);
1566 poptSetOtherOptionHelp(pc, "[OPTION...] <destination> <message-type> "
1567 "<parameters>");
1569 if (argc == 1)
1570 usage(pc);
1572 while ((opt = poptGetNextOpt(pc)) != -1) {
1573 switch(opt) {
1574 case 't': /* --timeout */
1575 break;
1576 default:
1577 fprintf(stderr, "Invalid option\n");
1578 poptPrintHelp(pc, stderr, 0);
1579 break;
1583 /* We should now have the remaining command line arguments in
1584 argv. The argc parameter should have been decremented to the
1585 correct value in the above switch statement. */
1587 argv = (const char **)poptGetArgs(pc);
1588 argc = 0;
1589 if (argv != NULL) {
1590 while (argv[argc] != NULL) {
1591 argc++;
1595 if (argc <= 1)
1596 usage(pc);
1598 lp_load_global(get_dyn_CONFIGFILE());
1600 /* Need to invert sense of return code -- samba
1601 * routines mostly return True==1 for success, but
1602 * shell needs 0. */
1604 if (!(evt_ctx = samba_tevent_context_init(NULL)) ||
1605 !(msg_ctx = messaging_init(NULL, evt_ctx))) {
1606 fprintf(stderr, "could not init messaging context\n");
1607 TALLOC_FREE(frame);
1608 exit(1);
1611 ret = !do_command(evt_ctx, msg_ctx, argc, argv);
1612 TALLOC_FREE(msg_ctx);
1613 TALLOC_FREE(frame);
1614 return ret;