root/source3/utils/smbcontrol.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. send_message
  2. smbcontrol_timeout
  3. wait_replies
  4. print_pid_string_cb
  5. print_string_cb
  6. do_noop
  7. do_debug
  8. procname
  9. print_stack_trace
  10. stack_trace_connection
  11. do_daemon_stack_trace
  12. do_daemon_stack_trace
  13. do_inject_fault
  14. do_election
  15. pong_cb
  16. do_ping
  17. do_profile
  18. profilelevel_cb
  19. profilelevel_rqst
  20. do_profilelevel
  21. do_debuglevel
  22. do_printnotify
  23. do_closeshare
  24. do_lockretry
  25. do_brl_revalidate
  26. do_samsync
  27. do_samrepl
  28. do_poolusage
  29. do_dmalloc_mark
  30. do_dmalloc_changed
  31. do_shutdown
  32. do_drvupgrade
  33. do_winbind_online
  34. do_winbind_offline
  35. do_winbind_onlinestatus
  36. do_dump_event_list
  37. do_winbind_dump_domain_list
  38. winbind_validate_cache_cb
  39. do_winbind_validate_cache
  40. do_reload_config
  41. my_make_nmb_name
  42. do_nodestatus
  43. usage
  44. parse_dest
  45. do_command
  46. smbcontrol_help
  47. main

   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 
  28 #if HAVE_LIBUNWIND_H
  29 #include <libunwind.h>
  30 #endif
  31 
  32 #if HAVE_LIBUNWIND_PTRACE_H
  33 #include <libunwind-ptrace.h>
  34 #endif
  35 
  36 #if HAVE_SYS_PTRACE_H
  37 #include <sys/ptrace.h>
  38 #endif
  39 
  40 /* Default timeout value when waiting for replies (in seconds) */
  41 
  42 #define DEFAULT_TIMEOUT 10
  43 
  44 static int timeout = DEFAULT_TIMEOUT;
  45 static int num_replies;         /* Used by message callback fns */
  46 
  47 /* Send a message to a destination pid.  Zero means broadcast smbd. */
  48 
  49 static bool send_message(struct messaging_context *msg_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
  50                          struct server_id pid, int msg_type,
  51                          const void *buf, int len)
  52 {
  53         bool ret;
  54         int n_sent = 0;
  55 
  56         if (procid_to_pid(&pid) != 0)
  57                 return NT_STATUS_IS_OK(
  58                         messaging_send_buf(msg_ctx, pid, msg_type,
  59                                            (uint8 *)buf, len));
  60 
  61         ret = message_send_all(msg_ctx, msg_type, buf, len, &n_sent);
  62         DEBUG(10,("smbcontrol/send_message: broadcast message to "
  63                   "%d processes\n", n_sent));
  64         
  65         return ret;
  66 }
  67 
  68 static void smbcontrol_timeout(struct tevent_context *event_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
  69                                struct tevent_timer *te,
  70                                struct timeval now,
  71                                void *private_data)
  72 {
  73         bool *timed_out = (bool *)private_data;
  74         TALLOC_FREE(te);
  75         *timed_out = True;
  76 }
  77 
  78 /* Wait for one or more reply messages */
  79 
  80 static void wait_replies(struct messaging_context *msg_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
  81                          bool multiple_replies)
  82 {
  83         struct tevent_timer *te;
  84         bool timed_out = False;
  85 
  86         if (!(te = tevent_add_timer(messaging_event_context(msg_ctx), NULL,
  87                                     timeval_current_ofs(timeout, 0),
  88                                     smbcontrol_timeout, (void *)&timed_out))) {
  89                 DEBUG(0, ("tevent_add_timer failed\n"));
  90                 return;
  91         }
  92 
  93         while (!timed_out) {
  94                 int ret;
  95                 if (num_replies > 0 && !multiple_replies)
  96                         break;
  97                 ret = tevent_loop_once(messaging_event_context(msg_ctx));
  98                 if (ret != 0) {
  99                         break;
 100                 }
 101         }
 102 }
 103 
 104 /* Message handler callback that displays the PID and a string on stdout */
 105 
 106 static void print_pid_string_cb(struct messaging_context *msg,
     /* [<][>][^][v][top][bottom][index][help] */
 107                                 void *private_data, 
 108                                 uint32_t msg_type, 
 109                                 struct server_id pid,
 110                                 DATA_BLOB *data)
 111 {
 112         printf("PID %u: %.*s", (unsigned int)procid_to_pid(&pid),
 113                (int)data->length, (const char *)data->data);
 114         num_replies++;
 115 }
 116 
 117 /* Message handler callback that displays a string on stdout */
 118 
 119 static void print_string_cb(struct messaging_context *msg,
     /* [<][>][^][v][top][bottom][index][help] */
 120                             void *private_data, 
 121                             uint32_t msg_type, 
 122                             struct server_id pid,
 123                             DATA_BLOB *data)
 124 {
 125         printf("%.*s", (int)data->length, (const char *)data->data);
 126         num_replies++;
 127 }
 128 
 129 /* Send no message.  Useful for testing. */
 130 
 131 static bool do_noop(struct messaging_context *msg_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 132                     const struct server_id pid,
 133                     const int argc, const char **argv)
 134 {
 135         if (argc != 1) {
 136                 fprintf(stderr, "Usage: smbcontrol <dest> noop\n");
 137                 return False;
 138         }
 139 
 140         /* Move along, nothing to see here */
 141 
 142         return True;
 143 }
 144 
 145 /* Send a debug string */
 146 
 147 static bool do_debug(struct messaging_context *msg_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 148                      const struct server_id pid,
 149                      const int argc, const char **argv)
 150 {
 151         if (argc != 2) {
 152                 fprintf(stderr, "Usage: smbcontrol <dest> debug "
 153                         "<debug-string>\n");
 154                 return False;
 155         }
 156 
 157         return send_message(msg_ctx, pid, MSG_DEBUG, argv[1],
 158                             strlen(argv[1]) + 1);
 159 }
 160 
 161 #if defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE)
 162 
 163 /* Return the name of a process given it's PID. This will only work on Linux,
 164  * but that's probably moot since this whole stack tracing implementatino is
 165  * Linux-specific anyway.
 166  */
 167 static const char * procname(pid_t pid, char * buf, size_t bufsz)
     /* [<][>][^][v][top][bottom][index][help] */
 168 {
 169         char path[64];
 170         FILE * fp;
 171 
 172         snprintf(path, sizeof(path), "/proc/%llu/cmdline",
 173                 (unsigned long long)pid);
 174         if ((fp = fopen(path, "r")) == NULL) {
 175                 return NULL;
 176         }
 177 
 178         fgets(buf, bufsz, fp);
 179 
 180         fclose(fp);
 181         return buf;
 182 }
 183 
 184 static void print_stack_trace(pid_t pid, int * count)
     /* [<][>][^][v][top][bottom][index][help] */
 185 {
 186         void *              pinfo = NULL;
 187         unw_addr_space_t    aspace = NULL;
 188         unw_cursor_t        cursor;
 189         unw_word_t          ip, sp;
 190 
 191         char                nbuf[256];
 192         unw_word_t          off;
 193 
 194         int ret;
 195 
 196         if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) {
 197                 fprintf(stderr,
 198                         "Failed to attach to process %llu: %s\n",
 199                         (unsigned long long)pid, strerror(errno));
 200                 return;
 201         }
 202 
 203         /* Wait until the attach is complete. */
 204         waitpid(pid, NULL, 0);
 205 
 206         if (((pinfo = _UPT_create(pid)) == NULL) ||
 207             ((aspace = unw_create_addr_space(&_UPT_accessors, 0)) == NULL)) {
 208                 /* Probably out of memory. */
 209                 fprintf(stderr,
 210                         "Unable to initialize stack unwind for process %llu\n",
 211                         (unsigned long long)pid);
 212                 goto cleanup;
 213         }
 214 
 215         if ((ret = unw_init_remote(&cursor, aspace, pinfo))) {
 216                 fprintf(stderr,
 217                         "Unable to unwind stack for process %llu: %s\n",
 218                         (unsigned long long)pid, unw_strerror(ret));
 219                 goto cleanup;
 220         }
 221 
 222         if (*count > 0) {
 223                 printf("\n");
 224         }
 225 
 226         if (procname(pid, nbuf, sizeof(nbuf))) {
 227                 printf("Stack trace for process %llu (%s):\n",
 228                         (unsigned long long)pid, nbuf);
 229         } else {
 230                 printf("Stack trace for process %llu:\n",
 231                         (unsigned long long)pid);
 232         }
 233 
 234         while (unw_step(&cursor) > 0) {
 235                 ip = sp = off = 0;
 236                 unw_get_reg(&cursor, UNW_REG_IP, &ip);
 237                 unw_get_reg(&cursor, UNW_REG_SP, &sp);
 238 
 239                 ret = unw_get_proc_name(&cursor, nbuf, sizeof(nbuf), &off);
 240                 if (ret != 0 && ret != -UNW_ENOMEM) {
 241                         snprintf(nbuf, sizeof(nbuf), "<unknown symbol>");
 242                 }
 243                 printf("    %s + %#llx [ip=%#llx] [sp=%#llx]\n",
 244                         nbuf, (long long)off, (long long)ip,
 245                         (long long)sp);
 246         }
 247 
 248         (*count)++;
 249 
 250 cleanup:
 251         if (aspace) {
 252                 unw_destroy_addr_space(aspace);
 253         }
 254 
 255         if (pinfo) {
 256                 _UPT_destroy(pinfo);
 257         }
 258 
 259         ptrace(PTRACE_DETACH, pid, NULL, NULL);
 260 }
 261 
 262 static int stack_trace_connection(struct db_record *rec,
     /* [<][>][^][v][top][bottom][index][help] */
 263                                   const struct connections_key *key,
 264                                   const struct connections_data *crec,
 265                                   void *priv)
 266 {
 267         print_stack_trace(procid_to_pid(&crec->pid), (int *)priv);
 268 
 269         return 0;
 270 }
 271 
 272 static bool do_daemon_stack_trace(struct messaging_context *msg_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 273                                   const struct server_id pid,
 274                        const int argc, const char **argv)
 275 {
 276         pid_t   dest;
 277         int     count = 0;
 278 
 279         if (argc != 1) {
 280                 fprintf(stderr, "Usage: smbcontrol <dest> stacktrace\n");
 281                 return False;
 282         }
 283 
 284         dest = procid_to_pid(&pid);
 285 
 286         if (dest != 0) {
 287                 /* It would be nice to be able to make sure that this PID is
 288                  * the PID of a smbd/winbind/nmbd process, not some random PID
 289                  * the user liked the look of. It doesn't seem like it's worth
 290                  * the effort at the moment, however.
 291                  */
 292                 print_stack_trace(dest, &count);
 293         } else {
 294                 connections_forall(stack_trace_connection, &count);
 295         }
 296 
 297         return True;
 298 }
 299 
 300 #else /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
 301 
 302 static bool do_daemon_stack_trace(struct messaging_context *msg_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 303                                   const struct server_id pid,
 304                        const int argc, const char **argv)
 305 {
 306         fprintf(stderr,
 307                 "Daemon stack tracing is not supported on this platform\n");
 308         return False;
 309 }
 310 
 311 #endif /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
 312 
 313 /* Inject a fault (fatal signal) into a running smbd */
 314 
 315 static bool do_inject_fault(struct messaging_context *msg_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 316                             const struct server_id pid,
 317                        const int argc, const char **argv)
 318 {
 319         if (argc != 2) {
 320                 fprintf(stderr, "Usage: smbcontrol <dest> inject "
 321                         "<bus|hup|term|internal|segv>\n");
 322                 return False;
 323         }
 324 
 325 #ifndef DEVELOPER
 326         fprintf(stderr, "Fault injection is only available in "
 327                 "developer builds\n");
 328         return False;
 329 #else /* DEVELOPER */
 330         {
 331                 int sig = 0;
 332 
 333                 if (strcmp(argv[1], "bus") == 0) {
 334                         sig = SIGBUS;
 335                 } else if (strcmp(argv[1], "hup") == 0) {
 336                         sig = SIGHUP;
 337                 } else if (strcmp(argv[1], "term") == 0) {
 338                         sig = SIGTERM;
 339                 } else if (strcmp(argv[1], "segv") == 0) {
 340                         sig = SIGSEGV;
 341                 } else if (strcmp(argv[1], "internal") == 0) {
 342                         /* Force an internal error, ie. an unclean exit. */
 343                         sig = -1;
 344                 } else {
 345                         fprintf(stderr, "Unknown signal name '%s'\n", argv[1]);
 346                         return False;
 347                 }
 348 
 349                 return send_message(msg_ctx, pid, MSG_SMB_INJECT_FAULT,
 350                                     &sig, sizeof(int));
 351         }
 352 #endif /* DEVELOPER */
 353 }
 354 
 355 /* Force a browser election */
 356 
 357 static bool do_election(struct messaging_context *msg_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 358                         const struct server_id pid,
 359                         const int argc, const char **argv)
 360 {
 361         if (argc != 1) {
 362                 fprintf(stderr, "Usage: smbcontrol <dest> force-election\n");
 363                 return False;
 364         }
 365 
 366         return send_message(msg_ctx, pid, MSG_FORCE_ELECTION, NULL, 0);
 367 }
 368 
 369 /* Ping a samba daemon process */
 370 
 371 static void pong_cb(struct messaging_context *msg,
     /* [<][>][^][v][top][bottom][index][help] */
 372                     void *private_data, 
 373                     uint32_t msg_type, 
 374                     struct server_id pid,
 375                     DATA_BLOB *data)
 376 {
 377         char *src_string = procid_str(NULL, &pid);
 378         printf("PONG from pid %s\n", src_string);
 379         TALLOC_FREE(src_string);
 380         num_replies++;
 381 }
 382 
 383 static bool do_ping(struct messaging_context *msg_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 384                     const struct server_id pid,
 385                     const int argc, const char **argv)
 386 {
 387         if (argc != 1) {
 388                 fprintf(stderr, "Usage: smbcontrol <dest> ping\n");
 389                 return False;
 390         }
 391 
 392         /* Send a message and register our interest in a reply */
 393 
 394         if (!send_message(msg_ctx, pid, MSG_PING, NULL, 0))
 395                 return False;
 396 
 397         messaging_register(msg_ctx, NULL, MSG_PONG, pong_cb);
 398 
 399         wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
 400 
 401         /* No replies were received within the timeout period */
 402 
 403         if (num_replies == 0)
 404                 printf("No replies received\n");
 405 
 406         messaging_deregister(msg_ctx, MSG_PONG, NULL);
 407 
 408         return num_replies;
 409 }
 410 
 411 /* Set profiling options */
 412 
 413 static bool do_profile(struct messaging_context *msg_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 414                        const struct server_id pid,
 415                        const int argc, const char **argv)
 416 {
 417         int v;
 418 
 419         if (argc != 2) {
 420                 fprintf(stderr, "Usage: smbcontrol <dest> profile "
 421                         "<off|count|on|flush>\n");
 422                 return False;
 423         }
 424 
 425         if (strcmp(argv[1], "off") == 0) {
 426                 v = 0;
 427         } else if (strcmp(argv[1], "count") == 0) {
 428                 v = 1;
 429         } else if (strcmp(argv[1], "on") == 0) {
 430                 v = 2;
 431         } else if (strcmp(argv[1], "flush") == 0) {
 432                 v = 3;
 433         } else {
 434                 fprintf(stderr, "Unknown profile command '%s'\n", argv[1]);
 435                 return False;
 436         }
 437 
 438         return send_message(msg_ctx, pid, MSG_PROFILE, &v, sizeof(int));
 439 }
 440 
 441 /* Return the profiling level */
 442 
 443 static void profilelevel_cb(struct messaging_context *msg_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 444                             void *private_data, 
 445                             uint32_t msg_type, 
 446                             struct server_id pid,
 447                             DATA_BLOB *data)
 448 {
 449         int level;
 450         const char *s;
 451 
 452         num_replies++;
 453 
 454         if (data->length != sizeof(int)) {
 455                 fprintf(stderr, "invalid message length %ld returned\n", 
 456                         (unsigned long)data->length);
 457                 return;
 458         }
 459 
 460         memcpy(&level, data->data, sizeof(int));
 461 
 462         switch (level) {
 463         case 0:
 464                 s = "not enabled";
 465                 break;
 466         case 1:
 467                 s = "off";
 468                 break;
 469         case 3:
 470                 s = "count only";
 471                 break;
 472         case 7:
 473                 s = "count and time";
 474                 break;
 475         default:
 476                 s = "BOGUS";
 477                 break;
 478         }
 479         
 480         printf("Profiling %s on pid %u\n",s,(unsigned int)procid_to_pid(&pid));
 481 }
 482 
 483 static void profilelevel_rqst(struct messaging_context *msg_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 484                               void *private_data, 
 485                               uint32_t msg_type, 
 486                               struct server_id pid,
 487                               DATA_BLOB *data)
 488 {
 489         int v = 0;
 490 
 491         /* Send back a dummy reply */
 492 
 493         send_message(msg_ctx, pid, MSG_PROFILELEVEL, &v, sizeof(int));
 494 }
 495 
 496 static bool do_profilelevel(struct messaging_context *msg_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 497                             const struct server_id pid,
 498                             const int argc, const char **argv)
 499 {
 500         if (argc != 1) {
 501                 fprintf(stderr, "Usage: smbcontrol <dest> profilelevel\n");
 502                 return False;
 503         }
 504 
 505         /* Send a message and register our interest in a reply */
 506 
 507         if (!send_message(msg_ctx, pid, MSG_REQ_PROFILELEVEL, NULL, 0))
 508                 return False;
 509 
 510         messaging_register(msg_ctx, NULL, MSG_PROFILELEVEL, profilelevel_cb);
 511         messaging_register(msg_ctx, NULL, MSG_REQ_PROFILELEVEL,
 512                            profilelevel_rqst);
 513 
 514         wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
 515 
 516         /* No replies were received within the timeout period */
 517 
 518         if (num_replies == 0)
 519                 printf("No replies received\n");
 520 
 521         messaging_deregister(msg_ctx, MSG_PROFILE, NULL);
 522 
 523         return num_replies;
 524 }
 525 
 526 /* Display debug level settings */
 527 
 528 static bool do_debuglevel(struct messaging_context *msg_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 529                           const struct server_id pid,
 530                           const int argc, const char **argv)
 531 {
 532         if (argc != 1) {
 533                 fprintf(stderr, "Usage: smbcontrol <dest> debuglevel\n");
 534                 return False;
 535         }
 536 
 537         /* Send a message and register our interest in a reply */
 538 
 539         if (!send_message(msg_ctx, pid, MSG_REQ_DEBUGLEVEL, NULL, 0))
 540                 return False;
 541 
 542         messaging_register(msg_ctx, NULL, MSG_DEBUGLEVEL, print_pid_string_cb);
 543 
 544         wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
 545 
 546         /* No replies were received within the timeout period */
 547 
 548         if (num_replies == 0)
 549                 printf("No replies received\n");
 550 
 551         messaging_deregister(msg_ctx, MSG_DEBUGLEVEL, NULL);
 552 
 553         return num_replies;
 554 }
 555 
 556 /* Send a print notify message */
 557 
 558 static bool do_printnotify(struct messaging_context *msg_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 559                            const struct server_id pid,
 560                            const int argc, const char **argv)
 561 {
 562         const char *cmd;
 563 
 564         /* Check for subcommand */
 565 
 566         if (argc == 1) {
 567                 fprintf(stderr, "Must specify subcommand:\n");
 568                 fprintf(stderr, "\tqueuepause <printername>\n");
 569                 fprintf(stderr, "\tqueueresume <printername>\n");
 570                 fprintf(stderr, "\tjobpause <printername> <unix jobid>\n");
 571                 fprintf(stderr, "\tjobresume <printername> <unix jobid>\n");
 572                 fprintf(stderr, "\tjobdelete <printername> <unix jobid>\n");
 573                 fprintf(stderr, "\tprinter <printername> <comment|port|"
 574                         "driver> <value>\n");
 575                 
 576                 return False;
 577         }
 578 
 579         cmd = argv[1];
 580 
 581         if (strcmp(cmd, "queuepause") == 0) {
 582 
 583                 if (argc != 3) {
 584                         fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
 585                                 " queuepause <printername>\n");
 586                         return False;
 587                 }
 588                 
 589                 notify_printer_status_byname(argv[2], PRINTER_STATUS_PAUSED);
 590 
 591                 goto send;
 592 
 593         } else if (strcmp(cmd, "queueresume") == 0) {
 594 
 595                 if (argc != 3) {
 596                         fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
 597                                 " queuereume <printername>\n");
 598                         return False;
 599                 }
 600                 
 601                 notify_printer_status_byname(argv[2], PRINTER_STATUS_OK);
 602 
 603                 goto send;
 604 
 605         } else if (strcmp(cmd, "jobpause") == 0) {
 606                 int jobid;
 607 
 608                 if (argc != 4) {
 609                         fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
 610                                 " jobpause <printername> <unix-jobid>\n");
 611                         return False;
 612                 }
 613 
 614                 jobid = atoi(argv[3]);
 615 
 616                 notify_job_status_byname(
 617                         argv[2], jobid, JOB_STATUS_PAUSED, 
 618                         SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
 619 
 620                 goto send;
 621 
 622         } else if (strcmp(cmd, "jobresume") == 0) {
 623                 int jobid;
 624 
 625                 if (argc != 4) {
 626                         fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
 627                                 " jobpause <printername> <unix-jobid>\n");
 628                         return False;
 629                 }
 630 
 631                 jobid = atoi(argv[3]);
 632 
 633                 notify_job_status_byname(
 634                         argv[2], jobid, JOB_STATUS_QUEUED, 
 635                         SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
 636 
 637                 goto send;
 638 
 639         } else if (strcmp(cmd, "jobdelete") == 0) {
 640                 int jobid;
 641 
 642                 if (argc != 4) {
 643                         fprintf(stderr, "Usage: smbcontrol <dest> printnotify"
 644                                 " jobpause <printername> <unix-jobid>\n");
 645                         return False;
 646                 }
 647 
 648                 jobid = atoi(argv[3]);
 649 
 650                 notify_job_status_byname(
 651                         argv[2], jobid, JOB_STATUS_DELETING,
 652                         SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
 653                 
 654                 notify_job_status_byname(
 655                         argv[2], jobid, JOB_STATUS_DELETING|
 656                         JOB_STATUS_DELETED,
 657                         SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
 658 
 659                 goto send;
 660 
 661         } else if (strcmp(cmd, "printer") == 0) {
 662                 uint32 attribute;
 663                 
 664                 if (argc != 5) {
 665                         fprintf(stderr, "Usage: smbcontrol <dest> printnotify "
 666                                 "printer <printername> <comment|port|driver> "
 667                                 "<value>\n");
 668                         return False;
 669                 }
 670 
 671                 if (strcmp(argv[3], "comment") == 0) {
 672                         attribute = PRINTER_NOTIFY_FIELD_COMMENT;
 673                 } else if (strcmp(argv[3], "port") == 0) {
 674                         attribute = PRINTER_NOTIFY_FIELD_PORT_NAME;
 675                 } else if (strcmp(argv[3], "driver") == 0) {
 676                         attribute = PRINTER_NOTIFY_FIELD_DRIVER_NAME;
 677                 } else {
 678                         fprintf(stderr, "Invalid printer command '%s'\n",
 679                                 argv[3]);
 680                         return False;
 681                 }
 682 
 683                 notify_printer_byname(argv[2], attribute,
 684                                       CONST_DISCARD(char *, argv[4]));
 685 
 686                 goto send;
 687         }
 688 
 689         fprintf(stderr, "Invalid subcommand '%s'\n", cmd);
 690         return False;
 691 
 692 send:
 693         print_notify_send_messages(msg_ctx, 0);
 694         return True;
 695 }
 696 
 697 /* Close a share */
 698 
 699 static bool do_closeshare(struct messaging_context *msg_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 700                           const struct server_id pid,
 701                           const int argc, const char **argv)
 702 {
 703         if (argc != 2) {
 704                 fprintf(stderr, "Usage: smbcontrol <dest> close-share "
 705                         "<sharename>\n");
 706                 return False;
 707         }
 708 
 709         return send_message(msg_ctx, pid, MSG_SMB_FORCE_TDIS, argv[1],
 710                             strlen(argv[1]) + 1);
 711 }
 712 
 713 /* force a blocking lock retry */
 714 
 715 static bool do_lockretry(struct messaging_context *msg_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 716                          const struct server_id pid,
 717                          const int argc, const char **argv)
 718 {
 719         if (argc != 1) {
 720                 fprintf(stderr, "Usage: smbcontrol <dest> lockretry\n");
 721                 return False;
 722         }
 723 
 724         return send_message(msg_ctx, pid, MSG_SMB_UNLOCK, NULL, 0);
 725 }
 726 
 727 /* force a validation of all brl entries, including re-sends. */
 728 
 729 static bool do_brl_revalidate(struct messaging_context *msg_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 730                               const struct server_id pid,
 731                               const int argc, const char **argv)
 732 {
 733         if (argc != 1) {
 734                 fprintf(stderr, "Usage: smbcontrol <dest> brl-revalidate\n");
 735                 return False;
 736         }
 737 
 738         return send_message(msg_ctx, pid, MSG_SMB_BRL_VALIDATE, NULL, 0);
 739 }
 740 
 741 /* Force a SAM synchronisation */
 742 
 743 static bool do_samsync(struct messaging_context *msg_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 744                        const struct server_id pid,
 745                        const int argc, const char **argv)
 746 {
 747         if (argc != 1) {
 748                 fprintf(stderr, "Usage: smbcontrol <dest> samsync\n");
 749                 return False;
 750         }
 751 
 752         return send_message(msg_ctx, pid, MSG_SMB_SAM_SYNC, NULL, 0);
 753 }
 754 
 755 /* Force a SAM replication */
 756 
 757 static bool do_samrepl(struct messaging_context *msg_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 758                        const struct server_id pid,
 759                        const int argc, const char **argv)
 760 {
 761         if (argc != 1) {
 762                 fprintf(stderr, "Usage: smbcontrol <dest> samrepl\n");
 763                 return False;
 764         }
 765 
 766         return send_message(msg_ctx, pid, MSG_SMB_SAM_REPL, NULL, 0);
 767 }
 768 
 769 /* Display talloc pool usage */
 770 
 771 static bool do_poolusage(struct messaging_context *msg_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 772                          const struct server_id pid,
 773                          const int argc, const char **argv)
 774 {
 775         if (argc != 1) {
 776                 fprintf(stderr, "Usage: smbcontrol <dest> pool-usage\n");
 777                 return False;
 778         }
 779 
 780         messaging_register(msg_ctx, NULL, MSG_POOL_USAGE, print_string_cb);
 781 
 782         /* Send a message and register our interest in a reply */
 783 
 784         if (!send_message(msg_ctx, pid, MSG_REQ_POOL_USAGE, NULL, 0))
 785                 return False;
 786 
 787         wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
 788 
 789         /* No replies were received within the timeout period */
 790 
 791         if (num_replies == 0)
 792                 printf("No replies received\n");
 793 
 794         messaging_deregister(msg_ctx, MSG_POOL_USAGE, NULL);
 795 
 796         return num_replies;
 797 }
 798 
 799 /* Perform a dmalloc mark */
 800 
 801 static bool do_dmalloc_mark(struct messaging_context *msg_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 802                             const struct server_id pid,
 803                             const int argc, const char **argv)
 804 {
 805         if (argc != 1) {
 806                 fprintf(stderr, "Usage: smbcontrol <dest> dmalloc-mark\n");
 807                 return False;
 808         }
 809 
 810         return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_MARK, NULL, 0);
 811 }
 812 
 813 /* Perform a dmalloc changed */
 814 
 815 static bool do_dmalloc_changed(struct messaging_context *msg_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 816                                const struct server_id pid,
 817                                const int argc, const char **argv)
 818 {
 819         if (argc != 1) {
 820                 fprintf(stderr, "Usage: smbcontrol <dest> "
 821                         "dmalloc-log-changed\n");
 822                 return False;
 823         }
 824 
 825         return send_message(msg_ctx, pid, MSG_REQ_DMALLOC_LOG_CHANGED,
 826                             NULL, 0);
 827 }
 828 
 829 /* Shutdown a server process */
 830 
 831 static bool do_shutdown(struct messaging_context *msg_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 832                         const struct server_id pid,
 833                         const int argc, const char **argv)
 834 {
 835         if (argc != 1) {
 836                 fprintf(stderr, "Usage: smbcontrol <dest> shutdown\n");
 837                 return False;
 838         }
 839 
 840         return send_message(msg_ctx, pid, MSG_SHUTDOWN, NULL, 0);
 841 }
 842 
 843 /* Notify a driver upgrade */
 844 
 845 static bool do_drvupgrade(struct messaging_context *msg_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 846                           const struct server_id pid,
 847                           const int argc, const char **argv)
 848 {
 849         if (argc != 2) {
 850                 fprintf(stderr, "Usage: smbcontrol <dest> drvupgrade "
 851                         "<driver-name>\n");
 852                 return False;
 853         }
 854 
 855         return send_message(msg_ctx, pid, MSG_DEBUG, argv[1],
 856                             strlen(argv[1]) + 1);
 857 }
 858 
 859 static bool do_winbind_online(struct messaging_context *msg_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 860                               const struct server_id pid,
 861                              const int argc, const char **argv)
 862 {
 863         TDB_CONTEXT *tdb;
 864 
 865         if (argc != 1) {
 866                 fprintf(stderr, "Usage: smbcontrol winbindd online\n");
 867                 return False;
 868         }
 869 
 870         /* Remove the entry in the winbindd_cache tdb to tell a later
 871            starting winbindd that we're online. */
 872 
 873         tdb = tdb_open_log(cache_path("winbindd_cache.tdb"), 0, TDB_DEFAULT, O_RDWR, 0600);
 874         if (!tdb) {
 875                 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
 876                         cache_path("winbindd_cache.tdb"));
 877                 return False;
 878         }
 879 
 880         tdb_delete_bystring(tdb, "WINBINDD_OFFLINE");
 881         tdb_close(tdb);
 882 
 883         return send_message(msg_ctx, pid, MSG_WINBIND_ONLINE, NULL, 0);
 884 }
 885 
 886 static bool do_winbind_offline(struct messaging_context *msg_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 887                                const struct server_id pid,
 888                              const int argc, const char **argv)
 889 {
 890         TDB_CONTEXT *tdb;
 891         bool ret = False;
 892         int retry = 0;
 893 
 894         if (argc != 1) {
 895                 fprintf(stderr, "Usage: smbcontrol winbindd offline\n");
 896                 return False;
 897         }
 898 
 899         /* Create an entry in the winbindd_cache tdb to tell a later
 900            starting winbindd that we're offline. We may actually create
 901            it here... */
 902 
 903         tdb = tdb_open_log(cache_path("winbindd_cache.tdb"),
 904                                 WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
 905                                 TDB_DEFAULT /* TDB_CLEAR_IF_FIRST */, O_RDWR|O_CREAT, 0600);
 906 
 907         if (!tdb) {
 908                 fprintf(stderr, "Cannot open the tdb %s for writing.\n",
 909                         cache_path("winbindd_cache.tdb"));
 910                 return False;
 911         }
 912 
 913         /* There's a potential race condition that if a child
 914            winbindd detects a domain is online at the same time
 915            we're trying to tell it to go offline that it might 
 916            delete the record we add between us adding it and
 917            sending the message. Minimize this by retrying up to
 918            5 times. */
 919 
 920         for (retry = 0; retry < 5; retry++) {
 921                 TDB_DATA d;
 922                 uint8 buf[4];
 923 
 924                 ZERO_STRUCT(d);
 925 
 926                 SIVAL(buf, 0, time(NULL));
 927                 d.dptr = buf;
 928                 d.dsize = 4;
 929 
 930                 tdb_store_bystring(tdb, "WINBINDD_OFFLINE", d, TDB_INSERT);
 931 
 932                 ret = send_message(msg_ctx, pid, MSG_WINBIND_OFFLINE,
 933                                    NULL, 0);
 934 
 935                 /* Check that the entry "WINBINDD_OFFLINE" still exists. */
 936                 d = tdb_fetch_bystring( tdb, "WINBINDD_OFFLINE" );
 937         
 938                 if (!d.dptr || d.dsize != 4) {
 939                         SAFE_FREE(d.dptr);
 940                         DEBUG(10,("do_winbind_offline: offline state not set - retrying.\n"));
 941                 } else {
 942                         SAFE_FREE(d.dptr);
 943                         break;
 944                 }
 945         }
 946 
 947         tdb_close(tdb);
 948         return ret;
 949 }
 950 
 951 static bool do_winbind_onlinestatus(struct messaging_context *msg_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 952                                     const struct server_id pid,
 953                                     const int argc, const char **argv)
 954 {
 955         struct server_id myid;
 956 
 957         myid = pid_to_procid(sys_getpid());
 958 
 959         if (argc != 1) {
 960                 fprintf(stderr, "Usage: smbcontrol winbindd onlinestatus\n");
 961                 return False;
 962         }
 963 
 964         messaging_register(msg_ctx, NULL, MSG_WINBIND_ONLINESTATUS,
 965                            print_pid_string_cb);
 966 
 967         if (!send_message(msg_ctx, pid, MSG_WINBIND_ONLINESTATUS, &myid,
 968                           sizeof(myid)))
 969                 return False;
 970 
 971         wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
 972 
 973         /* No replies were received within the timeout period */
 974 
 975         if (num_replies == 0)
 976                 printf("No replies received\n");
 977 
 978         messaging_deregister(msg_ctx, MSG_WINBIND_ONLINESTATUS, NULL);
 979 
 980         return num_replies;
 981 }
 982 
 983 static bool do_dump_event_list(struct messaging_context *msg_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 984                                const struct server_id pid,
 985                                const int argc, const char **argv)
 986 {
 987         struct server_id myid;
 988 
 989         myid = pid_to_procid(sys_getpid());
 990 
 991         if (argc != 1) {
 992                 fprintf(stderr, "Usage: smbcontrol <dest> dump-event-list\n");
 993                 return False;
 994         }
 995 
 996         return send_message(msg_ctx, pid, MSG_DUMP_EVENT_LIST, NULL, 0);
 997 }
 998 
 999 static bool do_winbind_dump_domain_list(struct messaging_context *msg_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
1000                                         const struct server_id pid,
1001                                         const int argc, const char **argv)
1002 {
1003         const char *domain = NULL;
1004         int domain_len = 0;
1005         struct server_id myid;
1006         uint8_t *buf = NULL;
1007         int buf_len = 0;
1008 
1009         myid = pid_to_procid(sys_getpid());
1010 
1011         if (argc < 1 || argc > 2) {
1012                 fprintf(stderr, "Usage: smbcontrol <dest> dump_domain_list "
1013                         "<domain>\n");
1014                 return false;
1015         }
1016 
1017         if (argc == 2) {
1018                 domain = argv[1];
1019                 domain_len = strlen(argv[1]) + 1;
1020         }
1021 
1022         messaging_register(msg_ctx, NULL, MSG_WINBIND_DUMP_DOMAIN_LIST,
1023                            print_pid_string_cb);
1024 
1025         buf_len = sizeof(myid)+domain_len;
1026         buf = SMB_MALLOC_ARRAY(uint8_t, buf_len);
1027         if (!buf) {
1028                 return false;
1029         }
1030 
1031         memcpy(buf, &myid, sizeof(myid));
1032         memcpy(&buf[sizeof(myid)], domain, domain_len);
1033 
1034         if (!send_message(msg_ctx, pid, MSG_WINBIND_DUMP_DOMAIN_LIST,
1035                           buf, buf_len))
1036         {
1037                 SAFE_FREE(buf);
1038                 return false;
1039         }
1040 
1041         wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
1042 
1043         /* No replies were received within the timeout period */
1044 
1045         SAFE_FREE(buf);
1046         if (num_replies == 0) {
1047                 printf("No replies received\n");
1048         }
1049 
1050         messaging_deregister(msg_ctx, MSG_WINBIND_DUMP_DOMAIN_LIST, NULL);
1051 
1052         return num_replies;
1053 }
1054 
1055 static void winbind_validate_cache_cb(struct messaging_context *msg,
     /* [<][>][^][v][top][bottom][index][help] */
1056                                       void *private_data,
1057                                       uint32_t msg_type,
1058                                       struct server_id pid,
1059                                       DATA_BLOB *data)
1060 {
1061         char *src_string = procid_str(NULL, &pid);
1062         printf("Winbindd cache is %svalid. (answer from pid %s)\n",
1063                (*(data->data) == 0 ? "" : "NOT "), src_string);
1064         TALLOC_FREE(src_string);
1065         num_replies++;
1066 }
1067 
1068 static bool do_winbind_validate_cache(struct messaging_context *msg_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
1069                                       const struct server_id pid,
1070                                       const int argc, const char **argv)
1071 {
1072         struct server_id myid = pid_to_procid(sys_getpid());
1073 
1074         if (argc != 1) {
1075                 fprintf(stderr, "Usage: smbcontrol winbindd validate-cache\n");
1076                 return False;
1077         }
1078 
1079         messaging_register(msg_ctx, NULL, MSG_WINBIND_VALIDATE_CACHE,
1080                            winbind_validate_cache_cb);
1081 
1082         if (!send_message(msg_ctx, pid, MSG_WINBIND_VALIDATE_CACHE, &myid,
1083                           sizeof(myid))) {
1084                 return False;
1085         }
1086 
1087         wait_replies(msg_ctx, procid_to_pid(&pid) == 0);
1088 
1089         if (num_replies == 0) {
1090                 printf("No replies received\n");
1091         }
1092 
1093         messaging_deregister(msg_ctx, MSG_WINBIND_VALIDATE_CACHE, NULL);
1094 
1095         return num_replies;
1096 }
1097 
1098 static bool do_reload_config(struct messaging_context *msg_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
1099                              const struct server_id pid,
1100                              const int argc, const char **argv)
1101 {
1102         if (argc != 1) {
1103                 fprintf(stderr, "Usage: smbcontrol <dest> reload-config\n");
1104                 return False;
1105         }
1106 
1107         return send_message(msg_ctx, pid, MSG_SMB_CONF_UPDATED, NULL, 0);
1108 }
1109 
1110 static void my_make_nmb_name( struct nmb_name *n, const char *name, int type)
     /* [<][>][^][v][top][bottom][index][help] */
