LCOV - code coverage report
Current view: top level - source3/utils - smbcontrol.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 129 601 21.5 %
Date: 2024-06-13 04:01:37 Functions: 14 51 27.5 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    Send messages to other Samba daemons
       5             : 
       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
      11             : 
      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.
      16             : 
      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.
      21             : 
      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/>.
      24             : */
      25             : 
      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 "cmdline_contexts.h"
      39             : #include "lib/util/string_wrappers.h"
      40             : #include "lib/global_contexts.h"
      41             : 
      42             : #ifdef HAVE_LIBUNWIND_H
      43             : #include <libunwind.h>
      44             : #endif
      45             : 
      46             : #ifdef HAVE_LIBUNWIND_PTRACE_H
      47             : #include <libunwind-ptrace.h>
      48             : #endif
      49             : 
      50             : #ifdef HAVE_SYS_PTRACE_H
      51             : #include <sys/ptrace.h>
      52             : #endif
      53             : 
      54             : /* Default timeout value when waiting for replies (in seconds) */
      55             : 
      56             : #define DEFAULT_TIMEOUT 10
      57             : 
      58             : static int timeout = DEFAULT_TIMEOUT;
      59             : static int num_replies;         /* Used by message callback fns */
      60             : 
      61             : /* Send a message to a destination pid.  Zero means broadcast smbd. */
      62             : 
      63         102 : static bool send_message(struct messaging_context *msg_ctx,
      64             :                          struct server_id pid, int msg_type,
      65             :                          const void *buf, int len)
      66             : {
      67         102 :         if (procid_to_pid(&pid) != 0)
      68         102 :                 return NT_STATUS_IS_OK(
      69             :                         messaging_send_buf(msg_ctx, pid, msg_type,
      70             :                                            (const uint8_t *)buf, len));
      71             : 
      72           0 :         messaging_send_all(msg_ctx, msg_type, buf, len);
      73             : 
      74           0 :         return true;
      75             : }
      76             : 
      77           1 : static void smbcontrol_timeout(struct tevent_context *event_ctx,
      78             :                                struct tevent_timer *te,
      79             :                                struct timeval now,
      80             :                                void *private_data)
      81             : {
      82           1 :         bool *timed_out = (bool *)private_data;
      83           1 :         TALLOC_FREE(te);
      84           1 :         *timed_out = True;
      85           1 : }
      86             : 
      87             : /* Wait for one or more reply messages */
      88             : 
      89          86 : static void wait_replies(struct tevent_context *ev_ctx,
      90             :                          struct messaging_context *msg_ctx,
      91             :                          bool multiple_replies)
      92             : {
      93             :         struct tevent_timer *te;
      94          86 :         bool timed_out = False;
      95             : 
      96          86 :         te = tevent_add_timer(ev_ctx, NULL,
      97             :                               timeval_current_ofs(timeout, 0),
      98             :                               smbcontrol_timeout, (void *)&timed_out);
      99          86 :         if (te == NULL) {
     100           0 :                 DEBUG(0, ("tevent_add_timer failed\n"));
     101           0 :                 return;
     102             :         }
     103             : 
     104         232 :         while (!timed_out) {
     105             :                 int ret;
     106         173 :                 if (num_replies > 0 && !multiple_replies)
     107          85 :                         break;
     108          88 :                 ret = tevent_loop_once(ev_ctx);
     109          88 :                 if (ret != 0) {
     110           0 :                         break;
     111             :                 }
     112             :         }
     113             : }
     114             : 
     115             : /* Message handler callback that displays the PID and a string on stdout */
     116             : 
     117           0 : static void print_pid_string_cb(struct messaging_context *msg,
     118             :                                 void *private_data, 
     119             :                                 uint32_t msg_type, 
     120             :                                 struct server_id pid,
     121             :                                 DATA_BLOB *data)
     122             : {
     123             :         struct server_id_buf pidstr;
     124             : 
     125           0 :         printf("PID %s: %.*s", server_id_str_buf(pid, &pidstr),
     126           0 :                (int)data->length, (const char *)data->data);
     127           0 :         num_replies++;
     128           0 : }
     129             : 
     130             : /* Send no message.  Useful for testing. */
     131             : 
     132           0 : static bool do_noop(struct tevent_context *ev_ctx,
     133             :                     struct messaging_context *msg_ctx,
     134             :                     const struct server_id pid,
     135             :                     const int argc, const char **argv)
     136             : {
     137           0 :         if (argc != 1) {
     138           0 :                 fprintf(stderr, "Usage: smbcontrol <dest> noop\n");
     139           0 :                 return False;
     140             :         }
     141             : 
     142             :         /* Move along, nothing to see here */
     143             : 
     144           0 :         return True;
     145             : }
     146             : 
     147             : /* Send a debug string */
     148             : 
     149           0 : static bool do_debug(struct tevent_context *ev_ctx,
     150             :                      struct messaging_context *msg_ctx,
     151             :                      const struct server_id pid,
     152             :                      const int argc, const char **argv)
     153             : {
     154           0 :         if (argc != 2) {
     155           0 :                 fprintf(stderr, "Usage: smbcontrol <dest> debug "
     156             :                         "<debug-string>\n");
     157           0 :                 return False;
     158             :         }
     159             : 
     160           0 :         return send_message(msg_ctx, pid, MSG_DEBUG, argv[1],
     161           0 :                             strlen(argv[1]) + 1);
     162             : }
     163             : 
     164             : 
     165           0 : static bool do_idmap(struct tevent_context *ev,
     166             :                      struct messaging_context *msg_ctx,
     167             :                      const struct server_id pid,
     168             :                      const int argc, const char **argv)
     169             : {
     170             :         static const char* usage = "Usage: "
     171             :                 "smbcontrol <dest> idmap <cmd> [arg]\n"
     172             :                 "\tcmd:"
     173             :                 "\tdelete \"UID <uid>\"|\"GID <gid>\"|<sid>\n"
     174             :                 "\t\tkill \"UID <uid>\"|\"GID <gid>\"|<sid>\n";
     175           0 :         const char* arg = NULL;
     176           0 :         int arglen = 0;
     177             :         int msg_type;
     178             : 
     179           0 :         switch (argc) {
     180           0 :         case 2:
     181           0 :                 break;
     182           0 :         case 3:
     183           0 :                 arg = argv[2];
     184           0 :                 arglen = strlen(arg) + 1;
     185           0 :                 break;
     186           0 :         default:
     187           0 :                 fprintf(stderr, "%s", usage);
     188           0 :                 return false;
     189             :         }
     190             : 
     191           0 :         if (strcmp(argv[1], "delete") == 0) {
     192           0 :                 msg_type = ID_CACHE_DELETE;
     193             :         }
     194           0 :         else if (strcmp(argv[1], "kill") == 0) {
     195           0 :                 msg_type = ID_CACHE_KILL;
     196             :         }
     197           0 :         else if (strcmp(argv[1], "help") == 0) {
     198           0 :                 fprintf(stdout, "%s", usage);
     199           0 :                 return true;
     200             :         }
     201             :         else {
     202           0 :                 fprintf(stderr, "%s", usage);
     203           0 :                 return false;
     204             :         }
     205             : 
     206           0 :         return send_message(msg_ctx, pid, msg_type, arg, arglen);
     207             : }
     208             : 
     209             : 
     210             : #if defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE)
     211             : 
     212             : /* Return the name of a process given it's PID. This will only work on Linux,
     213             :  * but that's probably moot since this whole stack tracing implementation is
     214             :  * Linux-specific anyway.
     215             :  */
     216             : static const char * procname(pid_t pid, char * buf, size_t bufsz)
     217             : {
     218             :         char path[64];
     219             :         FILE * fp;
     220             : 
     221             :         snprintf(path, sizeof(path), "/proc/%llu/cmdline",
     222             :                 (unsigned long long)pid);
     223             :         if ((fp = fopen(path, "r")) == NULL) {
     224             :                 return NULL;
     225             :         }
     226             : 
     227             :         fgets(buf, bufsz, fp);
     228             : 
     229             :         fclose(fp);
     230             :         return buf;
     231             : }
     232             : 
     233             : static void print_stack_trace(pid_t pid, int * count)
     234             : {
     235             :         void *              pinfo = NULL;
     236             :         unw_addr_space_t    aspace = NULL;
     237             :         unw_cursor_t        cursor;
     238             :         unw_word_t          ip, sp;
     239             : 
     240             :         char                nbuf[256];
     241             :         unw_word_t          off;
     242             : 
     243             :         int ret;
     244             : 
     245             :         if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) {
     246             :                 fprintf(stderr,
     247             :                         "Failed to attach to process %llu: %s\n",
     248             :                         (unsigned long long)pid, strerror(errno));
     249             :                 return;
     250             :         }
     251             : 
     252             :         /* Wait until the attach is complete. */
     253             :         waitpid(pid, NULL, 0);
     254             : 
     255             :         if (((pinfo = _UPT_create(pid)) == NULL) ||
     256             :             ((aspace = unw_create_addr_space(&_UPT_accessors, 0)) == NULL)) {
     257             :                 /* Probably out of memory. */
     258             :                 fprintf(stderr,
     259             :                         "Unable to initialize stack unwind for process %llu\n",
     260             :                         (unsigned long long)pid);
     261             :                 goto cleanup;
     262             :         }
     263             : 
     264             :         if ((ret = unw_init_remote(&cursor, aspace, pinfo))) {
     265             :                 fprintf(stderr,
     266             :                         "Unable to unwind stack for process %llu: %s\n",
     267             :                         (unsigned long long)pid, unw_strerror(ret));
     268             :                 goto cleanup;
     269             :         }
     270             : 
     271             :         if (*count > 0) {
     272             :                 printf("\n");
     273             :         }
     274             : 
     275             :         if (procname(pid, nbuf, sizeof(nbuf))) {
     276             :                 printf("Stack trace for process %llu (%s):\n",
     277             :                         (unsigned long long)pid, nbuf);
     278             :         } else {
     279             :                 printf("Stack trace for process %llu:\n",
     280             :                         (unsigned long long)pid);
     281             :         }
     282             : 
     283             :         while (unw_step(&cursor) > 0) {
     284             :                 ip = sp = off = 0;
     285             :                 unw_get_reg(&cursor, UNW_REG_IP, &ip);
     286             :                 unw_get_reg(&cursor, UNW_REG_SP, &sp);
     287             : 
     288             :                 ret = unw_get_proc_name(&cursor, nbuf, sizeof(nbuf), &off);
     289             :                 if (ret != 0 && ret != -UNW_ENOMEM) {
     290             :                         snprintf(nbuf, sizeof(nbuf), "<unknown symbol>");
     291             :                 }
     292             :                 printf("    %s + %#llx [ip=%#llx] [sp=%#llx]\n",
     293             :                         nbuf, (long long)off, (long long)ip,
     294             :                         (long long)sp);
     295             :         }
     296             : 
     297             :         (*count)++;
     298             : 
     299             : cleanup:
     300             :         if (aspace) {
     301             :                 unw_destroy_addr_space(aspace);
     302             :         }
     303             : 
     304             :         if (pinfo) {
     305             :                 _UPT_destroy(pinfo);
     306             :         }
     307             : 
     308             :         ptrace(PTRACE_DETACH, pid, NULL, NULL);
     309             : }
     310             : 
     311             : static int stack_trace_server(pid_t pid, void *priv)
     312             : {
     313             :         print_stack_trace(pid, (int *)priv);
     314             :         return 0;
     315             : }
     316             : 
     317             : static bool do_daemon_stack_trace(struct tevent_context *ev_ctx,
     318             :                                   struct messaging_context *msg_ctx,
     319             :                                   const struct server_id pid,
     320             :                                   const int argc, const char **argv)
     321             : {
     322             :         pid_t   dest;
     323             :         int     count = 0;
     324             : 
     325             :         if (argc != 1) {
     326             :                 fprintf(stderr, "Usage: smbcontrol <dest> stacktrace\n");
     327             :                 return False;
     328             :         }
     329             : 
     330             :         dest = procid_to_pid(&pid);
     331             : 
     332             :         if (dest != 0) {
     333             :                 /* It would be nice to be able to make sure that this PID is
     334             :                  * the PID of a smbd/winbind/nmbd process, not some random PID
     335             :                  * the user liked the look of. It doesn't seem like it's worth
     336             :                  * the effort at the moment, however.
     337             :                  */
     338             :                 print_stack_trace(dest, &count);
     339             :         } else {
     340             :                 messaging_dgm_forall(stack_trace_server, &count);
     341             :         }
     342             : 
     343             :         return True;
     344             : }
     345             : 
     346             : #else /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
     347             : 
     348           0 : static bool do_daemon_stack_trace(struct tevent_context *ev_ctx,
     349             :                                   struct messaging_context *msg_ctx,
     350             :                                   const struct server_id pid,
     351             :                                   const int argc, const char **argv)
     352             : {
     353           0 :         fprintf(stderr,
     354             :                 "Daemon stack tracing is not supported on this platform\n");
     355           0 :         return False;
     356             : }
     357             : 
     358             : #endif /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
     359             : 
     360             : /* Inject a fault (fatal signal) into a running smbd */
     361             : 
     362           1 : static bool do_inject_fault(struct tevent_context *ev_ctx,
     363             :                             struct messaging_context *msg_ctx,
     364             :                             const struct server_id pid,
     365             :                             const int argc, const char **argv)
     366             : {
     367           1 :         if (argc != 2) {
     368           0 :                 fprintf(stderr, "Usage: smbcontrol <dest> inject "
     369             :                         "<bus|hup|term|internal|segv>\n");
     370           0 :                 return False;
     371             :         }
     372             : 
     373             : #if !defined(DEVELOPER) && !defined(ENABLE_SELFTEST)
     374             :         fprintf(stderr, "Fault injection is only available in "
     375             :                 "developer and self test builds\n");
     376             :         return False;
     377             : #else /* DEVELOPER || ENABLE_SELFTEST */
     378             :         {
     379           1 :                 int sig = 0;
     380             : 
     381           1 :                 if (strcmp(argv[1], "bus") == 0) {
     382           0 :                         sig = SIGBUS;
     383           1 :                 } else if (strcmp(argv[1], "hup") == 0) {
     384           0 :                         sig = SIGHUP;
     385           1 :                 } else if (strcmp(argv[1], "term") == 0) {
     386           0 :                         sig = SIGTERM;
     387           1 :                 } else if (strcmp(argv[1], "segv") == 0) {
     388           1 :                         sig = SIGSEGV;
     389           0 :                 } else if (strcmp(argv[1], "internal") == 0) {
     390             :                         /* Force an internal error, ie. an unclean exit. */
     391           0 :                         sig = -1;
     392             :                 } else {
     393           0 :                         fprintf(stderr, "Unknown signal name '%s'\n", argv[1]);
     394           0 :                         return False;
     395             :                 }
     396             : 
     397           1 :                 return send_message(msg_ctx, pid, MSG_SMB_INJECT_FAULT,
     398             :                                     &sig, sizeof(int));
     399             :         }
     400             : #endif /* DEVELOPER || ENABLE_SELFTEST */
     401             : }
     402             : 
     403           1 : static bool do_sleep(struct tevent_context *ev_ctx,
     404             :                      struct messaging_context *msg_ctx,
     405             :                      const struct server_id pid,
     406             :                      const int argc, const char **argv)
     407             : {
     408             : #if defined(DEVELOPER) || defined(ENABLE_SELFTEST)
     409             :         unsigned int seconds;
     410             :         long input;
     411           1 :         const long MAX_SLEEP = 60 * 60; /* One hour maximum sleep */
     412             : #endif
     413             : 
     414           1 :         if (argc != 2) {
     415           0 :                 fprintf(stderr, "Usage: smbcontrol <dest> sleep seconds\n");
     416           0 :                 return False;
     417             :         }
     418             : 
     419             : #if !defined(DEVELOPER) && !defined(ENABLE_SELFTEST)
     420             :         fprintf(stderr, "Sleep is only available in "
     421             :                 "developer and self test builds\n");
     422             :         return False;
     423             : #else /* DEVELOPER || ENABLE_SELFTEST */
     424             : 
     425           1 :         input = atol(argv[1]);
     426           1 :         if (input < 1 || input > MAX_SLEEP) {
     427           0 :                 fprintf(stderr,
     428             :                         "Invalid duration for sleep '%s'\n"
     429             :                         "It should be at least 1 second and no more than %ld\n",
     430           0 :                         argv[1],
     431             :                         MAX_SLEEP);
     432           0 :                 return False;
     433             :         }
     434           1 :         seconds = input;
     435           1 :         return send_message(msg_ctx, pid,
     436             :                             MSG_SMB_SLEEP,
     437             :                             &seconds,
     438             :                             sizeof(unsigned int));
     439             : #endif /* DEVELOPER || ENABLE_SELFTEST */
     440             : }
     441             : 
     442             : /* Force a browser election */
     443             : 
     444           0 : static bool do_election(struct tevent_context *ev_ctx,
     445             :                         struct messaging_context *msg_ctx,
     446             :                         const struct server_id pid,
     447             :                         const int argc, const char **argv)
     448             : {
     449           0 :         if (argc != 1) {
     450           0 :                 fprintf(stderr, "Usage: smbcontrol <dest> force-election\n");
     451           0 :                 return False;
     452             :         }
     453             : 
     454           0 :         return send_message(msg_ctx, pid, MSG_FORCE_ELECTION, NULL, 0);
     455             : }
     456             : 
     457             : /* Ping a samba daemon process */
     458             : 
     459          81 : static void pong_cb(struct messaging_context *msg,
     460             :                     void *private_data, 
     461             :                     uint32_t msg_type, 
     462             :                     struct server_id pid,
     463             :                     DATA_BLOB *data)
     464             : {
     465             :         struct server_id_buf src_string;
     466          81 :         printf("PONG from pid %s\n", server_id_str_buf(pid, &src_string));
     467          81 :         num_replies++;
     468          81 : }
     469             : 
     470          82 : static bool do_ping(struct tevent_context *ev_ctx,
     471             :                     struct messaging_context *msg_ctx,
     472             :                     const struct server_id pid,
     473             :                     const int argc, const char **argv)
     474             : {
     475          82 :         if (argc != 1) {
     476           0 :                 fprintf(stderr, "Usage: smbcontrol <dest> ping\n");
     477           0 :                 return False;
     478             :         }
     479             : 
     480             :         /* Send a message and register our interest in a reply */
     481             : 
     482          82 :         if (!send_message(msg_ctx, pid, MSG_PING, NULL, 0))
     483           0 :                 return False;
     484             : 
     485          82 :         messaging_register(msg_ctx, NULL, MSG_PONG, pong_cb);
     486             : 
     487          82 :         wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
     488             : 
     489             :         /* No replies were received within the timeout period */
     490             : 
     491          82 :         if (num_replies == 0)
     492           1 :                 printf("No replies received\n");
     493             : 
     494          82 :         messaging_deregister(msg_ctx, MSG_PONG, NULL);
     495             : 
     496          82 :         return num_replies;
     497             : }
     498             : 
     499             : /* Set profiling options */
     500             : 
     501           0 : static bool do_profile(struct tevent_context *ev_ctx,
     502             :                        struct messaging_context *msg_ctx,
     503             :                        const struct server_id pid,
     504             :                        const int argc, const char **argv)
     505             : {
     506             :         int v;
     507             : 
     508           0 :         if (argc != 2) {
     509           0 :                 fprintf(stderr, "Usage: smbcontrol <dest> profile "
     510             :                         "<off|count|on|flush>\n");
     511           0 :                 return False;
     512             :         }
     513             : 
     514           0 :         if (strcmp(argv[1], "off") == 0) {
     515           0 :                 v = 0;
     516           0 :         } else if (strcmp(argv[1], "count") == 0) {
     517           0 :                 v = 1;
     518           0 :         } else if (strcmp(argv[1], "on") == 0) {
     519           0 :                 v = 2;
     520           0 :         } else if (strcmp(argv[1], "flush") == 0) {
     521           0 :                 v = 3;
     522             :         } else {
     523           0 :                 fprintf(stderr, "Unknown profile command '%s'\n", argv[1]);
     524           0 :                 return False;
     525             :         }
     526             : 
     527           0 :         return send_message(msg_ctx, pid, MSG_PROFILE, &v, sizeof(int));
     528             : }
     529             : 
     530             : /* Return the profiling level */
     531             : 
     532           0 : static void profilelevel_cb(struct messaging_context *msg_ctx,
     533             :                             void *private_data, 
     534             :                             uint32_t msg_type, 
     535             :                             struct server_id pid,
     536             :                             DATA_BLOB *data)
     537             : {
     538             :         int level;
     539             :         const char *s;
     540             : 
     541           0 :         num_replies++;
     542             : 
     543           0 :         if (data->length != sizeof(int)) {
     544           0 :                 fprintf(stderr, "invalid message length %ld returned\n", 
     545           0 :                         (unsigned long)data->length);
     546           0 :                 return;
     547             :         }
     548             : 
     549           0 :         memcpy(&level, data->data, sizeof(int));
     550             : 
     551           0 :         switch (level) {
     552           0 :         case 0:
     553           0 :                 s = "not enabled";
     554           0 :                 break;
     555           0 :         case 1:
     556           0 :                 s = "off";
     557           0 :                 break;
     558           0 :         case 3:
     559           0 :                 s = "count only";
     560           0 :                 break;
     561           0 :         case 7:
     562           0 :                 s = "count and time";
     563           0 :                 break;
     564           0 :         default:
     565           0 :                 s = "BOGUS";
     566           0 :                 break;
     567             :         }
     568             : 
     569           0 :         printf("Profiling %s on pid %u\n",s,(unsigned int)procid_to_pid(&pid));
     570             : }
     571             : 
     572           0 : static void profilelevel_rqst(struct messaging_context *msg_ctx,
     573             :                               void *private_data, 
     574             :                               uint32_t msg_type, 
     575             :                               struct server_id pid,
     576             :                               DATA_BLOB *data)
     577             : {
     578           0 :         int v = 0;
     579             : 
     580             :         /* Send back a dummy reply */
     581             : 
     582           0 :         send_message(msg_ctx, pid, MSG_PROFILELEVEL, &v, sizeof(int));
     583           0 : }
     584             : 
     585           0 : static bool do_profilelevel(struct tevent_context *ev_ctx,
     586             :                             struct messaging_context *msg_ctx,
     587             :                             const struct server_id pid,
     588             :                             const int argc, const char **argv)
     589             : {
     590           0 :         if (argc != 1) {
     591           0 :                 fprintf(stderr, "Usage: smbcontrol <dest> profilelevel\n");
     592           0 :                 return False;
     593             :         }
     594             : 
     595             :         /* Send a message and register our interest in a reply */
     596             : 
     597           0 :         if (!send_message(msg_ctx, pid, MSG_REQ_PROFILELEVEL, NULL, 0))
     598           0 :                 return False;
     599             : 
     600           0 :         messaging_register(msg_ctx, NULL, MSG_PROFILELEVEL, profilelevel_cb);
     601           0 :         messaging_register(msg_ctx, NULL, MSG_REQ_PROFILELEVEL,
     602             :                            profilelevel_rqst);
     603             : 
     604           0 :         wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
     605             : 
     606             :         /* No replies were received within the timeout period */
     607             : 
     608           0 :         if (num_replies == 0)
     609           0 :                 printf("No replies received\n");
     610             : 
     611           0 :         messaging_deregister(msg_ctx, MSG_PROFILE, NULL);
     612             : 
     613           0 :         return num_replies;
     614             : }
     615             : 
     616             : /* Display debug level settings */
     617             : 
     618           0 : static bool do_debuglevel(struct tevent_context *ev_ctx,
     619             :                           struct messaging_context *msg_ctx,
     620             :                           const struct server_id pid,
     621             :                           const int argc, const char **argv)
     622             : {
     623           0 :         if (argc != 1) {
     624           0 :                 fprintf(stderr, "Usage: smbcontrol <dest> debuglevel\n");
     625           0 :                 return False;
     626             :         }
     627             : 
     628             :         /* Send a message and register our interest in a reply */
     629             : 
     630           0 :         if (!send_message(msg_ctx, pid, MSG_REQ_DEBUGLEVEL, NULL, 0))
     631           0 :                 return False;
     632             : 
     633           0 :         messaging_register(msg_ctx, NULL, MSG_DEBUGLEVEL, print_pid_string_cb);
     634             : 
     635           0 :         wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
     636             : 
     637             :         /* No replies were received within the timeout period */
     638             : 
     639           0 :         if (num_replies == 0)
     640           0 :                 printf("No replies received\n");
     641             : 
     642           0 :         messaging_deregister(msg_ctx, MSG_DEBUGLEVEL, NULL);
     643             : 
     644           0 :         return num_replies;
     645             : }
     646             : 
     647             : /* Send a print notify message */
     648             : 
     649           0 : static bool do_printnotify(struct tevent_context *ev_ctx,
     650             :                            struct messaging_context *msg_ctx,
     651             :                            const struct server_id pid,
     652             :                            const int argc, const char **argv)
     653             : {
     654             :         const char *cmd;
     655             : 
     656             :         /* Check for subcommand */
     657             : 
     658           0 :         if (argc == 1) {
     659           0 :                 fprintf(stderr, "Must specify subcommand:\n");
     660           0 :                 fprintf(stderr, "\tqueuepause <printername>\n");
     661           0 :                 fprintf(stderr, "\tqueueresume <printername>\n");
     662           0 :                 fprintf(stderr, "\tjobpause <printername> <unix jobid>\n");
     663           0 :                 fprintf(stderr, "\tjobresume <printername> <unix jobid>\n");
     664           0 :                 fprintf(stderr, "\tjobdelete <printername> <unix jobid>\n");
     665           0 :                 fprintf(stderr, "\tprinter <printername> <comment|port|"
     666             :                         "driver> <value>\n");
     667             : 
     668           0 :                 return False;
     669             :         }
     670             : 
     671           0 :         cmd = argv[1];
     672             : 
     673           0 :         if (strcmp(cmd, "queuepause") == 0) {
     674             : 
     675           0 :                 if (argc != 3) {
     676           0 :                         fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
     677             :                                 " queuepause <printername>\n");
     678           0 :                         return False;
     679             :                 }
     680             : 
     681           0 :                 notify_printer_status_byname(ev_ctx, msg_ctx, argv[2],
     682             :                                              PRINTER_STATUS_PAUSED);
     683             : 
     684           0 :                 goto send;
     685             : 
     686           0 :         } else if (strcmp(cmd, "queueresume") == 0) {
     687             : 
     688           0 :                 if (argc != 3) {
     689           0 :                         fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
     690             :                                 " queuereume <printername>\n");
     691           0 :                         return False;
     692             :                 }
     693             : 
     694           0 :                 notify_printer_status_byname(ev_ctx, msg_ctx, argv[2],
     695             :                                              PRINTER_STATUS_OK);
     696             : 
     697           0 :                 goto send;
     698             : 
     699           0 :         } else if (strcmp(cmd, "jobpause") == 0) {
     700             :                 int jobid;
     701             : 
     702           0 :                 if (argc != 4) {
     703           0 :                         fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
     704             :                                 " jobpause <printername> <unix-jobid>\n");
     705           0 :                         return False;
     706             :                 }
     707             : 
     708           0 :                 jobid = atoi(argv[3]);
     709             : 
     710           0 :                 notify_job_status_byname(
     711             :                         ev_ctx, msg_ctx,
     712           0 :                         argv[2], jobid, JOB_STATUS_PAUSED,
     713             :                         SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
     714             : 
     715           0 :                 goto send;
     716             : 
     717           0 :         } else if (strcmp(cmd, "jobresume") == 0) {
     718             :                 int jobid;
     719             : 
     720           0 :                 if (argc != 4) {
     721           0 :                         fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
     722             :                                 " jobpause <printername> <unix-jobid>\n");
     723           0 :                         return False;
     724             :                 }
     725             : 
     726           0 :                 jobid = atoi(argv[3]);
     727             : 
     728           0 :                 notify_job_status_byname(
     729             :                         ev_ctx, msg_ctx,
     730           0 :                         argv[2], jobid, JOB_STATUS_QUEUED, 
     731             :                         SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
     732             : 
     733           0 :                 goto send;
     734             : 
     735           0 :         } else if (strcmp(cmd, "jobdelete") == 0) {
     736             :                 int jobid;
     737             : 
     738           0 :                 if (argc != 4) {
     739           0 :                         fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
     740             :                                 " jobpause <printername> <unix-jobid>\n");
     741           0 :                         return False;
     742             :                 }
     743             : 
     744           0 :                 jobid = atoi(argv[3]);
     745             : 
     746           0 :                 notify_job_status_byname(
     747             :                         ev_ctx, msg_ctx,
     748           0 :                         argv[2], jobid, JOB_STATUS_DELETING,
     749             :                         SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
     750             : 
     751           0 :                 notify_job_status_byname(
     752             :                         ev_ctx, msg_ctx,
     753           0 :                         argv[2], jobid, JOB_STATUS_DELETING|
     754             :                         JOB_STATUS_DELETED,
     755             :                         SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
     756             : 
     757           0 :                 goto send;
     758             : 
     759           0 :         } else if (strcmp(cmd, "printer") == 0) {
     760             :                 uint32_t attribute;
     761             : 
     762           0 :                 if (argc != 5) {
     763           0 :                         fprintf(stderr, "Usage: smbcontrol <dest> printnotify "
     764             :                                 "printer <printername> <comment|port|driver> "
     765             :                                 "<value>\n");
     766           0 :                         return False;
     767             :                 }
     768             : 
     769           0 :                 if (strcmp(argv[3], "comment") == 0) {
     770           0 :                         attribute = PRINTER_NOTIFY_FIELD_COMMENT;
     771           0 :                 } else if (strcmp(argv[3], "port") == 0) {
     772           0 :                         attribute = PRINTER_NOTIFY_FIELD_PORT_NAME;
     773           0 :                 } else if (strcmp(argv[3], "driver") == 0) {
     774           0 :                         attribute = PRINTER_NOTIFY_FIELD_DRIVER_NAME;
     775             :                 } else {
     776           0 :                         fprintf(stderr, "Invalid printer command '%s'\n",
     777           0 :                                 argv[3]);
     778           0 :                         return False;
     779             :                 }
     780             : 
     781           0 :                 notify_printer_byname(ev_ctx, msg_ctx, argv[2], attribute,
     782           0 :                                       discard_const_p(char, argv[4]));
     783             : 
     784           0 :                 goto send;
     785             :         }
     786             : 
     787           0 :         fprintf(stderr, "Invalid subcommand '%s'\n", cmd);
     788           0 :         return False;
     789             : 
     790           0 : send:
     791           0 :         print_notify_send_messages(msg_ctx, 0);
     792           0 :         return True;
     793             : }
     794             : 
     795             : /* Close a share */
     796             : 
     797           0 : static bool do_closeshare(struct tevent_context *ev_ctx,
     798             :                           struct messaging_context *msg_ctx,
     799             :                           const struct server_id pid,
     800             :                           const int argc, const char **argv)
     801             : {
     802           0 :         if (argc != 2) {
     803           0 :                 fprintf(stderr, "Usage: smbcontrol <dest> close-share "
     804             :                         "<sharename>\n");
     805           0 :                 return False;
     806             :         }
     807             : 
     808           0 :         return send_message(msg_ctx, pid, MSG_SMB_FORCE_TDIS, argv[1],
     809           0 :                             strlen(argv[1]) + 1);
     810             : }
     811             : 
     812             : /*
     813             :  * Close a share if access denied by now
     814             :  **/
     815             : 
     816           0 : static bool do_close_denied_share(
     817             :         struct tevent_context *ev_ctx,
     818             :         struct messaging_context *msg_ctx,
     819             :         const struct server_id pid,
     820             :         const int argc, const char **argv)
     821             : {
     822           0 :         if (argc != 2) {
     823           0 :                 fprintf(stderr, "Usage: smbcontrol <dest> close-denied-share "
     824             :                         "<sharename>\n");
     825           0 :                 return False;
     826             :         }
     827             : 
     828           0 :         return send_message(
     829             :                 msg_ctx,
     830             :                 pid,
     831             :                 MSG_SMB_FORCE_TDIS_DENIED,
     832           0 :                 argv[1],
     833           0 :                 strlen(argv[1]) + 1);
     834             : }
     835             : 
     836             : /* Kill a client by IP address */
     837           0 : static bool do_kill_client_by_ip(struct tevent_context *ev_ctx,
     838             :                                  struct messaging_context *msg_ctx,
     839             :                                  const struct server_id pid,
     840             :                                  const int argc, const char **argv)
     841             : {
     842           0 :         if (argc != 2) {
     843           0 :                 fprintf(stderr, "Usage: smbcontrol <dest> kill-client-ip "
     844             :                         "<IP address>\n");
     845           0 :                 return false;
     846             :         }
     847             : 
     848           0 :         if (!is_ipaddress_v4(argv[1]) && !is_ipaddress_v6(argv[1])) {
     849           0 :                 fprintf(stderr, "%s is not a valid IP address!\n", argv[1]);
     850           0 :                 return false;
     851             :         }
     852             : 
     853           0 :         return send_message(msg_ctx, pid, MSG_SMB_KILL_CLIENT_IP,
     854           0 :                             argv[1], strlen(argv[1]) + 1);
     855             : }
     856             : 
     857             : /* Tell winbindd an IP got dropped */
     858             : 
     859           0 : static bool do_ip_dropped(struct tevent_context *ev_ctx,
     860             :                           struct messaging_context *msg_ctx,
     861             :                           const struct server_id pid,
     862             :                           const int argc, const char **argv)
     863             : {
     864           0 :         if (argc != 2) {
     865           0 :                 fprintf(stderr, "Usage: smbcontrol <dest> ip-dropped "
     866             :                         "<ip-address>\n");
     867           0 :                 return False;
     868             :         }
     869             : 
     870           0 :         return send_message(msg_ctx, pid, MSG_WINBIND_IP_DROPPED, argv[1],
     871           0 :                             strlen(argv[1]) + 1);
     872             : }
     873             : 
     874             : /* Display talloc pool usage */
     875             : 
     876           0 : static bool do_poolusage(struct tevent_context *ev_ctx,
     877             :                          struct messaging_context *msg_ctx,
     878             :                          const struct server_id dst,
     879             :                          const int argc, const char **argv)
     880             : {
     881           0 :         pid_t pid = procid_to_pid(&dst);
     882           0 :         int stdout_fd = 1;
     883             : 
     884           0 :         if (argc != 1) {
     885           0 :                 fprintf(stderr, "Usage: smbcontrol <dest> pool-usage\n");
     886           0 :                 return False;
     887             :         }
     888             : 
     889           0 :         if (pid == 0) {
     890           0 :                 fprintf(stderr, "Can only send to a specific PID\n");
     891           0 :                 return false;
     892             :         }
     893             : 
     894           0 :         messaging_send_iov(
     895             :                 msg_ctx,
     896             :                 dst,
     897             :                 MSG_REQ_POOL_USAGE,
     898             :                 NULL,
     899             :                 0,
     900             :                 &stdout_fd,
     901             :                 1);
     902             : 
     903           0 :         return true;
     904             : }
     905             : 
     906           0 : static bool do_rpc_dump_status(
     907             :         struct tevent_context *ev_ctx,
     908             :         struct messaging_context *msg_ctx,
     909             :         const struct server_id dst,
     910             :         const int argc,
     911             :         const char **argv)
     912             : {
     913           0 :         pid_t pid = procid_to_pid(&dst);
     914           0 :         int stdout_fd = 1;
     915             : 
     916           0 :         if (argc != 1) {
     917           0 :                 fprintf(stderr,
     918             :                         "Usage: smbcontrol <dest> rpc-dump-status\n");
     919           0 :                 return False;
     920             :         }
     921             : 
     922           0 :         if (pid == 0) {
     923           0 :                 fprintf(stderr, "Can only send to a specific PID\n");
     924           0 :                 return false;
     925             :         }
     926             : 
     927           0 :         messaging_send_iov(
     928             :                 msg_ctx,
     929             :                 dst,
     930             :                 MSG_RPC_DUMP_STATUS,
     931             :                 NULL,
     932             :                 0,
     933             :                 &stdout_fd,
     934             :                 1);
     935             : 
     936           0 :         return true;
     937             : }
     938             : 
     939             : /* Fetch and print the ringbuf log */
     940             : 
     941           0 : static void print_ringbuf_log_cb(struct messaging_context *msg,
     942             :                                  void *private_data,
     943             :                                  uint32_t msg_type,
     944             :                                  struct server_id pid,
     945             :                                  DATA_BLOB *data)
     946             : {
     947           0 :         printf("%s", (const char *)data->data);
     948           0 :         num_replies++;
     949           0 : }
     950             : 
     951           0 : static bool do_ringbuflog(struct tevent_context *ev_ctx,
     952             :                           struct messaging_context *msg_ctx,
     953             :                           const struct server_id pid,
     954             :                           const int argc, const char **argv)
     955             : {
     956           0 :         if (argc != 1) {
     957           0 :                 fprintf(stderr, "Usage: smbcontrol <dest> ringbuf-log\n");
     958           0 :                 return false;
     959             :         }
     960             : 
     961           0 :         messaging_register(msg_ctx, NULL, MSG_RINGBUF_LOG,
     962             :                            print_ringbuf_log_cb);
     963             : 
     964             :         /* Send a message and register our interest in a reply */
     965             : 
     966           0 :         if (!send_message(msg_ctx, pid, MSG_REQ_RINGBUF_LOG, NULL, 0)) {
     967           0 :                 return false;
     968             :         }
     969             : 
     970           0 :         wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
     971             : 
     972             :         /* No replies were received within the timeout period */
     973             : 
     974           0 :         if (num_replies == 0) {
     975           0 :                 printf("No replies received\n");
     976             :         }
     977             : 
     978           0 :         messaging_deregister(msg_ctx, MSG_RINGBUF_LOG, NULL);
     979             : 
     980           0 :         return num_replies != 0;
     981             : }
     982             : 
     983             : /* Perform a dmalloc mark */
     984             : 
     985           0 : static bool do_dmalloc_mark(struct tevent_context *ev_ctx,
     986             :                             struct messaging_context *msg_ctx,
     987             :                             const struct server_id pid,
     988             :                             const int argc, const char **argv)
     989             : {
     990           0 :         if (argc != 1) {
     991           0 :                 fprintf(stderr, "Usage: smbcontrol <dest> dmalloc-mark\n");
     992           0 :                 return False;
     993             :         }
     994             : 
     995           0 :         return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_MARK, NULL, 0);
     996             : }
     997             : 
     998             : /* Perform a dmalloc changed */
     999             : 
    1000           0 : static bool do_dmalloc_changed(struct tevent_context *ev_ctx,
    1001             :                                struct messaging_context *msg_ctx,
    1002             :                                const struct server_id pid,
    1003             :                                const int argc, const char **argv)
    1004             : {
    1005           0 :         if (argc != 1) {
    1006           0 :                 fprintf(stderr, "Usage: smbcontrol <dest> "
    1007             :                         "dmalloc-log-changed\n");
    1008           0 :                 return False;
    1009             :         }
    1010             : 
    1011           0 :         return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_LOG_CHANGED,
    1012             :                             NULL, 0);
    1013             : }
    1014             : 
    1015           0 : static void print_uint32_cb(struct messaging_context *msg, void *private_data,
    1016             :                             uint32_t msg_type, struct server_id pid,
    1017             :                             DATA_BLOB *data)
    1018             : {
    1019             :         uint32_t num_children;
    1020             : 
    1021           0 :         if (data->length != sizeof(uint32_t)) {
    1022           0 :                 printf("Invalid response: %d bytes long\n",
    1023           0 :                        (int)data->length);
    1024           0 :                 goto done;
    1025             :         }
    1026           0 :         num_children = IVAL(data->data, 0);
    1027           0 :         printf("%u children\n", (unsigned)num_children);
    1028           0 : done:
    1029           0 :         num_replies++;
    1030           0 : }
    1031             : 
    1032           0 : static bool do_num_children(struct tevent_context *ev_ctx,
    1033             :                             struct messaging_context *msg_ctx,
    1034             :                             const struct server_id pid,
    1035             :                             const int argc, const char **argv)
    1036             : {
    1037           0 :         if (argc != 1) {
    1038           0 :                 fprintf(stderr, "Usage: smbcontrol <dest> num-children\n");
    1039           0 :                 return False;
    1040             :         }
    1041             : 
    1042           0 :         messaging_register(msg_ctx, NULL, MSG_SMB_NUM_CHILDREN,
    1043             :                            print_uint32_cb);
    1044             : 
    1045             :         /* Send a message and register our interest in a reply */
    1046             : 
    1047           0 :         if (!send_message(msg_ctx, pid, MSG_SMB_TELL_NUM_CHILDREN, NULL, 0))
    1048           0 :                 return false;
    1049             : 
    1050           0 :         wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
    1051             : 
    1052             :         /* No replies were received within the timeout period */
    1053             : 
    1054           0 :         if (num_replies == 0)
    1055           0 :                 printf("No replies received\n");
    1056             : 
    1057           0 :         messaging_deregister(msg_ctx, MSG_SMB_NUM_CHILDREN, NULL);
    1058             : 
    1059           0 :         return num_replies;
    1060             : }
    1061             : 
    1062           0 : static bool do_msg_cleanup(struct tevent_context *ev_ctx,
    1063             :                            struct messaging_context *msg_ctx,
    1064             :                            const struct server_id pid,
    1065             :                            const int argc, const char **argv)
    1066             : {
    1067             :         int ret;
    1068             : 
    1069           0 :         ret = messaging_cleanup(msg_ctx, pid.pid);
    1070             : 
    1071           0 :         printf("cleanup(%u) returned %s\n", (unsigned)pid.pid,
    1072           0 :                ret ? strerror(ret) : "ok");
    1073             : 
    1074           0 :         return (ret == 0);
    1075             : }
    1076             : 
    1077             : /* Shutdown a server process */
    1078             : 
    1079           0 : static bool do_shutdown(struct tevent_context *ev_ctx,
    1080             :                         struct messaging_context *msg_ctx,
    1081             :                         const struct server_id pid,
    1082             :                         const int argc, const char **argv)
    1083             : {
    1084           0 :         if (argc != 1) {
    1085           0 :                 fprintf(stderr, "Usage: smbcontrol <dest> shutdown\n");
    1086           0 :                 return False;
    1087             :         }
    1088             : 
    1089           0 :         return send_message(msg_ctx, pid, MSG_SHUTDOWN, NULL, 0);
    1090             : }
    1091             : 
    1092             : /* Notify a driver upgrade */
    1093             : 
    1094           0 : static bool do_drvupgrade(struct tevent_context *ev_ctx,
    1095             :                           struct messaging_context *msg_ctx,
    1096             :                           const struct server_id pid,
    1097             :                           const int argc, const char **argv)
    1098             : {
    1099           0 :         if (argc != 2) {
    1100           0 :                 fprintf(stderr, "Usage: smbcontrol <dest> drvupgrade "
    1101             :                         "<driver-name>\n");
    1102           0 :                 return False;
    1103             :         }
    1104             : 
    1105           0 :         return send_message(msg_ctx, pid, MSG_PRINTER_DRVUPGRADE, argv[1],
    1106           0 :                             strlen(argv[1]) + 1);
    1107             : }
    1108             : 
    1109           0 : static bool do_winbind_online(struct tevent_context *ev_ctx,
    1110             :                               struct messaging_context *msg_ctx,
    1111             :                               const struct server_id pid,
    1112             :                               const int argc, const char **argv)
    1113             : {
    1114             :         TDB_CONTEXT *tdb;
    1115             :         char *db_path;
    1116             : 
    1117           0 :         if (argc != 1) {
    1118           0 :                 fprintf(stderr, "Usage: smbcontrol winbindd online\n");
    1119           0 :                 return False;
    1120             :         }
    1121             : 
    1122           0 :         db_path = state_path(talloc_tos(), "winbindd_cache.tdb");
    1123           0 :         if (db_path == NULL) {
    1124           0 :                 return false;
    1125             :         }
    1126             : 
    1127             :         /* Remove the entry in the winbindd_cache tdb to tell a later
    1128             :            starting winbindd that we're online. */
    1129             : 
    1130           0 :         tdb = tdb_open_log(db_path, 0, TDB_DEFAULT, O_RDWR, 0600);
    1131           0 :         if (!tdb) {
    1132           0 :                 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
    1133             :                         db_path);
    1134           0 :                 TALLOC_FREE(db_path);
    1135           0 :                 return False;
    1136             :         }
    1137             : 
    1138           0 :         TALLOC_FREE(db_path);
    1139           0 :         tdb_delete_bystring(tdb, "WINBINDD_OFFLINE");
    1140           0 :         tdb_close(tdb);
    1141             : 
    1142           0 :         return send_message(msg_ctx, pid, MSG_WINBIND_ONLINE, NULL, 0);
    1143             : }
    1144             : 
    1145           4 : static bool do_winbind_offline(struct tevent_context *ev_ctx,
    1146             :                                struct messaging_context *msg_ctx,
    1147             :                                const struct server_id pid,
    1148             :                                const int argc, const char **argv)
    1149             : {
    1150             :         TDB_CONTEXT *tdb;
    1151           4 :         bool ret = False;
    1152           4 :         int retry = 0;
    1153             :         char *db_path;
    1154             : 
    1155           4 :         if (argc != 1) {
    1156           0 :                 fprintf(stderr, "Usage: smbcontrol winbindd offline\n");
    1157           0 :                 return False;
    1158             :         }
    1159             : 
    1160           4 :         db_path = state_path(talloc_tos(), "winbindd_cache.tdb");
    1161           4 :         if (db_path == NULL) {
    1162           0 :                 return false;
    1163             :         }
    1164             : 
    1165             :         /* Create an entry in the winbindd_cache tdb to tell a later
    1166             :            starting winbindd that we're offline. We may actually create
    1167             :            it here... */
    1168             : 
    1169           4 :         tdb = tdb_open_log(db_path,
    1170             :                                 WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
    1171             :                                 TDB_DEFAULT|TDB_INCOMPATIBLE_HASH /* TDB_CLEAR_IF_FIRST */,
    1172             :                                 O_RDWR|O_CREAT, 0600);
    1173             : 
    1174           4 :         if (!tdb) {
    1175           0 :                 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
    1176             :                         db_path);
    1177           0 :                 TALLOC_FREE(db_path);
    1178           0 :                 return False;
    1179             :         }
    1180           4 :         TALLOC_FREE(db_path);
    1181             : 
    1182             :         /* There's a potential race condition that if a child
    1183             :            winbindd detects a domain is online at the same time
    1184             :            we're trying to tell it to go offline that it might 
    1185             :            delete the record we add between us adding it and
    1186             :            sending the message. Minimize this by retrying up to
    1187             :            5 times. */
    1188             : 
    1189           4 :         for (retry = 0; retry < 5; retry++) {
    1190             :                 uint8_t buf[4];
    1191           4 :                 TDB_DATA d = { .dptr = buf, .dsize = sizeof(buf) };
    1192             : 
    1193           4 :                 SIVAL(buf, 0, time(NULL));
    1194             : 
    1195           4 :                 tdb_store_bystring(tdb, "WINBINDD_OFFLINE", d, TDB_INSERT);
    1196             : 
    1197           4 :                 ret = send_message(msg_ctx, pid, MSG_WINBIND_OFFLINE,
    1198             :                                    NULL, 0);
    1199             : 
    1200             :                 /* Check that the entry "WINBINDD_OFFLINE" still exists. */
    1201           4 :                 d = tdb_fetch_bystring( tdb, "WINBINDD_OFFLINE" );
    1202           4 :                 if (d.dptr != NULL && d.dsize == 4) {
    1203           4 :                         SAFE_FREE(d.dptr);
    1204           4 :                         break;
    1205             :                 }
    1206             : 
    1207           0 :                 SAFE_FREE(d.dptr);
    1208           0 :                 DEBUG(10,("do_winbind_offline: offline state not set - retrying.\n"));
    1209             :         }
    1210             : 
    1211           4 :         tdb_close(tdb);
    1212           4 :         return ret;
    1213             : }
    1214             : 
    1215           0 : static bool do_winbind_onlinestatus(struct tevent_context *ev_ctx,
    1216             :                                     struct messaging_context *msg_ctx,
    1217             :                                     const struct server_id pid,
    1218             :                                     const int argc, const char **argv)
    1219             : {
    1220           0 :         if (argc != 1) {
    1221           0 :                 fprintf(stderr, "Usage: smbcontrol winbindd onlinestatus\n");
    1222           0 :                 return False;
    1223             :         }
    1224             : 
    1225           0 :         messaging_register(msg_ctx, NULL, MSG_WINBIND_ONLINESTATUS,
    1226             :                            print_pid_string_cb);
    1227             : 
    1228           0 :         if (!send_message(msg_ctx, pid, MSG_WINBIND_ONLINESTATUS, NULL, 0)) {
    1229           0 :                 return False;
    1230             :         }
    1231             : 
    1232           0 :         wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
    1233             : 
    1234             :         /* No replies were received within the timeout period */
    1235             : 
    1236           0 :         if (num_replies == 0)
    1237           0 :                 printf("No replies received\n");
    1238             : 
    1239           0 :         messaging_deregister(msg_ctx, MSG_WINBIND_ONLINESTATUS, NULL);
    1240             : 
    1241           0 :         return num_replies;
    1242             : }
    1243             : 
    1244           0 : static bool do_winbind_dump_domain_list(struct tevent_context *ev_ctx,
    1245             :                                         struct messaging_context *msg_ctx,
    1246             :                                         const struct server_id pid,
    1247             :                                         const int argc, const char **argv)
    1248             : {
    1249           0 :         const char *domain = NULL;
    1250           0 :         int domain_len = 0;
    1251             : 
    1252           0 :         if (argc < 1 || argc > 2) {
    1253           0 :                 fprintf(stderr, "Usage: smbcontrol <dest> dump-domain-list "
    1254             :                         "<domain>\n");
    1255           0 :                 return false;
    1256             :         }
    1257             : 
    1258           0 :         if (argc == 2) {
    1259           0 :                 domain = argv[1];
    1260           0 :                 domain_len = strlen(argv[1]) + 1;
    1261             :         }
    1262             : 
    1263           0 :         messaging_register(msg_ctx, NULL, MSG_WINBIND_DUMP_DOMAIN_LIST,
    1264             :                            print_pid_string_cb);
    1265             : 
    1266           0 :         if (!send_message(msg_ctx, pid, MSG_WINBIND_DUMP_DOMAIN_LIST,
    1267             :                           domain, domain_len))
    1268             :         {
    1269           0 :                 return false;
    1270             :         }
    1271             : 
    1272           0 :         wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
    1273             : 
    1274             :         /* No replies were received within the timeout period */
    1275             : 
    1276           0 :         if (num_replies == 0) {
    1277           0 :                 printf("No replies received\n");
    1278             :         }
    1279             : 
    1280           0 :         messaging_deregister(msg_ctx, MSG_WINBIND_DUMP_DOMAIN_LIST, NULL);
    1281             : 
    1282           0 :         return num_replies;
    1283             : }
    1284             : 
    1285           0 : static bool do_msg_disconnect_dc(struct tevent_context *ev_ctx,
    1286             :                                  struct messaging_context *msg_ctx,
    1287             :                                  const struct server_id pid,
    1288             :                                  const int argc, const char **argv)
    1289             : {
    1290           0 :         if (argc != 1) {
    1291           0 :                 fprintf(stderr, "Usage: smbcontrol <dest> disconnect-dc\n");
    1292           0 :                 return False;
    1293             :         }
    1294             : 
    1295           0 :         return send_message(msg_ctx, pid, MSG_WINBIND_DISCONNECT_DC, NULL, 0);
    1296             : }
    1297             : 
    1298           4 : static void winbind_validate_cache_cb(struct messaging_context *msg,
    1299             :                                       void *private_data,
    1300             :                                       uint32_t msg_type,
    1301             :                                       struct server_id pid,
    1302             :                                       DATA_BLOB *data)
    1303             : {
    1304             :         struct server_id_buf src_string;
    1305           8 :         printf("Winbindd cache is %svalid. (answer from pid %s)\n",
    1306           4 :                (*(data->data) == 0 ? "" : "NOT "),
    1307             :                server_id_str_buf(pid, &src_string));
    1308           4 :         num_replies++;
    1309           4 : }
    1310             : 
    1311           4 : static bool do_winbind_validate_cache(struct tevent_context *ev_ctx,
    1312             :                                       struct messaging_context *msg_ctx,
    1313             :                                       const struct server_id pid,
    1314             :                                       const int argc, const char **argv)
    1315             : {
    1316             :         struct server_id myid;
    1317             : 
    1318           4 :         myid = messaging_server_id(msg_ctx);
    1319             : 
    1320           4 :         if (argc != 1) {
    1321           0 :                 fprintf(stderr, "Usage: smbcontrol winbindd validate-cache\n");
    1322           0 :                 return False;
    1323             :         }
    1324             : 
    1325           4 :         messaging_register(msg_ctx, NULL, MSG_WINBIND_VALIDATE_CACHE,
    1326             :                            winbind_validate_cache_cb);
    1327             : 
    1328           4 :         if (!send_message(msg_ctx, pid, MSG_WINBIND_VALIDATE_CACHE, &myid,
    1329             :                           sizeof(myid))) {
    1330           0 :                 return False;
    1331             :         }
    1332             : 
    1333           4 :         wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);
    1334             : 
    1335           4 :         if (num_replies == 0) {
    1336           0 :                 printf("No replies received\n");
    1337             :         }
    1338             : 
    1339           4 :         messaging_deregister(msg_ctx, MSG_WINBIND_VALIDATE_CACHE, NULL);
    1340             : 
    1341           4 :         return num_replies;
    1342             : }
    1343             : 
    1344          10 : static bool do_reload_config(struct tevent_context *ev_ctx,
    1345             :                              struct messaging_context *msg_ctx,
    1346             :                              const struct server_id pid,
    1347             :                              const int argc, const char **argv)
    1348             : {
    1349          10 :         if (argc != 1) {
    1350           0 :                 fprintf(stderr, "Usage: smbcontrol <dest> reload-config\n");
    1351           0 :                 return False;
    1352             :         }
    1353             : 
    1354          10 :         return send_message(msg_ctx, pid, MSG_SMB_CONF_UPDATED, NULL, 0);
    1355             : }
    1356             : 
    1357           0 : static bool do_reload_printers(struct tevent_context *ev_ctx,
    1358             :                                struct messaging_context *msg_ctx,
    1359             :                                const struct server_id pid,
    1360             :                                const int argc, const char **argv)
    1361             : {
    1362           0 :         if (argc != 1) {
    1363           0 :                 fprintf(stderr, "Usage: smbcontrol <dest> reload-printers\n");
    1364           0 :                 return False;
    1365             :         }
    1366             : 
    1367           0 :         return send_message(msg_ctx, pid, MSG_PRINTER_PCAP, NULL, 0);
    1368             : }
    1369             : 
    1370           0 : static void my_make_nmb_name( struct nmb_name *n, const char *name, int type)
    1371             : {
    1372             :         fstring unix_name;
    1373           0 :         memset( (char *)n, '\0', sizeof(struct nmb_name) );
    1374           0 :         fstrcpy(unix_name, name);
    1375           0 :         (void)strupper_m(unix_name);
    1376           0 :         push_ascii(n->name, unix_name, sizeof(n->name), STR_TERMINATE);
    1377           0 :         n->name_type = (unsigned int)type & 0xFF;
    1378           0 :         push_ascii(n->scope,  lp_netbios_scope(), 64, STR_TERMINATE);
    1379           0 : }
    1380             : 
    1381           0 : static bool do_nodestatus(struct tevent_context *ev_ctx,
    1382             :                           struct messaging_context *msg_ctx,
    1383             :                           const struct server_id pid,
    1384             :                           const int argc, const char **argv)
    1385             : {
    1386             :         struct packet_struct p;
    1387             : 
    1388           0 :         if (argc != 2) {
    1389           0 :                 fprintf(stderr, "Usage: smbcontrol nmbd nodestatus <ip>\n");
    1390           0 :                 return False;
    1391             :         }
    1392             : 
    1393           0 :         ZERO_STRUCT(p);
    1394             : 
    1395           0 :         p.ip = interpret_addr2(argv[1]);
    1396           0 :         p.port = 137;
    1397           0 :         p.packet_type = NMB_PACKET;
    1398             : 
    1399           0 :         p.packet.nmb.header.name_trn_id = 10;
    1400           0 :         p.packet.nmb.header.opcode = 0;
    1401           0 :         p.packet.nmb.header.response = False;
    1402           0 :         p.packet.nmb.header.nm_flags.bcast = False;
    1403           0 :         p.packet.nmb.header.nm_flags.recursion_available = False;
    1404           0 :         p.packet.nmb.header.nm_flags.recursion_desired = False;
    1405           0 :         p.packet.nmb.header.nm_flags.trunc = False;
    1406           0 :         p.packet.nmb.header.nm_flags.authoritative = False;
    1407           0 :         p.packet.nmb.header.rcode = 0;
    1408           0 :         p.packet.nmb.header.qdcount = 1;
    1409           0 :         p.packet.nmb.header.ancount = 0;
    1410           0 :         p.packet.nmb.header.nscount = 0;
    1411           0 :         p.packet.nmb.header.arcount = 0;
    1412           0 :         my_make_nmb_name(&p.packet.nmb.question.question_name, "*", 0x00);
    1413           0 :         p.packet.nmb.question.question_type = 0x21;
    1414           0 :         p.packet.nmb.question.question_class = 0x1;
    1415             : 
    1416           0 :         return send_message(msg_ctx, pid, MSG_SEND_PACKET, &p, sizeof(p));
    1417             : }
    1418             : 
    1419           0 : static bool do_notify_cleanup(struct tevent_context *ev_ctx,
    1420             :                               struct messaging_context *msg_ctx,
    1421             :                               const struct server_id pid,
    1422             :                               const int argc, const char **argv)
    1423             : {
    1424           0 :         if (argc != 1) {
    1425           0 :                 fprintf(stderr, "Usage: smbcontrol smbd notify-cleanup\n");
    1426           0 :                 return false;
    1427             :         }
    1428           0 :         return send_message(msg_ctx, pid, MSG_SMB_NOTIFY_CLEANUP, NULL, 0);
    1429             : }
    1430             : 
    1431             : /* A list of message type supported */
    1432             : 
    1433             : static const struct {
    1434             :         const char *name;       /* Option name */
    1435             :         bool (*fn)(struct tevent_context *ev_ctx,
    1436             :                    struct messaging_context *msg_ctx,
    1437             :                    const struct server_id pid,
    1438             :                    const int argc, const char **argv);
    1439             :         const char *help;       /* Short help text */
    1440             : } msg_types[] = {
    1441             :         {
    1442             :                 .name = "debug",
    1443             :                 .fn   = do_debug,
    1444             :                 .help = "Set debuglevel",
    1445             :         },
    1446             :         {
    1447             :                 .name = "idmap",
    1448             :                 .fn   = do_idmap,
    1449             :                 .help = "Manipulate idmap cache",
    1450             :         },
    1451             :         {
    1452             :                 .name = "force-election",
    1453             :                 .fn   = do_election,
    1454             :                 .help = "Force a browse election",
    1455             :         },
    1456             :         {
    1457             :                 .name = "ping",
    1458             :                 .fn   = do_ping,
    1459             :                 .help = "Elicit a response",
    1460             :         },
    1461             :         {
    1462             :                 .name = "profile",
    1463             :                 .fn   = do_profile,
    1464             :                 .help = "",
    1465             :         },
    1466             :         {
    1467             :                 .name = "inject",
    1468             :                 .fn   = do_inject_fault,
    1469             :                 .help = "Inject a fatal signal into a running smbd"},
    1470             :         {
    1471             :                 .name = "stacktrace",
    1472             :                 .fn   = do_daemon_stack_trace,
    1473             :                 .help = "Display a stack trace of a daemon",
    1474             :         },
    1475             :         {
    1476             :                 .name = "profilelevel",
    1477             :                 .fn   = do_profilelevel,
    1478             :                 .help = "",
    1479             :         },
    1480             :         {
    1481             :                 .name = "debuglevel",
    1482             :                 .fn   = do_debuglevel,
    1483             :                 .help = "Display current debuglevels",
    1484             :         },
    1485             :         {
    1486             :                 .name = "printnotify",
    1487             :                 .fn   = do_printnotify,
    1488             :                 .help = "Send a print notify message",
    1489             :         },
    1490             :         {
    1491             :                 .name = "close-share",
    1492             :                 .fn   = do_closeshare,
    1493             :                 .help = "Forcibly disconnect a share",
    1494             :         },
    1495             :         {
    1496             :                 .name = "close-denied-share",
    1497             :                 .fn   = do_close_denied_share,
    1498             :                 .help = "Forcibly disconnect users from shares disallowed now",
    1499             :         },
    1500             :         {
    1501             :                 .name = "kill-client-ip",
    1502             :                 .fn   = do_kill_client_by_ip,
    1503             :                 .help = "Forcibly disconnect a client with a specific IP address",
    1504             :         },
    1505             :         {
    1506             :                 .name = "ip-dropped",
    1507             :                 .fn   = do_ip_dropped,
    1508             :                 .help = "Tell winbind that an IP got dropped",
    1509             :         },
    1510             :         {
    1511             :                 .name = "pool-usage",
    1512             :                 .fn   = do_poolusage,
    1513             :                 .help = "Display talloc memory usage",
    1514             :         },
    1515             :         {
    1516             :                 .name = "rpc-dump-status",
    1517             :                 .fn   = do_rpc_dump_status,
    1518             :                 .help = "Display rpc status",
    1519             :         },
    1520             :         {
    1521             :                 .name = "ringbuf-log",
    1522             :                 .fn   = do_ringbuflog,
    1523             :                 .help = "Display ringbuf log",
    1524             :         },
    1525             :         {
    1526             :                 .name = "dmalloc-mark",
    1527             :                 .fn   = do_dmalloc_mark,
    1528             :                 .help = "",
    1529             :         },
    1530             :         {
    1531             :                 .name = "dmalloc-log-changed",
    1532             :                 .fn   = do_dmalloc_changed,
    1533             :                 .help = "",
    1534             :         },
    1535             :         {
    1536             :                 .name = "shutdown",
    1537             :                 .fn   = do_shutdown,
    1538             :                 .help = "Shut down daemon",
    1539             :         },
    1540             :         {
    1541             :                 .name = "drvupgrade",
    1542             :                 .fn   = do_drvupgrade,
    1543             :                 .help = "Notify a printer driver has changed",
    1544             :         },
    1545             :         {
    1546             :                 .name = "reload-config",
    1547             :                 .fn   = do_reload_config,
    1548             :                 .help = "Force smbd or winbindd to reload config file"},
    1549             :         {
    1550             :                 .name = "reload-printers",
    1551             :                 .fn   = do_reload_printers,
    1552             :                 .help = "Force smbd to reload printers"},
    1553             :         {
    1554             :                 .name = "nodestatus",
    1555             :                 .fn   = do_nodestatus,
    1556             :                 .help = "Ask nmbd to do a node status request"},
    1557             :         {
    1558             :                 .name = "online",
    1559             :                 .fn   = do_winbind_online,
    1560             :                 .help = "Ask winbind to go into online state"},
    1561             :         {
    1562             :                 .name = "offline",
    1563             :                 .fn   = do_winbind_offline,
    1564             :                 .help = "Ask winbind to go into offline state"},
    1565             :         {
    1566             :                 .name = "onlinestatus",
    1567             :                 .fn   = do_winbind_onlinestatus,
    1568             :                 .help = "Request winbind online status"},
    1569             :         {
    1570             :                 .name = "validate-cache" ,
    1571             :                 .fn   = do_winbind_validate_cache,
    1572             :                 .help = "Validate winbind's credential cache",
    1573             :         },
    1574             :         {
    1575             :                 .name = "dump-domain-list",
    1576             :                 .fn   = do_winbind_dump_domain_list,
    1577             :                 .help = "Dump winbind domain list"},
    1578             :         {
    1579             :                 .name = "disconnect-dc",
    1580             :                 .fn   = do_msg_disconnect_dc,
    1581             :         },
    1582             :         {
    1583             :                 .name = "notify-cleanup",
    1584             :                 .fn   = do_notify_cleanup,
    1585             :         },
    1586             :         {
    1587             :                 .name = "num-children",
    1588             :                 .fn   = do_num_children,
    1589             :                 .help = "Print number of smbd child processes",
    1590             :         },
    1591             :         {
    1592             :                 .name = "msg-cleanup",
    1593             :                 .fn   = do_msg_cleanup,
    1594             :         },
    1595             :         {
    1596             :                 .name = "noop",
    1597             :                 .fn   = do_noop,
    1598             :                 .help = "Do nothing",
    1599             :         },
    1600             :         {
    1601             :                 .name = "sleep",
    1602             :                 .fn   = do_sleep,
    1603             :                 .help = "Cause the target process to sleep",
    1604             :         },
    1605             :         { .name = NULL, },
    1606             : };
    1607             : 
    1608             : /* Display usage information */
    1609             : 
    1610           0 : static void usage(poptContext pc)
    1611             : {
    1612             :         int i;
    1613             : 
    1614           0 :         poptPrintHelp(pc, stderr, 0);
    1615             : 
    1616           0 :         fprintf(stderr, "\n");
    1617           0 :         fprintf(stderr, "<destination> is one of \"nmbd\", \"smbd\", \"winbindd\" or a "
    1618             :                 "process ID\n");
    1619             : 
    1620           0 :         fprintf(stderr, "\n");
    1621           0 :         fprintf(stderr, "<message-type> is one of:\n");
    1622             : 
    1623           0 :         for (i = 0; msg_types[i].name; i++) {
    1624           0 :                 const char *help = msg_types[i].help;
    1625           0 :                 if (help == NULL) {
    1626           0 :                         help = "";
    1627             :                 }
    1628           0 :                 fprintf(stderr, "\t%-30s%s\n", msg_types[i].name, help);
    1629             :         }
    1630             : 
    1631           0 :         fprintf(stderr, "\n");
    1632             : 
    1633           0 :         exit(1);
    1634             : }
    1635             : 
    1636             : /* Return the pid number for a string destination */
    1637             : 
    1638         102 : static struct server_id parse_dest(struct messaging_context *msg,
    1639             :                                    const char *dest)
    1640             : {
    1641         102 :         struct server_id result = {
    1642             :                 .pid = (uint64_t)-1,
    1643             :         };
    1644             :         pid_t pid;
    1645             : 
    1646             :         /* Zero is a special return value for broadcast to all processes */
    1647             : 
    1648         102 :         if (strequal(dest, "all")) {
    1649           0 :                 return interpret_pid(MSG_BROADCAST_PID_STR);
    1650             :         }
    1651             : 
    1652             :         /* Try self - useful for testing */
    1653             : 
    1654         102 :         if (strequal(dest, "self")) {
    1655           0 :                 return messaging_server_id(msg);
    1656             :         }
    1657             : 
    1658             :         /* Fix winbind typo. */
    1659         102 :         if (strequal(dest, "winbind")) {
    1660           0 :                 dest = "winbindd";
    1661             :         }
    1662             : 
    1663             :         /* Check for numeric pid number */
    1664         102 :         result = interpret_pid(dest);
    1665             : 
    1666             :         /* Zero isn't valid if not "all". */
    1667         102 :         if (result.pid && procid_valid(&result)) {
    1668          84 :                 return result;
    1669             :         }
    1670             : 
    1671             :         /* Look up other destinations in pidfile directory */
    1672             : 
    1673          18 :         if ((pid = pidfile_pid(lp_pid_directory(), dest)) != 0) {
    1674          18 :                 return pid_to_procid(pid);
    1675             :         }
    1676             : 
    1677           0 :         fprintf(stderr,"Can't find pid for destination '%s'\n", dest);
    1678             : 
    1679           0 :         return result;
    1680             : }
    1681             : 
    1682             : /* Execute smbcontrol command */
    1683             : 
    1684         102 : static bool do_command(struct tevent_context *ev_ctx,
    1685             :                        struct messaging_context *msg_ctx,
    1686             :                        int argc, const char **argv)
    1687             : {
    1688         102 :         const char *dest = argv[0], *command = argv[1];
    1689             :         struct server_id pid;
    1690             :         int i;
    1691             : 
    1692             :         /* Check destination */
    1693             : 
    1694         102 :         pid = parse_dest(msg_ctx, dest);
    1695         102 :         if (!procid_valid(&pid)) {
    1696           0 :                 return False;
    1697             :         }
    1698             : 
    1699             :         /* Check command */
    1700             : 
    1701         805 :         for (i = 0; msg_types[i].name; i++) {
    1702         805 :                 if (strequal(command, msg_types[i].name))
    1703         102 :                         return msg_types[i].fn(ev_ctx, msg_ctx, pid,
    1704             :                                                argc - 1, argv + 1);
    1705             :         }
    1706             : 
    1707           0 :         fprintf(stderr, "smbcontrol: unknown command '%s'\n", command);
    1708             : 
    1709           0 :         return False;
    1710             : }
    1711             : 
    1712           0 : static void smbcontrol_help(poptContext pc,
    1713             :                     enum poptCallbackReason preason,
    1714             :                     struct poptOption * poption,
    1715             :                     const char * parg,
    1716             :                     void * pdata)
    1717             : {
    1718           0 :         if (poption->shortName != '?') {
    1719           0 :                 poptPrintUsage(pc, stdout, 0);
    1720             :         } else {
    1721           0 :                 usage(pc);
    1722             :         }
    1723             : 
    1724           0 :         exit(0);
    1725             : }
    1726             : 
    1727             : struct poptOption help_options[] = {
    1728             :         { NULL, '\0', POPT_ARG_CALLBACK, (void *)&smbcontrol_help, '\0',
    1729             :           NULL, NULL },
    1730             :         { "help", '?', 0, NULL, '?', "Show this help message", NULL },
    1731             :         { "usage", '\0', 0, NULL, 'u', "Display brief usage message", NULL },
    1732             :         {0}
    1733             : } ;
    1734             : 
    1735             : /* Main program */
    1736             : 
    1737         102 : int main(int argc, const char **argv)
    1738             : {
    1739             :         poptContext pc;
    1740             :         int opt;
    1741             :         struct tevent_context *evt_ctx;
    1742             :         struct messaging_context *msg_ctx;
    1743             : 
    1744         306 :         struct poptOption long_options[] = {
    1745             :                 /* POPT_AUTOHELP */
    1746             :                 { NULL, '\0', POPT_ARG_INCLUDE_TABLE, help_options,
    1747             :                                         0, "Help options:", NULL },
    1748             :                 { "timeout", 't', POPT_ARG_INT, &timeout, 't', 
    1749             :                   "Set timeout value in seconds", "TIMEOUT" },
    1750             : 
    1751         102 :                 POPT_COMMON_SAMBA
    1752         102 :                 POPT_COMMON_VERSION
    1753             :                 POPT_TABLEEND
    1754             :         };
    1755         102 :         TALLOC_CTX *frame = talloc_stackframe();
    1756         102 :         int ret = 0;
    1757             :         bool ok;
    1758             : 
    1759         102 :         smb_init_locale();
    1760             : 
    1761         102 :         ok = samba_cmdline_init(frame,
    1762             :                                 SAMBA_CMDLINE_CONFIG_CLIENT,
    1763             :                                 false /* require_smbconf */);
    1764         102 :         if (!ok) {
    1765           0 :                 DBG_ERR("Failed to init cmdline parser!\n");
    1766           0 :                 TALLOC_FREE(frame);
    1767           0 :                 exit(1);
    1768             :         }
    1769         102 :         lp_set_cmdline("log level", "0");
    1770             : 
    1771             :         /* Parse command line arguments using popt */
    1772             : 
    1773         102 :         pc = samba_popt_get_context(getprogname(),
    1774             :                                     argc,
    1775             :                                     argv,
    1776             :                                     long_options,
    1777             :                                     0);
    1778         102 :         if (pc == NULL) {
    1779           0 :                 DBG_ERR("Failed to setup popt context!\n");
    1780           0 :                 TALLOC_FREE(frame);
    1781           0 :                 exit(1);
    1782             :         }
    1783             : 
    1784         102 :         poptSetOtherOptionHelp(pc, "[OPTION...] <destination> <message-type> "
    1785             :                                "<parameters>");
    1786             : 
    1787         102 :         if (argc == 1)
    1788           0 :                 usage(pc);
    1789             : 
    1790         169 :         while ((opt = poptGetNextOpt(pc)) != -1) {
    1791           0 :                 switch(opt) {
    1792           0 :                 case 't':       /* --timeout */
    1793           0 :                         break;
    1794           0 :                 default:
    1795           0 :                         fprintf(stderr, "Invalid option\n");
    1796           0 :                         poptPrintHelp(pc, stderr, 0);
    1797           0 :                         break;
    1798             :                 }
    1799             :         }
    1800             : 
    1801             :         /* We should now have the remaining command line arguments in
    1802             :            argv.  The argc parameter should have been decremented to the
    1803             :            correct value in the above switch statement. */
    1804             : 
    1805         102 :         argv = (const char **)poptGetArgs(pc);
    1806         102 :         argc = 0;
    1807         102 :         if (argv != NULL) {
    1808         375 :                 while (argv[argc] != NULL) {
    1809         206 :                         argc++;
    1810             :                 }
    1811             :         }
    1812             : 
    1813         102 :         if (argc <= 1)
    1814           0 :                 usage(pc);
    1815             : 
    1816         102 :         msg_ctx = cmdline_messaging_context(get_dyn_CONFIGFILE());
    1817         102 :         if (msg_ctx == NULL) {
    1818           0 :                 fprintf(stderr,
    1819             :                         "Could not init messaging context, not root?\n");
    1820           0 :                 TALLOC_FREE(frame);
    1821           0 :                 exit(1);
    1822             :         }
    1823             : 
    1824         102 :         evt_ctx = global_event_context();
    1825             : 
    1826             :         /* Need to invert sense of return code -- samba
    1827             :          * routines mostly return True==1 for success, but
    1828             :          * shell needs 0. */ 
    1829             : 
    1830         102 :         ret = !do_command(evt_ctx, msg_ctx, argc, argv);
    1831             : 
    1832         102 :         cmdline_messaging_context_free();
    1833         102 :         poptFreeContext(pc);
    1834         102 :         TALLOC_FREE(frame);
    1835         102 :         return ret;
    1836             : }

Generated by: LCOV version 1.13