ext/bsdjail.c
author Mahlon E. Smith <mahlon@martini.nu>
Thu, 25 Dec 2008 08:35:46 +0000
branchmahlon-misc
changeset 11 e908d309e7ec
parent 9 4c51ebe6e9b6
permissions -rw-r--r--
* It compiles! * Removed additional leftover link parser stuff. * Removed unused memory allocate/free stuff until I discuss with my cohort. It may be back... it may be left over from linkparser too. ;) * list() works, but cores. Not sure why yet. Really, list() should be renamed to something sensible, and return instantiated BSD::Jail objects to attach() to or get additional info on. * Ruby C bindings are way, way fun. Reminds me how little C I can remember with one project a year :)

/*
 *
 *  bsdjail.c - Ruby jparallel
 *  $Id$
 *
 *  vim: set nosta noet ts=4 sw=4:
 *  
 *  Authors:
 *    * Michael Granger <ged@FaerieMUD.org>
 *    * Mahlon E. Smith <mahlon@martini.nu>
 *  
 *  Copyright (c) 2006 The FaerieMUD Consortium.
 *  
 *  This work is licensed under the Creative Commons Attribution License. To
 *  view a copy of this license, visit
 *  http://creativecommons.org/licenses/by/1.0 or send a letter to Creative
 *  Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.
 *  
 */

#include "bsdjail.h"

VALUE rbjail_mBSD;
VALUE rbjail_cBSDJail;


/*
struct jail {
	u_int32_t       version;
	char            *path;
	char            *hostname;
	u_int32_t       ip_number;
};
*/


static void
rbjail_do_jail_attach( int jid )
{
	if ( jail_attach(jid) == -1 )
		rb_sys_fail( "jail_attach" );
}

/* Mostly ripped off from Ruby's process.c */
static VALUE
rbjail_attach_block( int jid )
{
	int pid;

	rb_secure(2);

	fflush(stdout);
	fflush(stderr);

	switch ( pid = fork() ) {
		case 0:
			rb_thread_atfork();
			if ( rb_block_given_p() ) {
				int status;

				rbjail_do_jail_attach( jid );
				rb_protect( rb_yield, Qundef, &status );
				ruby_stop( status );
			}
			return Qnil;

		case -1:
			rb_sys_fail( "fork(2)" );
			return Qnil;

		default:
			return INT2FIX( pid );
	}
}

static VALUE
rbjail_attach( int argc, VALUE *argv, VALUE self )
{
	VALUE jidnum, rval;
	int jid;

	rb_scan_args( argc, argv, "1", &jidnum );
	jid = NUM2INT( jidnum );

	if ( rb_block_given_p() ) {
		rval = rbjail_attach_block( jid );
	}

	else {
		rbjail_do_jail_attach( jid );
		rval = Qtrue;
	}

	return rval;
}

static VALUE
rbjail_list( VALUE self )
{
	struct xprison *xp;
	struct in_addr in;
	size_t i, len;

	/* Get the size of the xprison and allocate memory to it. */
	if ( sysctlbyname("security.jail.list", NULL, &len, NULL, 0) == -1 )
		rb_sys_fail("sysctlbyname(): security.jail.list");
	xp = ALLOCA_N( struct xprison, 1 );

	/* Get and sanity check the current prison list */
	if ( sysctlbyname("security.jail.list", xp, &len, NULL, 0) == -1 ) {
		rb_sys_fail("sysctlbyname(): security.jail.list");
	}
	if ( len < sizeof(*xp) || len % sizeof(*xp) ||
			xp->pr_version != XPRISON_VERSION )
		rb_fatal("Kernel and userland out of sync");

	len /= sizeof(*xp);
	printf("   JID  IP Address      Hostname                      Path\n");
	for ( i = 0; i < len; i++ ) {
		in.s_addr = ntohl( xp->pr_ip );
		printf("%6d  %-15.15s %-29.29s %.74s\n",
				xp->pr_id, inet_ntoa(in), xp->pr_host, xp->pr_path);
		xp++;
	}
	return self;
}

void
Init_bsdjail( void )
{
	rbjail_mBSD = rb_define_module( "BSD" );
	rbjail_cBSDJail = rb_define_class_under( rbjail_mBSD, "Jail", rb_cObject );

	rb_define_singleton_method( rbjail_cBSDJail, "list", rbjail_list, 0 );

	/*
	rb_define_alloc_function( rbjail_cBSDJail, );

	rb_define_method( rbjail_cBSDJail, "attach", rbjail_attach, -1 );
	*/
}