ext/bsdjail.c
changeset 0 92d00ff32c56
child 2 0c24586f579a
child 9 4c51ebe6e9b6
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ext/bsdjail.c	Fri Aug 15 15:43:38 2008 +0000
@@ -0,0 +1,233 @@
+/*
+ *  dict.c - Ruby LinkParser - Dict Class
+ *  $Id$
+ *  
+ *  Authors:
+ *    * Michael Granger <ged@FaerieMUD.org>
+ *  
+ *  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 <ruby.h>
+#include <intern.h>
+
+#include <stdio.h>
+#include <sys/param.h>
+#include <sys/jail.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+
+VALUE rbjail_mBSD;
+VALUE rbjail_cBSDJail;
+
+
+/*
+struct jail {
+	u_int32_t       version;
+	char            *path;
+	char            *hostname;
+	u_int32_t       ip_number;
+};
+*/
+
+/*
+ * Allocation function
+ */
+static jail *
+rbjail_jail_alloc()
+{
+	jail *ptr = ALLOC( jail );
+	
+	ptr->version	= 0;
+	ptr->path		= NULL;
+	ptr->hostname	= NULL;
+	ptr->ip_number	= 0;
+	
+	debugMsg(( "Initialized a jail pointer <%p>", ptr ));
+	return ptr;
+}
+
+
+/*
+ * GC Free function
+ */
+static void
+rbjail_jail_gc_free( ptr )
+	jail *ptr;
+{
+	if ( ptr ) {
+		ptr->path		= NULL;
+		ptr->hostname	= NULL;
+		xfree( ptr );
+	}
+	
+	else {
+		debugMsg(( "Not freeing an uninitialized rlink_SENTENCE" ));
+	}
+}
+
+
+/*
+ * Object validity checker. Returns the data pointer.
+ */
+static rlink_SENTENCE *
+check_sentence( self )
+	 VALUE	self;
+{
+	debugMsg(( "Checking a LinkParser::Sentence object (%d).", self ));
+	Check_Type( self, T_DATA );
+
+    if ( !IsSentence(self) ) {
+		rb_raise( rb_eTypeError, "wrong argument type %s (expected LinkParser::Sentence)",
+				  rb_class2name(CLASS_OF( self )) );
+    }
+	
+	return DATA_PTR( self );
+}
+
+
+/*
+ * Fetch the data pointer and check it for sanity.
+ */
+static rlink_SENTENCE *
+get_sentence( self )
+	 VALUE self;
+{
+	rlink_SENTENCE *ptr = check_sentence( self );
+
+	debugMsg(( "Fetching a Sentence (%p).", ptr ));
+	if ( !ptr )
+		rb_raise( rb_eRuntimeError, "uninitialized Sentence" );
+
+	return ptr;
+}
+
+
+/*
+ * Publicly-usable sentence-fetcher
+ */
+rlink_SENTENCE *
+rlink_get_sentence( self )
+	VALUE self;
+{
+	return get_sentence( self );
+}
+
+
+
+
+
+
+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 kinfo_prison *sxp, *xp;
+	struct in_addr in;
+	size_t i, len;
+
+	if (sysctlbyname("jail.list", NULL, &len, NULL, 0) == -1)
+		rb_sys_fail("sysctlbyname(): jail.list");
+
+	xp = ALLOCA_N( kinfo_prison, 1 );
+
+	if (sysctlbyname("jail.list", xp, &len, NULL, 0) == -1) {
+		rb_sys_fail("sysctlbyname(): jail.list");
+	}
+
+	if (len < sizeof(*xp) || len % sizeof(*xp) ||
+		xp->pr_version != KINFO_PRISON_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++;
+	}
+	free(sxp);
+	exit(0);
+
+}
+
+void
+Init_bsdjail( void )
+{
+	rbjail_mBSD = rb_define_module( "BSD" );
+	rbjail_cBSDJail = rb_define_class_under( rbjail_mBSD, "Jail" );
+
+	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 );
+	
+}
+