/*
 * $Id: cap_proc.c,v 1.2.2.1 1999/04/23 06:16:31 morgan Exp $
 *
 * Copyright (c) 1997-9 Andrew G Morgan <morgan@linux.kernel.org>
 *
 * See end of file for Log.
 *
 * This file deals with setting capabilities on processes.
 */

#include "libcap.h"

static void _libcap_cappid(cap_t cap_d, pid_t pid)
{
    cap_d->head.version = _libcap_kernel_version;

    _cap_debug("version: %x, features: %x\n",
	       cap_d->head.version, cap_d->features);

#if (_LINUX_CAPABILITY_VERSION == 0x19980330)

    if (_libcap_kernel_version == 0x19980330) {
	cap_d->head.pid = pid;
    }
    _cap_debug("pid: %d\n", cap_d->head.pid);

#else

    if (_libcap_kernel_version == 0x19980330) {
	cap_d->head.type = pid;          /* a backward compatibility hack */
    } else {
	cap_d->head.type = _CAPABILITY_TYPE_PROCESS;
	cap_d->head.u.pid = pid;
    }
    _cap_debug("type: %d\npid: %d\n", cap_d->head.type, cap_d->head.u.pid);

#endif

    _cap_debugcap("effective = ", &cap_d->set.effective);
    _cap_debugcap("inheritable = ", &cap_d->set.inheritable);
    _cap_debugcap("permitted = ", &cap_d->set.permitted);
}

cap_t cap_get_proc(void)
{
    cap_t result;

    /* allocate a new capability set */
    result = cap_init();
    if (result) {
	_cap_debug("getting current process' capabilities");

	_libcap_cappid(result, 0);

	/* fill the capability sets via a system call */
	if (capget(&result->head, &result->set)) {
	    cap_free(&result);
	}
    }

    return result;
}

int cap_set_proc(cap_t cap_d)
{
    if (!good_cap_t(cap_d)) {
	errno = EINVAL;
	return -1;
    }

    _cap_debug("setting process capabilities");

    _libcap_cappid(cap_d, 0);

    return capset(&cap_d->head, &cap_d->set);
}

/* the following two functions are not required by POSIX */

/* read the caps on a specific process */

int capgetp(pid_t pid, cap_t cap_d)
{
    int error;

    if (!good_cap_t(cap_d)) {
	_cap_debug("failed check for good cap_t");
	errno = EINVAL;
	return -1;
    }

    _cap_debug("getting process capabilities for proc %d", pid);

    _libcap_cappid(cap_d, pid);
    error = capget(&cap_d->head, &cap_d->set);
    _libcap_cappid(cap_d, 0);

    return error;
}

/* set the caps on a specific process/pg etc.. */

int capsetp(pid_t pid, cap_t cap_d)
{
    int error;

    if (!good_cap_t(cap_d)) {
	errno = EINVAL;
	return -1;
    }

    _cap_debug("setting process capabilities for proc %d", pid);

    _libcap_cappid(cap_d, pid);
    error = capset(&cap_d->head, &cap_d->set);
    _libcap_cappid(cap_d, 0);

    return error;
}

/*
 * $Log: cap_proc.c,v $
 * Revision 1.2.2.1  1999/04/23 06:16:31  morgan
 * added support for revised kernel interface (with file cap support)
 *
 * Revision 1.2  1999/04/18 20:50:01  morgan
 * reliable behavior when trying to talk with a kernel that has a more
 * modern capability implementation than the one the library was compiled
 * with.
 *
 * Revision 1.1.1.1  1999/04/17 22:16:31  morgan
 * release 1.0 of libcap
 *
 * Revision 1.5  1998/05/24 22:54:09  morgan
 * updated for 2.1.104
 *
 * Revision 1.4  1997/05/14 05:17:13  morgan
 * bug-fix from zefram (errno no set on success)
 *
 * Revision 1.3  1997/05/04 05:35:46  morgan
 * fixed errno setting. syscalls do this part
 *
 * Revision 1.2  1997/04/28 00:57:11  morgan
 * fixes and zefram's patches
 *
 * Revision 1.1  1997/04/21 04:32:52  morgan
 * Initial revision
 *
 */
