/*
 * Functions used to support signals during
 * EFS calls.
 *
 * jam 850311
 */

#include "../h/param.h"
#include "../h/dir.h"
#include "../h/user.h"
#include "../h/proc.h"

#include "../vnet/vnet.h"
#include "../conn/conn.h"
#include "../rpc/rpc.h"
#include "../efs/efs.h"

#ifdef INTERMEDSIG
#define PROCFLAGS	(SOUSIG | SNUSIG)
#else INTERMEDSIG
#define PROCFLAGS	(SOUSIG)
#endif INTERMEDSIG

struct efs_sendenvCall {
	int		length;		/* Length of this packet */
	int		rfd;		/* Remote file descriptor */
	int		procflags;	/* Process flags (SNUSIG, SOUSIG) */
};

struct efs_sendenvReturn {
	int		length;		/* Length of this packet */
	int		error;		/* Error number */
};

/*
 * Send the current environment information
 * (for this node) to the remote descriptor.
 */
int
efs_sendenv(remote)
   register efs_remoteFile_t *remote;
{
	register struct efs_sendenvCall *params;
	register struct efs_sendenvReturn *results;

	/*
	 * Systems with version numbers less than
	 * 0x0001 will not respond correctly to
	 * environment calls.
	 */
	if (remote->conn->version < 0x0001)
		return;

	params = efs_makePacket(sendenv,0);
	params->length = sizeof(*params);
	params->rfd = remote->rfd;
	params->procflags = u.u_procp->p_flag & PROCFLAGS;
	results = (struct efs_sendenvReturn *)
				efs_call(remote->conn,EFS_SENDENV,params);
	if (results)
		rpc_freeResults(results);
}

caddr_t
efs_remoteSendenv(clientConn, clientId, operation, params)
   connection_t *clientConn;
   u_long clientId;
   u_short operation;
   register struct efs_sendenvCall *params;
{
	register struct efs_sendenvReturn *results;
	register efs_localFile_t *local;

	results = efs_makeReturnPacket(params,sendenv, 0);
	results->length = sizeof(*results);
	if ((local = efs_rfdToLocal(params->rfd)) == NULL) {
		results->error = EBADF;
	} else {
		local->procflags = params->procflags;
		results->error = 0;
	}
	rpc_freeParams(params);
	return((caddr_t)results);
}

/*
 * Check that the remote descriptor is
 * up-to-date with respect to the environment.
 * If it is not then send it.
 */
efs_checkenv(remote)
   register efs_remoteFile_t *remote;
{
	if (remote->procflags != (u.u_procp->p_flag & PROCFLAGS)) {
		remote->procflags = u.u_procp->p_flag & PROCFLAGS;
		efs_sendenv(remote);
	}
}

/*
 * Take part of the environment from the
 * local file descriptor into the current
 * process.
 */
efs_takeenv(local)
   register efs_localFile_t *local;
{
	u.u_procp->p_flag &= ~PROCFLAGS;
	u.u_procp->p_flag |= local->procflags & PROCFLAGS;
}