1111 {
1112         fstring unix_name;
1113         memset( (char *)n, '\0', sizeof(struct nmb_name) );
1114         fstrcpy(unix_name, name);
1115         strupper_m(unix_name);
1116         push_ascii(n->name, unix_name, sizeof(n->name), STR_TERMINATE);
1117         n->name_type = (unsigned int)type & 0xFF;
1118         push_ascii(n->scope,  global_scope(), 64, STR_TERMINATE);
1119 }
1120 
1121 static bool do_nodestatus(struct messaging_context *msg_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
1122                           const struct server_id pid,
1123                           const int argc, const char **argv)
1124 {
1125         struct packet_struct p;
1126 
1127         if (argc != 2) {
1128                 fprintf(stderr, "Usage: smbcontrol nmbd nodestatus <ip>\n");
1129                 return False;
1130         }
1131 
1132         ZERO_STRUCT(p);
1133 
1134         p.ip = interpret_addr2(argv[1]);
1135         p.port = 137;
1136         p.packet_type = NMB_PACKET;
1137 
1138         p.packet.nmb.header.name_trn_id = 10;
1139         p.packet.nmb.header.opcode = 0;
1140         p.packet.nmb.header.response = False;
1141         p.packet.nmb.header.nm_flags.bcast = False;
1142         p.packet.nmb.header.nm_flags.recursion_available = False;
1143         p.packet.nmb.header.nm_flags.recursion_desired = False;
1144         p.packet.nmb.header.nm_flags.trunc = False;
1145         p.packet.nmb.header.nm_flags.authoritative = False;
1146         p.packet.nmb.header.rcode = 0;
1147         p.packet.nmb.header.qdcount = 1;
1148         p.packet.nmb.header.ancount = 0;
1149         p.packet.nmb.header.nscount = 0;
1150         p.packet.nmb.header.arcount = 0;
1151         my_make_nmb_name(&p.packet.nmb.question.question_name, "*", 0x00);
1152         p.packet.nmb.question.question_type = 0x21;
1153         p.packet.nmb.question.question_class = 0x1;
1154 
1155         return send_message(msg_ctx, pid, MSG_SEND_PACKET, &p, sizeof(p));
1156 }
1157 
1158 /* A list of message type supported */
1159 
1160 static const struct {
1161         const char *name;       /* Option name */
1162         bool (*fn)(struct messaging_context *msg_ctx,
1163                    const struct server_id pid,
1164                    const int argc, const char **argv);
1165         const char *help;       /* Short help text */
1166 } msg_types[] = {
1167         { "debug", do_debug, "Set debuglevel"  },
1168         { "force-election", do_election,
1169           "Force a browse election" },
1170         { "ping", do_ping, "Elicit a response" },
1171         { "profile", do_profile, "" },
1172         { "inject", do_inject_fault,
1173             "Inject a fatal signal into a running smbd"},
1174         { "stacktrace", do_daemon_stack_trace,
1175             "Display a stack trace of a daemon" },
1176         { "profilelevel", do_profilelevel, "" },
1177         { "debuglevel", do_debuglevel, "Display current debuglevels" },
1178         { "printnotify", do_printnotify, "Send a print notify message" },
1179         { "close-share", do_closeshare, "Forcibly disconnect a share" },
1180         { "lockretry", do_lockretry, "Force a blocking lock retry" },
1181         { "brl-revalidate", do_brl_revalidate, "Revalidate all brl entries" },
1182         { "samsync", do_samsync, "Initiate SAM synchronisation" },
1183         { "samrepl", do_samrepl, "Initiate SAM replication" },
1184         { "pool-usage", do_poolusage, "Display talloc memory usage" },
1185         { "dmalloc-mark", do_dmalloc_mark, "" },
1186         { "dmalloc-log-changed", do_dmalloc_changed, "" },
1187         { "shutdown", do_shutdown, "Shut down daemon" },
1188         { "drvupgrade", do_drvupgrade, "Notify a printer driver has changed" },
1189         { "reload-config", do_reload_config, "Force smbd or winbindd to reload config file"},
1190         { "nodestatus", do_nodestatus, "Ask nmbd to do a node status request"},
1191         { "online", do_winbind_online, "Ask winbind to go into online state"},
1192         { "offline", do_winbind_offline, "Ask winbind to go into offline state"},
1193         { "onlinestatus", do_winbind_onlinestatus, "Request winbind online status"},
1194         { "dump-event-list", do_dump_event_list, "Dump event list"},
1195         { "validate-cache" , do_winbind_validate_cache,
1196           "Validate winbind's credential cache" },
1197         { "dump-domain-list", do_winbind_dump_domain_list, "Dump winbind domain list"},
1198         { "noop", do_noop, "Do nothing" },
1199         { NULL }
1200 };
1201 
1202 /* Display usage information */
1203 
1204 static void usage(poptContext pc)
     /* [<][>][^][v][top][bottom][index][help] */
