Esempio n. 1
0
static BOOL retrieve_all_messages(char **msgs_buf, size_t *total_len)
{
	TDB_DATA kbuf;
	TDB_DATA dbuf;
	TDB_DATA null_dbuf;

	ZERO_STRUCT(null_dbuf);

	*msgs_buf = NULL;
	*total_len = 0;

	kbuf = message_key_pid(pid_to_procid(sys_getpid()));

	if (tdb_chainlock(tdb, kbuf) == -1)
		return False;

	dbuf = tdb_fetch(tdb, kbuf);
	/*
	 * Replace with an empty record to keep the allocated
	 * space in the tdb.
	 */
	tdb_store(tdb, kbuf, null_dbuf, TDB_REPLACE);
	tdb_chainunlock(tdb, kbuf);

	if (dbuf.dptr == NULL || dbuf.dsize == 0) {
		SAFE_FREE(dbuf.dptr);
		return False;
	}

	*msgs_buf = dbuf.dptr;
	*total_len = dbuf.dsize;

	return True;
}
Esempio n. 2
0
unsigned int messages_pending_for_pid(struct process_id pid)
{
	TDB_DATA kbuf;
	TDB_DATA dbuf;
	char *buf;
	unsigned int message_count = 0;

	kbuf = message_key_pid(pid);

	dbuf = tdb_fetch(tdb, kbuf);
	if (dbuf.dptr == NULL || dbuf.dsize == 0) {
		SAFE_FREE(dbuf.dptr);
		return 0;
	}

	for (buf = dbuf.dptr; dbuf.dsize > sizeof(struct message_rec);) {
		struct message_rec rec;
		memcpy(&rec, buf, sizeof(rec));
		buf += (sizeof(rec) + rec.len);
		dbuf.dsize -= (sizeof(rec) + rec.len);
		message_count++;
	}

	SAFE_FREE(dbuf.dptr);
	return message_count;
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
static BOOL message_recv(int *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_chainlock(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;
	}

	if (rec.len > 0) {
		(*buf) = (void *)malloc(rec.len);
		if (!(*buf)) goto failed;

		memcpy(*buf, dbuf.dptr+sizeof(rec), rec.len);
	} else {
		*buf = NULL;
	}

	*len = rec.len;
	*msg_type = rec.msg_type;
	*src = rec.src;

	if (dbuf.dsize - (sizeof(rec)+rec.len) > 0)
		memmove(dbuf.dptr, dbuf.dptr+sizeof(rec)+rec.len, dbuf.dsize - (sizeof(rec)+rec.len));
	dbuf.dsize -= sizeof(rec)+rec.len;

	if (dbuf.dsize == 0)
		tdb_delete(tdb, kbuf);
	else
		tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);

	SAFE_FREE(dbuf.dptr);
	tdb_chainunlock(tdb, kbuf);
	return True;

 failed:
	tdb_chainunlock(tdb, kbuf);
	return False;
}
Esempio n. 5
0
static BOOL message_notify(struct process_id procid)
{
	pid_t pid = procid.pid;
	/*
	 * Doing kill with a non-positive pid causes messages to be
	 * sent to places we don't want.
	 */

	SMB_ASSERT(pid > 0);

	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(procid));
		} else {
			DEBUG(2,("message to process %d failed - %s\n", (int)pid, strerror(errno)));
		}
		return False;
	}
	return True;
}
Esempio n. 6
0
BOOL message_send_pid(pid_t pid, int msg_type, const void *buf, size_t len,
		      BOOL duplicates_allowed)
{
	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_chainlock(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));
		if (len > 0) memcpy((void *)((char*)p+sizeof(rec)), buf, len);

		dbuf.dptr = p;
		dbuf.dsize = len + sizeof(rec);
		tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
		SAFE_FREE(p);
		goto ok;
	}

	if (!duplicates_allowed) {
		char *ptr;
		struct message_rec prec;
		
		for(ptr = (char *)dbuf.dptr; ptr < dbuf.dptr + dbuf.dsize; ) {
			/*
			 * First check if the message header matches, then, if it's a non-zero
			 * sized message, check if the data matches. If so it's a duplicate and
			 * we can discard it. JRA.
			 */

			if (!memcmp(ptr, &rec, sizeof(rec))) {
				if (!len || (len && !memcmp( ptr + sizeof(rec), buf, len))) {
					DEBUG(10,("message_send_pid: discarding duplicate message.\n"));
					SAFE_FREE(dbuf.dptr);
					tdb_chainunlock(tdb, kbuf);
					return True;
				}
			}
			memcpy(&prec, ptr, sizeof(prec));
			ptr += sizeof(rec) + prec.len;
		}
	}

	/* 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((void *)((char*)p+dbuf.dsize), &rec, sizeof(rec));
	if (len > 0) memcpy((void *)((char*)p+dbuf.dsize+sizeof(rec)), buf, len);

	SAFE_FREE(dbuf.dptr);
	dbuf.dptr = p;
	dbuf.dsize += len + sizeof(rec);
	tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
	SAFE_FREE(dbuf.dptr);

 ok:
	tdb_chainunlock(tdb, kbuf);
	errno = 0;                    /* paranoia */
	return message_notify(pid);

 failed:
	tdb_chainunlock(tdb, kbuf);
	errno = 0;                    /* paranoia */
	return False;
}
Esempio n. 7
0
static BOOL message_send_pid_internal(struct process_id pid, int msg_type,
				      const void *buf, size_t len,
				      BOOL duplicates_allowed,
				      unsigned int timeout)
{
	TDB_DATA kbuf;
	TDB_DATA dbuf;
	TDB_DATA old_dbuf;
	struct message_rec rec;
	char *ptr;
	struct message_rec prec;

	/* NULL pointer means implicit length zero. */
	if (!buf) {
		SMB_ASSERT(len == 0);
	}

	/*
	 * Doing kill with a non-positive pid causes messages to be
	 * sent to places we don't want.
	 */

	SMB_ASSERT(procid_to_pid(&pid) > 0);

	rec.msg_version = MESSAGE_VERSION;
	rec.msg_type = msg_type;
	rec.dest = pid;
	rec.src = procid_self();
	rec.len = buf ? len : 0;

	kbuf = message_key_pid(pid);

	dbuf.dptr = (void *)SMB_MALLOC(len + sizeof(rec));
	if (!dbuf.dptr)
		return False;

	memcpy(dbuf.dptr, &rec, sizeof(rec));
	if (len > 0 && buf)
		memcpy((void *)((char*)dbuf.dptr+sizeof(rec)), buf, len);

	dbuf.dsize = len + sizeof(rec);

	if (duplicates_allowed) {

		/* If duplicates are allowed we can just append the message and return. */

		/* lock the record for the destination */
		if (timeout) {
			if (tdb_chainlock_with_timeout(tdb, kbuf, timeout) == -1) {
				DEBUG(0,("message_send_pid_internal: failed to get chainlock with timeout %ul.\n", timeout));
				return False;
			}
		} else {
			if (tdb_chainlock(tdb, kbuf) == -1) {
				DEBUG(0,("message_send_pid_internal: failed to get chainlock.\n"));
				return False;
			}
		}	
		tdb_append(tdb, kbuf, dbuf);
		tdb_chainunlock(tdb, kbuf);

		SAFE_FREE(dbuf.dptr);
		errno = 0;                    /* paranoia */
		return message_notify(pid);
	}

	/* lock the record for the destination */
	if (timeout) {
		if (tdb_chainlock_with_timeout(tdb, kbuf, timeout) == -1) {
			DEBUG(0,("message_send_pid_internal: failed to get chainlock with timeout %ul.\n", timeout));
			return False;
		}
	} else {
		if (tdb_chainlock(tdb, kbuf) == -1) {
			DEBUG(0,("message_send_pid_internal: failed to get chainlock.\n"));
			return False;
		}
	}	

	old_dbuf = tdb_fetch(tdb, kbuf);

	if (!old_dbuf.dptr) {
		/* its a new record */

		tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
		tdb_chainunlock(tdb, kbuf);

		SAFE_FREE(dbuf.dptr);
		errno = 0;                    /* paranoia */
		return message_notify(pid);
	}

	/* Not a new record. Check for duplicates. */

	for(ptr = (char *)old_dbuf.dptr; ptr < old_dbuf.dptr + old_dbuf.dsize; ) {
		/*
		 * First check if the message header matches, then, if it's a non-zero
		 * sized message, check if the data matches. If so it's a duplicate and
		 * we can discard it. JRA.
		 */

		if (!memcmp(ptr, &rec, sizeof(rec))) {
			if (!len || (len && !memcmp( ptr + sizeof(rec), buf, len))) {
				tdb_chainunlock(tdb, kbuf);
				DEBUG(10,("message_send_pid_internal: discarding duplicate message.\n"));
				SAFE_FREE(dbuf.dptr);
				SAFE_FREE(old_dbuf.dptr);
				return True;
			}
		}
		memcpy(&prec, ptr, sizeof(prec));
		ptr += sizeof(rec) + prec.len;
	}

	/* we're adding to an existing entry */

	tdb_append(tdb, kbuf, dbuf);
	tdb_chainunlock(tdb, kbuf);

	SAFE_FREE(old_dbuf.dptr);
	SAFE_FREE(dbuf.dptr);

	errno = 0;                    /* paranoia */
	return message_notify(pid);
}