summaryrefslogtreecommitdiff
path: root/source3/lib
diff options
context:
space:
mode:
Diffstat (limited to 'source3/lib')
-rw-r--r--source3/lib/debug.c61
-rw-r--r--source3/lib/messages.c237
2 files changed, 254 insertions, 44 deletions
diff --git a/source3/lib/debug.c b/source3/lib/debug.c
index bfb638a38a..5279dda2e3 100644
--- a/source3/lib/debug.c
+++ b/source3/lib/debug.c
@@ -119,51 +119,24 @@ static size_t format_pos = 0;
* Functions...
*/
-#if defined(SIGUSR2)
-/* ************************************************************************** **
- * catch a sigusr2 - decrease the debug log level.
- * ************************************************************************** **
- */
-void sig_usr2( int sig )
- {
- DEBUGLEVEL--;
- if( DEBUGLEVEL < 0 )
- DEBUGLEVEL = 0;
-
- DEBUG( 0, ( "Got SIGUSR2; set debug level to %d.\n", DEBUGLEVEL ) );
-
- sys_select_signal();
-
-#if !defined(HAVE_SIGACTION)
- CatchSignal( SIGUSR2, SIGNAL_CAST sig_usr2 );
-#endif
-
- } /* sig_usr2 */
-#endif /* SIGUSR2 */
-
-#if defined(SIGUSR1)
-/* ************************************************************************** **
- * catch a sigusr1 - increase the debug log level.
- * ************************************************************************** **
- */
-void sig_usr1( int sig )
- {
-
- DEBUGLEVEL++;
-
- if( DEBUGLEVEL > 10 )
- DEBUGLEVEL = 10;
-
- DEBUG( 0, ( "Got SIGUSR1; set debug level to %d.\n", DEBUGLEVEL ) );
-
- sys_select_signal();
-
-#if !defined(HAVE_SIGACTION)
- CatchSignal( SIGUSR1, SIGNAL_CAST sig_usr1 );
-#endif
+/****************************************************************************
+receive a "set debug level" message
+****************************************************************************/
+void debug_message(pid_t src, void *buf, int len)
+{
+ int level;
+ memcpy(&level, buf, sizeof(int));
+ DEBUGLEVEL = level;
+ DEBUG(1,("Debug level set to %d from pid %d\n", level, (int)src));
+}
- } /* sig_usr1 */
-#endif /* SIGUSR1 */
+/****************************************************************************
+send a "set debug level" message
+****************************************************************************/
+void debug_message_send(pid_t pid, int level)
+{
+ message_send_pid(pid, MSG_DEBUG, &level, sizeof(int));
+}
/* ************************************************************************** **
diff --git a/source3/lib/messages.c b/source3/lib/messages.c
new file mode 100644
index 0000000000..30eef40ec9
--- /dev/null
+++ b/source3/lib/messages.c
@@ -0,0 +1,237 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 3.0
+ Samba internal messaging functions
+ Copyright (C) Andrew Tridgell 2000
+
+ 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/* this module is used for internal messaging between Samba daemons. */
+
+#include "includes.h"
+
+/* the locking database handle */
+static TDB_CONTEXT *tdb;
+static int received_signal;
+
+/* change the message version with any incompatible changes in the protocol */
+#define MESSAGE_VERSION 1
+
+struct message_rec {
+ int msg_version;
+ enum message_type msg_type;
+ pid_t dest;
+ pid_t src;
+ size_t len;
+};
+
+/****************************************************************************
+notifications come in as signals
+****************************************************************************/
+static void sig_usr1(void)
+{
+ received_signal = 1;
+ sys_select_signal();
+}
+
+/****************************************************************************
+ Initialise the messaging functions.
+****************************************************************************/
+BOOL message_init(void)
+{
+ if (tdb) return True;
+
+ tdb = tdb_open(lock_path("messages.tdb"),
+ 0, TDB_CLEAR_IF_FIRST,
+ O_RDWR|O_CREAT,0600);
+
+ if (!tdb) {
+ DEBUG(0,("ERROR: Failed to initialise messages database\n"));
+ return False;
+ }
+
+ CatchSignal(SIGUSR1, sig_usr1);
+
+ return True;
+}
+
+
+/*******************************************************************
+ form a static tdb key from a pid
+******************************************************************/
+static TDB_DATA message_key_pid(pid_t pid)
+{
+ static char key[20];
+ TDB_DATA kbuf;
+
+ slprintf(key, sizeof(key), "PID/%d", (int)pid);
+
+ kbuf.dptr = (char *)key;
+ kbuf.dsize = sizeof(key);
+ return kbuf;
+}
+
+
+/****************************************************************************
+notify a process that it has a message. If the process doesn't exist
+then delete its record in the database
+****************************************************************************/
+static BOOL message_notify(pid_t pid)
+{
+ if (kill(pid, SIGUSR1) == -1) {
+ if (errno == ESRCH) {
+ DEBUG(2,("pid %d doesn't exist - deleting messages record\n", (int)pid));
+ tdb_delete(tdb, message_key_pid(pid));
+ } else {
+ DEBUG(2,("message to process %d failed - %s\n", (int)pid, strerror(errno)));
+ }
+ return False;
+ }
+ return True;
+}
+
+/****************************************************************************
+send a message to a particular pid
+****************************************************************************/
+BOOL message_send_pid(pid_t pid, enum message_type msg_type, void *buf, size_t len)
+{
+ TDB_DATA kbuf;
+ TDB_DATA dbuf;
+ struct message_rec rec;
+ void *p;
+
+ rec.msg_version = MESSAGE_VERSION;
+ rec.msg_type = msg_type;
+ rec.dest = pid;
+ rec.src = sys_getpid();
+ rec.len = len;
+
+ kbuf = message_key_pid(pid);
+
+ /* lock the record for the destination */
+ tdb_lockchain(tdb, kbuf);
+
+ dbuf = tdb_fetch(tdb, kbuf);
+
+ if (!dbuf.dptr) {
+ /* its a new record */
+ p = (void *)malloc(len + sizeof(rec));
+ if (!p) goto failed;
+
+ memcpy(p, &rec, sizeof(rec));
+ memcpy(p+sizeof(rec), buf, len);
+
+ dbuf.dptr = p;
+ dbuf.dsize = len + sizeof(rec);
+ tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
+ free(p);
+ goto ok;
+ }
+
+ /* we're adding to an existing entry */
+ p = (void *)malloc(dbuf.dsize + len + sizeof(rec));
+ if (!p) goto failed;
+
+ memcpy(p, dbuf.dptr, dbuf.dsize);
+ memcpy(p+dbuf.dsize, &rec, sizeof(rec));
+ memcpy(p+dbuf.dsize+sizeof(rec), buf, len);
+
+ dbuf.dptr = p;
+ dbuf.dsize += len + sizeof(rec);
+ tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
+ free(dbuf.dptr);
+ free(p);
+
+ ok:
+ tdb_unlockchain(tdb, kbuf);
+ return message_notify(pid);
+
+ failed:
+ tdb_unlockchain(tdb, kbuf);
+ return False;
+}
+
+
+
+/****************************************************************************
+retrieve the next message for the current process
+****************************************************************************/
+static BOOL message_recv(enum message_type *msg_type, pid_t *src, void **buf, size_t *len)
+{
+ TDB_DATA kbuf;
+ TDB_DATA dbuf;
+ struct message_rec rec;
+
+ kbuf = message_key_pid(sys_getpid());
+
+ tdb_lockchain(tdb, kbuf);
+
+ dbuf = tdb_fetch(tdb, kbuf);
+ if (dbuf.dptr == NULL || dbuf.dsize == 0) goto failed;
+
+ memcpy(&rec, dbuf.dptr, sizeof(rec));
+
+ if (rec.msg_version != MESSAGE_VERSION) {
+ DEBUG(0,("message version %d received (expected %d)\n", rec.msg_version, MESSAGE_VERSION));
+ goto failed;
+ }
+
+ (*buf) = (void *)malloc(rec.len);
+ if (!(*buf)) goto failed;
+
+ memcpy(*buf, dbuf.dptr+sizeof(rec), rec.len);
+ *len = rec.len;
+ *msg_type = rec.msg_type;
+ *src = rec.src;
+
+ memmove(dbuf.dptr, dbuf.dptr+sizeof(rec)+rec.len, dbuf.dsize - (sizeof(rec)+rec.len));
+ dbuf.dsize -= sizeof(rec)+rec.len;
+ tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
+
+ free(dbuf.dptr);
+ tdb_unlockchain(tdb, kbuf);
+ return True;
+
+ failed:
+ tdb_unlockchain(tdb, kbuf);
+ return False;
+}
+
+
+/****************************************************************************
+receive and dispatch any messages pending for this process
+****************************************************************************/
+void message_dispatch(void)
+{
+ enum message_type msg_type;
+ pid_t src;
+ void *buf;
+ size_t len;
+
+ if (!received_signal) return;
+ received_signal = 0;
+
+ while (message_recv(&msg_type, &src, &buf, &len)) {
+ switch (msg_type) {
+ case MSG_DEBUG:
+ debug_message(src, buf, len);
+ break;
+ default:
+ DEBUG(0,("Unknown message type %d from %d\n", msg_type, (int)src));
+ break;
+ }
+ }
+}