1205 {
1206         int i;
1207 
1208         poptPrintHelp(pc, stderr, 0);
1209 
1210         fprintf(stderr, "\n");
1211         fprintf(stderr, "<destination> is one of \"nmbd\", \"smbd\", \"winbindd\" or a "
1212                 "process ID\n");
1213 
1214         fprintf(stderr, "\n");
1215         fprintf(stderr, "<message-type> is one of:\n");
1216 
1217         for (i = 0; msg_types[i].name; i++) 
1218             fprintf(stderr, "\t%-30s%s\n", msg_types[i].name, 
1219                     msg_types[i].help);
1220 
1221         fprintf(stderr, "\n");
1222 
1223         exit(1);
1224 }
1225 
1226 /* Return the pid number for a string destination */
1227 
1228 static struct server_id parse_dest(const char *dest)
     /* [<][>][^][v][top][bottom][index][help] */
1229 {
1230         struct server_id result = {-1};
1231         pid_t pid;
1232 
1233         /* Zero is a special return value for broadcast to all processes */
1234 
1235         if (strequal(dest, "all")) {
1236                 return interpret_pid(MSG_BROADCAST_PID_STR);
1237         }
1238 
1239         /* Try self - useful for testing */
1240 
1241         if (strequal(dest, "self")) {
1242                 return pid_to_procid(sys_getpid());
1243         }
1244 
1245         /* Fix winbind typo. */
1246         if (strequal(dest, "winbind")) {
1247                 dest = "winbindd";
1248         }
1249 
1250         /* Check for numeric pid number */
1251         result = interpret_pid(dest);
1252 
1253         /* Zero isn't valid if not "all". */
1254         if (result.pid && procid_valid(&result)) {
1255                 return result;
1256         }
1257 
1258         /* Look up other destinations in pidfile directory */
1259 
1260         if ((pid = pidfile_pid(dest)) != 0) {
1261                 return pid_to_procid(pid);
1262         }
1263 
1264         fprintf(stderr,"Can't find pid for destination '%s'\n", dest);
1265 
1266         return result;
1267 }
1268 
1269 /* Execute smbcontrol command */
1270 
1271 static bool do_command(struct messaging_context *msg_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
1272                        int argc, const char **argv)
1273 {
1274         const char *dest = argv[0], *command = argv[1];
1275         struct server_id pid;
1276         int i;
1277 
1278         /* Check destination */
1279 
1280         pid = parse_dest(dest);
1281         if (!procid_valid(&pid)) {
1282                 return False;
1283         }
1284 
1285         /* Check command */
1286 
1287         for (i = 0; msg_types[i].name; i++) {
1288                 if (strequal(command, msg_types[i].name))
1289                         return msg_types[i].fn(msg_ctx, pid,
1290                                                argc - 1, argv + 1);
1291         }
1292 
1293         fprintf(stderr, "smbcontrol: unknown command '%s'\n", command);
1294 
1295         return False;
1296 }
1297 
1298 static void smbcontrol_help(poptContext pc,
     /* [<][>][^][v][top][bottom][index][help] */
1299                     enum poptCallbackReason preason,
1300                     struct poptOption * poption,
1301                     const char * parg,
1302                     void * pdata)
1303 {
1304         if (poption->shortName != '?') {
1305                 poptPrintUsage(pc, stdout, 0);
1306         } else {
1307                 usage(pc);
1308         }
1309 
1310         exit(0);
1311 }
1312 
1313 struct poptOption help_options[] = {
1314         { NULL, '\0', POPT_ARG_CALLBACK, (void *)&smbcontrol_help, '\0',
1315           NULL, NULL },
1316         { "help", '?', 0, NULL, '?', "Show this help message", NULL },
1317         { "usage", '\0', 0, NULL, 'u', "Display brief usage message", NULL },
1318         { NULL }
1319 } ;
1320 
1321 /* Main program */
1322 
1323 int main(int argc, const char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
1324 {
1325         poptContext pc;
1326         int opt;
1327         struct tevent_context *evt_ctx;
1328         struct messaging_context *msg_ctx;
1329 
1330         static struct poptOption long_options[] = {
1331                 /* POPT_AUTOHELP */
1332                 { NULL, '\0', POPT_ARG_INCLUDE_TABLE, help_options,
1333                                         0, "Help options:", NULL },
1334                 { "timeout", 't', POPT_ARG_INT, &timeout, 't', 
1335                   "Set timeout value in seconds", "TIMEOUT" },
1336 
1337                 POPT_COMMON_SAMBA
1338                 POPT_TABLEEND
1339         };
1340         TALLOC_CTX *frame = talloc_stackframe();
1341         int ret = 0;
1342 
1343         load_case_tables();
1344 
1345         setup_logging(argv[0],True);
1346         
1347         /* Parse command line arguments using popt */
1348 
1349         pc = poptGetContext(
1350                 "smbcontrol", argc, (const char **)argv, long_options, 0);
1351 
1352         poptSetOtherOptionHelp(pc, "[OPTION...] <destination> <message-type> "
1353                                "<parameters>");
1354 
1355         if (argc == 1)
1356                 usage(pc);
1357 
1358         while ((opt = poptGetNextOpt(pc)) != -1) {
1359                 switch(opt) {
1360                 case 't':       /* --timeout */
1361                         break;
1362                 default:
1363                         fprintf(stderr, "Invalid option\n");
1364                         poptPrintHelp(pc, stderr, 0);
1365                         break;
1366                 }
1367         }
1368 
1369         /* We should now have the remaining command line arguments in
1370            argv.  The argc parameter should have been decremented to the
1371            correct value in the above switch statement. */
1372 
1373         argv = (const char **)poptGetArgs(pc);
1374         argc = 0;
1375         if (argv != NULL) {
1376                 while (argv[argc] != NULL) {
1377                         argc++;
1378                 }
1379         }
1380 
1381         if (argc <= 1)
1382                 usage(pc);
1383 
1384         lp_load(get_dyn_CONFIGFILE(),False,False,False,True);
1385 
1386         /* Need to invert sense of return code -- samba
1387          * routines mostly return True==1 for success, but
1388          * shell needs 0. */ 
1389         
1390         if (!(evt_ctx = tevent_context_init(NULL)) ||
1391             !(msg_ctx = messaging_init(NULL, server_id_self(), evt_ctx))) {
1392                 fprintf(stderr, "could not init messaging context\n");
1393                 TALLOC_FREE(frame);
1394                 exit(1);
1395         }
1396         
1397         ret = !do_command(msg_ctx, argc, argv);
1398         TALLOC_FREE(frame);
1399         return ret;
1400 }

/* [<][>][^][v][top][bottom][index][help] */