LCOV - code coverage report
Current view: top level - source3/utils - smbcontrol.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 153 617 24.8 %
Date: 2024-04-21 15:09:00 Functions: 17 52 32.7 %

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

Generated by: LCOV version 1.14