lib/util_unistr.o lib/util_file.o \
lib/util.o lib/util_sock.o lib/util_sec.o smbd/ssl.o \
lib/talloc.o lib/hash.o lib/substitute.o lib/fsusage.o \
- lib/ms_fnmatch.o lib/select.o lib/error.o \
+ lib/ms_fnmatch.o lib/select.o lib/error.o lib/messages.o \
$(TDB_OBJ)
UBIQX_OBJ = ubiqx/ubi_BinTree.o ubiqx/ubi_Cache.o ubiqx/ubi_SplayTree.o \
STATUS_OBJ = utils/status.o $(LOCKING_OBJ) $(PARAM_OBJ) \
$(UBIQX_OBJ) $(PROFILE_OBJ) $(LIB_OBJ)
+MSGTEST_OBJ = utils/msgtest.o $(LOCKING_OBJ) $(PARAM_OBJ) \
+ $(UBIQX_OBJ) $(PROFILE_OBJ) $(LIB_OBJ)
+
TESTPARM_OBJ = utils/testparm.o \
$(PARAM_OBJ) $(UBIQX_OBJ) $(LIB_OBJ)
@echo Linking $@
@$(CC) $(FLAGS) -o $@ $(STATUS_OBJ) $(LDFLAGS) $(LIBS)
+bin/msgtest: $(MSGTEST_OBJ) bin/.dummy
+ @echo Linking $@
+ @$(CC) $(FLAGS) -o $@ $(MSGTEST_OBJ) $(LDFLAGS) $(LIBS)
+
bin/smbpasswd: $(SMBPASSWD_OBJ) bin/.dummy
@echo Linking $@
@$(CC) $(FLAGS) -o $@ $(SMBPASSWD_OBJ) $(LDFLAGS) $(LIBS)
#include "trans2.h"
#include "nterr.h"
#include "secrets.h"
+#include "messages.h"
#include "util_list.h"
#ifndef UBI_BINTREE_H
--- /dev/null
+/*
+ Unix SMB/Netbios implementation.
+ Version 3.0
+ messages.c header
+ 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.
+*/
+
+#ifndef _MESSAGES_H_
+#define _MESSAGES_H_
+
+enum message_type {MSG_DEBUG};
+
+#endif
/*The following definitions come from lib/debug.c */
-void sig_usr2( int sig );
-void sig_usr1( int sig );
+void debug_message(pid_t src, void *buf, int len);
+void debug_message_send(pid_t pid, int level);
void setup_logging( char *pname, BOOL interactive );
void reopen_logs( void );
void force_check_log_size( void );
void mdfour(unsigned char *out, unsigned char *in, int n);
+/*The following definitions come from lib/messages.c */
+
+BOOL message_init(void);
+BOOL message_send_pid(pid_t pid, enum message_type msg_type, void *buf, size_t len);
+void message_dispatch(void);
+
/*The following definitions come from lib/ms_fnmatch.c */
int ms_fnmatch(char *pattern, char *string);
* 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));
+}
/* ************************************************************************** **
--- /dev/null
+/*
+ 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;
+ }
+ }
+}
0644);
if (!tdb) {
- DEBUG(0,("ERROR: Failed to initialise share modes\n"));
+ DEBUG(0,("ERROR: Failed to initialise locking database\n"));
return False;
}
BlockSignals(True,SIGFPE);
#endif
- /* Setup the signals that allow the debug log level
- to by dynamically changed. */
-
- /* If we are using the malloc debug code we can't use
- SIGUSR1 and SIGUSR2 to do debug level changes. */
-#if defined(SIGUSR1)
- CatchSignal( SIGUSR1, SIGNAL_CAST sig_usr1 );
-#endif /* SIGUSR1 */
-
-#if defined(SIGUSR2)
- CatchSignal( SIGUSR2, SIGNAL_CAST sig_usr2 );
-#endif /* SIGUSR2 */
-
while( EOF !=
(opt = getopt( argc, argv, "Vaos:T:I:C:bAB:N:Rn:l:d:Dp:hSH:G:f:" )) )
{
/* We can only take signals in the select. */
BlockSignals( True, SIGTERM );
-#if defined(SIGUSR1)
- BlockSignals( True, SIGUSR1);
-#endif /* SIGUSR1 */
-#if defined(SIGUSR2)
- BlockSignals( True, SIGUSR2);
-#endif /* SIGUSR2 */
process();
/* Prepare for the select - allow certain signals. */
BlockSignals(False, SIGTERM);
-#if defined(SIGUSR1)
- BlockSignals(False, SIGUSR1);
-#endif /* SIGUSR1 */
-#if defined(SIGUSR2)
- BlockSignals(False, SIGUSR2);
-#endif /* SIGUSR2 */
selrtn = sys_select_intr(FD_SETSIZE,&fds,&timeout);
/* We can only take signals when we are in the select - block them again here. */
BlockSignals(True, SIGTERM);
-#if defined(SIGUSR1)
- BlockSignals(True, SIGUSR1);
-#endif /* SIGUSR1 */
-#if defined(SIGUSR2)
- BlockSignals(True, SIGUSR2);
-#endif /* SIGUSR2 */
if(selrtn > 0)
{
static BOOL print_client_info;
-static void sigusr1_handler(int signum)
-{
- BlockSignals(True, SIGUSR1);
- print_client_info = True;
- BlockSignals(False, SIGUSR1);
-}
-
static BOOL flush_cache;
static void sighup_handler(int signum)
CatchSignal(SIGPIPE, SIG_IGN); /* Ignore sigpipe */
- CatchSignal(SIGUSR1, sigusr1_handler); /* Debugging sigs */
CatchSignal(SIGHUP, sighup_handler);
/* Create UNIX domain socket */
reload_services(False);
reload_after_sighup = False;
}
+
+ /* check for any pending internal messages */
+ message_dispatch();
}
/****************************************************************************
CatchSignal(SIGHUP,SIGNAL_CAST sig_hup);
- /* Setup the signals that allow the debug log level
- to by dynamically changed. */
-
- /* If we are using the malloc debug code we can't use
- SIGUSR1 and SIGUSR2 to do debug level changes. */
-
-#if defined(SIGUSR1)
- CatchSignal( SIGUSR1, SIGNAL_CAST sig_usr1 );
-#endif /* SIGUSR1 */
-
-#if defined(SIGUSR2)
- CatchSignal( SIGUSR2, SIGNAL_CAST sig_usr2 );
-#endif /* SIGUSR2 */
-
DEBUG(3,( "loaded services\n"));
if (!is_daemon && !is_a_socket(0)) {
* everything after this point is run after the fork()
*/
+ if (!message_init()) {
+ exit(1);
+ }
+
if (!locking_init(0)) {
exit(1);
}