/* $Id: port-solaris.c,v 1.1 2006/08/30 17:24:42 djm Exp $ */

/*
 * Copyright (c) 2006 Chad Mynhier.
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include "config.h"
#include "includes.h"

#ifdef USE_SOLARIS_PROCESS_CONTRACTS

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>

#include <errno.h>
#ifdef HAVE_FCNTL_H
# include <fcntl.h>
#endif
#include <string.h>
#include <unistd.h>

#include <libcontract.h>
#include <sys/contract/process.h>
#include <sys/ctfs.h>

#include "log.h"

#define CT_TEMPLATE	CTFS_ROOT "/process/template"
#define CT_LATEST	CTFS_ROOT "/process/latest"

static int tmpl_fd = -1;

/* Lookup the latest process contract */
static ctid_t
get_active_process_contract_id(void)
{
	int stat_fd;
	ctid_t ctid = -1;
	ct_stathdl_t stathdl;

	if ((stat_fd = open64(CT_LATEST, O_RDONLY)) == -1) {
		error("%s: Error opening 'latest' process "
		    "contract: %s", __func__, strerror(errno));
		return -1;
	}
	if (ct_status_read(stat_fd, CTD_COMMON, &stathdl) != 0) {
		error("%s: Error reading process contract "
		    "status: %s", __func__, strerror(errno));
		goto out;
	}
	if ((ctid = ct_status_get_id(stathdl)) < 0) {
		error("%s: Error getting process contract id: %s",
		    __func__, strerror(errno));
		goto out;
	}

	ct_status_free(stathdl);
 out:
	close(stat_fd);
	return ctid;
}

void
solaris_contract_pre_fork(void)
{
	if ((tmpl_fd = open64(CT_TEMPLATE, O_RDWR)) == -1) {
		error("%s: open %s: %s", __func__,
		    CT_TEMPLATE, strerror(errno));
		return;
	}

	debug2("%s: setting up process contract template on fd %d",
	    __func__, tmpl_fd);

	/* We have to set certain attributes before activating the template */
	if (ct_pr_tmpl_set_fatal(tmpl_fd,
	    CT_PR_EV_HWERR|CT_PR_EV_SIGNAL|CT_PR_EV_CORE) != 0) {
		error("%s: Error setting process contract template "
		    "fatal events: %s", __func__, strerror(errno));
		goto fail;
	}
	if (ct_tmpl_set_critical(tmpl_fd, CT_PR_EV_HWERR) != 0) {
		error("%s: Error setting process contract template "
		    "critical events: %s", __func__, strerror(errno));
		goto fail;
	}

	/* Now make this the active template for this process. */
	if (ct_tmpl_activate(tmpl_fd) != 0) {
		error("%s: Error activating process contract "
		    "template: %s", __func__, strerror(errno));
		goto fail;
	}
	return;

 fail:
	if (tmpl_fd != -1) {
		close(tmpl_fd);
		tmpl_fd = -1;
	}
}

void
solaris_contract_post_fork_child()
{
	debug2("%s: clearing process contract template on fd %d",
	    __func__, tmpl_fd);

	/* Clear the active template. */
	if (ct_tmpl_clear(tmpl_fd) != 0)
		error("%s: Error clearing active process contract "
		    "template: %s", __func__, strerror(errno));

	close(tmpl_fd);
	tmpl_fd = -1;
}

void
solaris_contract_post_fork_parent(pid_t pid)
{
	ctid_t ctid;
	char ctl_path[256];
	int r, ctl_fd = -1, stat_fd = -1;

	debug2("%s: clearing template (fd %d)", __func__, tmpl_fd);

	if (tmpl_fd == -1)
		return;

	/* First clear the active template. */
	if ((r = ct_tmpl_clear(tmpl_fd)) != 0)
		error("%s: Error clearing active process contract "
		    "template: %s", __func__, strerror(errno));

	close(tmpl_fd);
	tmpl_fd = -1;

	/*
	 * If either the fork didn't succeed (pid < 0), or clearing
	 * th active contract failed (r != 0), then we have nothing
	 * more do.
	 */
	if (r != 0 || pid <= 0)
		return;

	/* Now lookup and abandon the contract we've created. */
	ctid = get_active_process_contract_id();

	debug2("%s: abandoning contract id %ld", __func__, ctid);

	snprintf(ctl_path, sizeof(ctl_path),
	    CTFS_ROOT "/process/%ld/ctl", ctid);
	if ((ctl_fd = open64(ctl_path, O_WRONLY)) < 0) {
		error("%s: Error opening process contract "
		    "ctl file: %s", __func__, strerror(errno));
		goto fail;
	}
	if (ct_ctl_abandon(ctl_fd) < 0) {
		error("%s: Error abandoning process contract: %s",
		    __func__, strerror(errno));
		goto fail;
	}
	close(ctl_fd);
	return;

 fail:
	if (tmpl_fd != -1) {
		close(tmpl_fd);
		tmpl_fd = -1;
	}
	if (stat_fd != -1)
		close(stat_fd);
	if (ctl_fd != -1)
		close(ctl_fd);
}
#endif
