Add two more memory-debug smbcontrol messages: these ones should
[ira/wip.git] / source3 / utils / smbcontrol.c
index 27a3b611701186c21ac87b02a9d26781113d0552..318e1657cc1e8367b26792bbf2913caa088f6fda 100644 (file)
@@ -3,6 +3,7 @@
    Version 3.0
    program to send control messages to Samba processes
    Copyright (C) Andrew Tridgell 1994-1998
+   Copyright (C) 2001, 2002 by Martin Pool
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -21,6 +22,8 @@
 
 #include "includes.h"
 
+extern BOOL AllowDebugChange;
+
 static struct {
        char *name;
        int value;
@@ -33,6 +36,11 @@ static struct {
        {"debuglevel", MSG_REQ_DEBUGLEVEL},
        {"printer-notify", MSG_PRINTER_NOTIFY},
        {"close-share", MSG_SMB_FORCE_TDIS},
+        {"samsync", MSG_SMB_SAM_SYNC},
+        {"samrepl", MSG_SMB_SAM_REPL},
+       {"pool-usage", MSG_REQ_POOL_USAGE },
+       {"dmalloc-mark", MSG_REQ_DMALLOC_MARK },
+       {"dmalloc-log-changed", MSG_REQ_DMALLOC_LOG_CHANGED },
        {NULL, -1}
 };
 
@@ -44,7 +52,7 @@ static void usage(BOOL doexit)
 {
        int i;
        if (doexit) {
-               printf("Usage: smbcontrol -i\n");
+               printf("Usage: smbcontrol -i -s configfile\n");
                printf("       smbcontrol <destination> <message-type> <parameters>\n\n");
        } else {
                printf("<destination> <message-type> <parameters>\n\n");
@@ -64,6 +72,25 @@ static BOOL debuglevel_registered = False;
 static BOOL profilelevel_registered = False;
 
 
+/**
+ * Wait for replies for up to @p *max_secs seconds, or until @p
+ * max_replies are received.  max_replies may be NULL in which case it
+ * is ignored.
+ *
+ * @note This is a pretty lame timeout; all it means is that after
+ * max_secs we won't look for any more messages.
+ **/
+static void wait_for_replies(int max_secs, int *max_replies)
+{
+       time_t timeout_end = time(NULL) + max_secs;
+
+       while ((!max_replies || (*max_replies)-- > 0)
+              &&  (time(NULL) < timeout_end)) {
+               message_dispatch();
+       }
+}
+
+
 /****************************************************************************
 a useful function for testing the message system
 ****************************************************************************/
@@ -120,9 +147,21 @@ void profilelevel_function(int msg_type, pid_t src, void *buf, size_t len)
        got_level = True;
 }
 
-/****************************************************************************
-send a message to a named destination
-****************************************************************************/
+/**
+ * Handle reply from POOL_USAGE.
+ **/
+static void pool_usage_cb(int msg_type, pid_t src_pid, void *buf, size_t len)
+{
+       printf("Got POOL_USAGE reply from pid%u:\n%.*s",
+              (unsigned int) src_pid, (int) len, (const char *) buf);
+}
+
+
+/**
+ * Send a message to a named destination
+ *
+ * @return False if an error occurred.
+ **/
 static BOOL send_message(char *dest, int msg_type, void *buf, int len, BOOL duplicates)
 {
        pid_t pid;
@@ -130,14 +169,18 @@ static BOOL send_message(char *dest, int msg_type, void *buf, int len, BOOL dupl
        if (strequal(dest,"smbd")) {
                TDB_CONTEXT *tdb;
                BOOL ret;
+               int n_sent = 0;
 
-               tdb = tdb_open_log(lock_path("connections.tdb"), 0, 0, O_RDONLY, 0);
+               tdb = tdb_open_log(lock_path("connections.tdb"), 0, TDB_DEFAULT, O_RDWR, 0);
                if (!tdb) {
                        fprintf(stderr,"Failed to open connections database in send_message.\n");
                        return False;
                }
 
-               ret = message_send_all(tdb,msg_type, buf, len, duplicates);
+               ret = message_send_all(tdb,msg_type, buf, len, duplicates,
+                                      &n_sent);
+               DEBUG(10,("smbcontrol/send_message: broadcast message to "
+                         "%d processes\n", n_sent));
                tdb_close(tdb);
 
                return ret;
@@ -157,6 +200,7 @@ static BOOL send_message(char *dest, int msg_type, void *buf, int len, BOOL dupl
                }               
        } 
 
+       DEBUG(10,("smbcontrol/send_message: send message to pid%d\n", pid));
        return message_send_pid(pid, msg_type, buf, len, duplicates);
 }
 
@@ -173,10 +217,16 @@ static int parse_type(char *mtype)
 }
 
 
+static void register_all(void)
+{
+       message_register(MSG_POOL_USAGE, pool_usage_cb);
+}
+
+
 /****************************************************************************
 do command
 ****************************************************************************/
-static BOOL do_command(char *dest, char *msg_name, char **params)
+static BOOL do_command(char *dest, char *msg_name, int iparams, char **params)
 {
        int i, n, v;
        int mtype;
@@ -299,6 +349,42 @@ static BOOL do_command(char *dest, char *msg_name, char **params)
                                      strlen(params[0]) + 1, False);
                break;
 
+        case MSG_SMB_SAM_SYNC:
+                if (!strequal(dest, "smbd")) {
+                        fprintf(stderr, "samsync can only be sent to smbd\n");
+                        return False;
+                }
+
+                if (params) {
+                        fprintf(stderr, "samsync does not take any parameters\n");
+                        return False;
+                }
+
+                retval = send_message(dest, MSG_SMB_SAM_SYNC, NULL, 0, False);
+
+                break;
+
+        case MSG_SMB_SAM_REPL: {
+                uint32 seqnum;
+
+                if (!strequal(dest, "smbd")) {
+                        fprintf(stderr, "sam repl can only be sent to smbd\n");
+                        return False;
+                }
+
+                if (!params || !params[0]) {
+                        fprintf(stderr, "SAM_REPL needs a parameter\n");
+                        return False;
+                }
+
+                seqnum = atoi(params[0]);
+
+                retval = send_message(dest, MSG_SMB_SAM_SYNC, 
+                                      (char *)&seqnum, sizeof(uint32), False); 
+
+                break;
+        }
+
        case MSG_PING:
                if (!pong_registered) {
                    message_register(MSG_PONG, pong_function);
@@ -311,23 +397,33 @@ static BOOL do_command(char *dest, char *msg_name, char **params)
                n = atoi(params[0]);
                pong_count = 0;
                for (i=0;i<n;i++) {
-                       retval = send_message(dest, MSG_PING, NULL, 0, True);
-                       if (retval == False) break;
+                       if (iparams > 1)
+                               retval = send_message(dest, MSG_PING, params[1], strlen(params[1]) + 1, True);
+                       else
+                               retval = send_message(dest, MSG_PING, NULL, 0, True);
+                       if (retval == False)
+                               return False;
                }
-               if (retval) {
-                       timeout_start = time(NULL);
-                       while (pong_count < n) {
-                               message_dispatch();
-                               if ((time(NULL) - timeout_start) > MAX_WAIT) {
-                                       fprintf(stderr,"PING timeout\n");
-                                       break;
-                               }
-                       }
+               wait_for_replies(MAX_WAIT, &n);
+               if (n > 0) {
+                       fprintf(stderr,"PING timeout\n");
                }
                break;
 
+       case MSG_REQ_POOL_USAGE:
+               if (!send_message(dest, MSG_REQ_POOL_USAGE, NULL, 0, True))
+                       return False;
+               wait_for_replies(MAX_WAIT, NULL);
+               
+               break;
+
+       case MSG_REQ_DMALLOC_LOG_CHANGED:
+       case MSG_REQ_DMALLOC_MARK:
+               if (!send_message(dest, mtype, NULL, 0, False))
+                       return False;
+               break;
        }
-       
+
        return (True);
 }
 
@@ -336,46 +432,54 @@ static BOOL do_command(char *dest, char *msg_name, char **params)
        int opt;
        char temp[255];
        extern int optind;
-       pstring servicesf = CONFIGFILE;
        BOOL interactive = False;
 
-       TimeInit();
+       AllowDebugChange = False;
+       DEBUGLEVEL = 0;
+
        setup_logging(argv[0],True);
        
-       charset_initialise();
-       lp_load(servicesf,False,False,False);
-
-       if (!message_init()) exit(1);
-
        if (argc < 2) usage(True);
 
-       while ((opt = getopt(argc, argv,"i")) != EOF) {
+       while ((opt = getopt(argc, argv,"is:")) != EOF) {
                switch (opt) {
                case 'i':
                        interactive = True;
                        break;
+               case 's':
+                       pstrcpy(dyn_CONFIGFILE, optarg);
+                       break;
                default:
                        printf("Unknown option %c (%d)\n", (char)opt, opt);
                        usage(True);
                }
        }
 
+       lp_load(dyn_CONFIGFILE,False,False,False);
+
+       if (!message_init()) exit(1);
+
        argc -= optind;
        argv = &argv[optind];
 
+       register_all();
+
        if (!interactive) {
                if (argc < 2) usage(True);
-               return (do_command(argv[0],argv[1],argc > 2 ? &argv[2] : 0));
+               /* Need to invert sense of return code -- samba
+                * routines mostly return True==1 for success, but
+                * shell needs 0. */ 
+               return ! do_command(argv[0],argv[1], argc-2, argc > 2 ? &argv[2] : 0);
        }
 
        while (True) {
-               char *myargv[3];
+               char *myargv[4];
                int myargc;
 
                printf("smbcontrol> ");
                if (!fgets(temp, sizeof(temp)-1, stdin)) break;
                myargc = 0;
-               while ((myargc < 3) && 
+               while ((myargc < 4) && 
                       (myargv[myargc] = strtok(myargc?NULL:temp," \t\n"))) {
                        myargc++;
                }
@@ -383,7 +487,7 @@ static BOOL do_command(char *dest, char *msg_name, char **params)
                if (strequal(myargv[0],"q")) break;
                if (myargc < 2)
                        usage(False);
-               else if (!do_command(myargv[0],myargv[1],myargc > 2 ? &myargv[2] : 0))
+               else if (!do_command(myargv[0],myargv[1],myargc-2,myargc > 2 ? &myargv[2] : 0))
                        usage(False);
        }
        return(0);