Index: package_tags/sipb-xen-console/4/debian/changelog
===================================================================
--- package_tags/sipb-xen-console/4/debian/changelog	(revision 360)
+++ package_tags/sipb-xen-console/4/debian/changelog	(revision 360)
@@ -0,0 +1,40 @@
+sipb-xen-console (4) unstable; urgency=low
+
+  * Added comments to sipb-xen-consolefs
+  * Added support for symlinks in the realpath
+  * Changed sipb-xen-consolefs to use syslog instead of printf debugging
+
+ -- SIPB Xen Project <sipb-xen@mit.edu>  Sun, 30 Mar 2008 14:17:59 -0400
+
+sipb-xen-console (3.2) unstable; urgency=low
+
+  * Fixing a bug in sipb-xen-consolefs ('@' is not re-added to realms
+    in the .k5login
+
+ -- SIPB Xen Project <sipb-xen@mit.edu>  Sun, 30 Mar 2008 06:39:30 -0400
+
+sipb-xen-console (3.1) unstable; urgency=low
+
+  * Clean up the motd a bit
+  * Add dependency on sipb-xen-chrony-config to make sure the clock is
+    staying synced
+
+ -- SIPB Xen Project <sipb-xen@mit.edu>  Sun, 30 Mar 2008 06:33:55 -0400
+
+sipb-xen-console (3) unstable; urgency=low
+
+  * Make the motd useful instead of turning it off
+
+ -- SIPB Xen Project <sipb-xen@mit.edu>  Sun, 30 Mar 2008 06:14:23 -0400
+
+sipb-xen-console (2) unstable; urgency=low
+
+  * Actually functional release.
+
+ -- SIPB Xen Project <sipb-xen@mit.edu>  Sun, 30 Mar 2008 05:07:43 -0400
+
+sipb-xen-console (1) unstable; urgency=low
+
+  * Initial release.
+
+ -- SIPB Xen Project <sipb-xen@mit.edu>  Sun, 30 Mar 2008 01:08:50 -0400
Index: package_tags/sipb-xen-console/4/debian/compat
===================================================================
--- package_tags/sipb-xen-console/4/debian/compat	(revision 360)
+++ package_tags/sipb-xen-console/4/debian/compat	(revision 360)
@@ -0,0 +1,1 @@
+5
Index: package_tags/sipb-xen-console/4/debian/control
===================================================================
--- package_tags/sipb-xen-console/4/debian/control	(revision 360)
+++ package_tags/sipb-xen-console/4/debian/control	(revision 360)
@@ -0,0 +1,15 @@
+Source: sipb-xen-console
+Section: servers
+Priority: important
+Maintainer: sipb-xen@mit.edu
+Build-Depends: cdbs (>= 0.4.23-1.1), debhelper (>= 5), config-package-dev
+Standards-Version: 3.7.2
+
+Package: sipb-xen-console
+Architecture: all
+Provides: ${diverted-files}
+Conflicts: ${diverted-files}
+Depends: ${shlibs:Depends}, ${misc:Depends}, daemon, fuse-utils, libnss-pgsql1, nscd, openssh-client, openssh-server, python-fuse, sipb-xen-database-common
+Description: SIPB Xen serial console server
+ This package  should be installed on sipb-xen-console
+ It makes sure that necessary tools are available.
Index: package_tags/sipb-xen-console/4/debian/control.in
===================================================================
--- package_tags/sipb-xen-console/4/debian/control.in	(revision 360)
+++ package_tags/sipb-xen-console/4/debian/control.in	(revision 360)
@@ -0,0 +1,15 @@
+Source: sipb-xen-console
+Section: servers
+Priority: important
+Maintainer: sipb-xen@mit.edu
+Build-Depends: @cdbs@
+Standards-Version: 3.7.2
+
+Package: sipb-xen-console
+Architecture: all
+Provides: ${diverted-files}
+Conflicts: ${diverted-files}
+Depends: ${shlibs:Depends}, ${misc:Depends}, daemon, fuse-utils, libnss-pgsql1, nscd, openssh-client, openssh-server, python-fuse, sipb-xen-chrony-config, sipb-xen-database-common
+Description: SIPB Xen serial console server
+ This package  should be installed on sipb-xen-console
+ It makes sure that necessary tools are available.
Index: package_tags/sipb-xen-console/4/debian/copyright
===================================================================
--- package_tags/sipb-xen-console/4/debian/copyright	(revision 360)
+++ package_tags/sipb-xen-console/4/debian/copyright	(revision 360)
@@ -0,0 +1,3 @@
+This package was created for internal use of the SIPB Xen Project of
+the MIT Student Information Processing Board.  Ask sipb-xen@mit.edu if
+you have questions about redistribution.
Index: package_tags/sipb-xen-console/4/debian/rules
===================================================================
--- package_tags/sipb-xen-console/4/debian/rules	(revision 360)
+++ package_tags/sipb-xen-console/4/debian/rules	(revision 360)
@@ -0,0 +1,13 @@
+#!/usr/bin/make -f
+
+DEB_AUTO_UPDATE_DEBIAN_CONTROL = 1
+DEB_DIVERT_EXTENSION = .sipb-xen
+DEB_DIVERT_FILES_sipb-xen-console += \
+	/etc/init.d/bootmisc.sh \
+	/etc/nscd.conf \
+	/etc/nsswitch.conf \
+	/etc/motd \
+	/etc/ssh/ssh_config
+
+include /usr/share/cdbs/1/rules/debhelper.mk
+include /usr/share/cdbs/1/rules/replace-files.mk
Index: package_tags/sipb-xen-console/4/debian/sipb-xen-console.init
===================================================================
--- package_tags/sipb-xen-console/4/debian/sipb-xen-console.init	(revision 360)
+++ package_tags/sipb-xen-console/4/debian/sipb-xen-console.init	(revision 360)
@@ -0,0 +1,125 @@
+#! /bin/sh
+### BEGIN INIT INFO
+# Provides:          sipb-xen-console
+# Required-Start:    $local_fs $remote_fs
+# Required-Stop:     $local_fs $remote_fs
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: sipb-xen Console Server homedir filesystem
+# Description:       
+### END INIT INFO
+
+# Author: SIPB Xen Project <sipb-xen@mit.edu>
+
+# Do NOT "set -e"
+
+# PATH should only include /usr/* if it runs after the mountnfs.sh script
+PATH=/sbin:/usr/sbin:/bin:/usr/bin
+DESC="The sipb-xen console server homedir filesystem"
+NAME=sipb-xen-console
+DAEMON=/usr/bin/sipb-xen-consolefs
+DAEMON_ARGS="/consolefs"
+PIDFILE=/var/run/$NAME.pid
+SCRIPTNAME=/etc/init.d/$NAME
+
+# Exit if the package is not installed
+[ -x "$DAEMON" ] || exit 0
+
+# Read configuration variable file if it is present
+[ -r /etc/default/$NAME ] && . /etc/default/$NAME
+
+# Load the VERBOSE setting and other rcS variables
+. /lib/init/vars.sh
+
+# Define LSB log_* functions.
+# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
+. /lib/lsb/init-functions
+
+#
+# Function that starts the daemon/service
+#
+do_start()
+{
+	# Return
+	#   0 if daemon has been started
+	#   1 if daemon was already running
+	#   2 if daemon could not be started
+	daemon --running -n $NAME && return 1
+	daemon -r -O daemon.info -E daemon.err -n $NAME -U $DAEMON $DAEMON_ARGS || return 2
+}
+
+#
+# Function that stops the daemon/service
+#
+do_stop()
+{
+	# Return
+	#   0 if daemon has been stopped
+	#   1 if daemon was already stopped
+	#   2 if daemon could not be stopped
+	#   other if a failure occurred
+	daemon --stop -n $NAME
+	RETVAL="$?"
+	[ "$RETVAL" = 2 ] && return 2
+	# Many daemons don't delete their pidfiles when they exit.
+	rm -f $PIDFILE
+	umount "$DAEMON_ARGS"
+	return "$RETVAL"
+}
+
+case "$1" in
+  start)
+	[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
+	do_start
+	case "$?" in
+		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
+		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
+	esac
+	;;
+  stop)
+	[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
+	do_stop
+	case "$?" in
+		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
+		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
+	esac
+	;;
+  #reload|force-reload)
+	#
+	# If do_reload() is not implemented then leave this commented out
+	# and leave 'force-reload' as an alias for 'restart'.
+	#
+	#log_daemon_msg "Reloading $DESC" "$NAME"
+	#do_reload
+	#log_end_msg $?
+	#;;
+  restart|force-reload)
+	#
+	# If the "reload" option is implemented then remove the
+	# 'force-reload' alias
+	#
+	log_daemon_msg "Restarting $DESC" "$NAME"
+	do_stop
+	case "$?" in
+	  0|1)
+		do_start
+		case "$?" in
+			0) log_end_msg 0 ;;
+			1) log_end_msg 1 ;; # Old process is still running
+			*) log_end_msg 1 ;; # Failed to start
+		esac
+		;;
+	  *)
+	  	# Failed to stop
+		log_end_msg 1
+		;;
+	esac
+	;;
+  *)
+	#echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
+	echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
+	exit 3
+	;;
+esac
+
+:
Index: package_tags/sipb-xen-console/4/debian/sipb-xen-console.install
===================================================================
--- package_tags/sipb-xen-console/4/debian/sipb-xen-console.install	(revision 360)
+++ package_tags/sipb-xen-console/4/debian/sipb-xen-console.install	(revision 360)
@@ -0,0 +1,1 @@
+files/* .
Index: package_tags/sipb-xen-console/4/files/etc/init.d/bootmisc.sh.sipb-xen
===================================================================
--- package_tags/sipb-xen-console/4/files/etc/init.d/bootmisc.sh.sipb-xen	(revision 360)
+++ package_tags/sipb-xen-console/4/files/etc/init.d/bootmisc.sh.sipb-xen	(revision 360)
@@ -0,0 +1,92 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          bootmisc
+# Required-Start:    $local_fs hostname $remote_fs
+# Required-Stop:     $local_fs
+# Default-Start:     S
+# Default-Stop:
+# Short-Description: Miscellaneous things to be done during bootup.
+# Description:
+### END INIT INFO
+
+PATH=/sbin:/usr/sbin:/bin:/usr/bin
+[ "$DELAYLOGIN" ] || DELAYLOGIN=yes
+. /lib/init/vars.sh
+
+do_start () {
+	#
+	# If login delaying is enabled then create the flag file
+	# which prevents logins before startup is complete
+	#
+	case "$DELAYLOGIN" in
+	  Y*|y*)
+		echo "System bootup in progress - please wait" > /var/lib/initscripts/nologin
+		;;
+	esac
+
+	# Create /var/run/utmp so we can login.
+	: > /var/run/utmp
+	if grep -q ^utmp: /etc/group
+	then
+		chmod 664 /var/run/utmp
+		chgrp utmp /var/run/utmp
+	fi
+
+	# Set pseudo-terminal access permissions.
+	if [ ! -e /dev/.devfsd ] && [ -c /dev/ttyp0 ]
+	then
+		chmod -f 666 /dev/tty[p-za-e][0-9a-f]
+		chown -f root:tty /dev/tty[p-za-e][0-9a-f]
+	fi
+
+	# Do not update motd
+	#uname -snrvm > /var/run/motd
+	#[ -f /etc/motd.tail ] && cat /etc/motd.tail >> /var/run/motd
+	cp /etc/motd /var/run/motd
+
+	# Save kernel messages in /var/log/dmesg
+	if which dmesg >/dev/null 2>&1
+	then
+		savelog -q -p -c 5 /var/log/dmesg
+		dmesg -s 524288 > /var/log/dmesg
+		chgrp adm /var/log/dmesg || :
+	elif [ -c /dev/klog ]
+	then
+		savelog -q -p -c 5 /var/log/dmesg
+		dd if=/dev/klog of=/var/log/dmesg &
+		sleep 1
+		kill $!
+		[ -f /var/log/dmesg ] && { chgrp adm /var/log/dmesg || : ; }
+	fi
+
+	#
+	#	Save udev log in /var/log/udev
+	#
+	if [ -e /dev/.udev.log ]
+	then
+		mv -f /dev/.udev.log /var/log/udev
+	fi
+
+	# Remove bootclean's flag files.
+	# Don't run bootclean again after this!
+	rm -f /tmp/.clean /var/run/.clean /var/lock/.clean
+}
+
+case "$1" in
+  start|"")
+	do_start
+	;;
+  restart|reload|force-reload)
+	echo "Error: argument '$1' not supported" >&2
+	exit 3
+	;;
+  stop)
+	# No-op
+	;;
+  *)
+	echo "Usage: bootmisc.sh [start|stop]" >&2
+	exit 3
+	;;
+esac
+
+:
Index: package_tags/sipb-xen-console/4/files/etc/motd.sipb-xen
===================================================================
--- package_tags/sipb-xen-console/4/files/etc/motd.sipb-xen	(revision 360)
+++ package_tags/sipb-xen-console/4/files/etc/motd.sipb-xen	(revision 360)
@@ -0,0 +1,3 @@
+
+Type Ctrl-] to escape from the console
+
Index: package_tags/sipb-xen-console/4/files/etc/nscd.conf.sipb-xen
===================================================================
--- package_tags/sipb-xen-console/4/files/etc/nscd.conf.sipb-xen	(revision 360)
+++ package_tags/sipb-xen-console/4/files/etc/nscd.conf.sipb-xen	(revision 360)
@@ -0,0 +1,67 @@
+#
+# /etc/nscd.conf
+#
+# An example Name Service Cache config file.  This file is needed by nscd.
+#
+# Legal entries are:
+#
+#	logfile			<file>
+#	debug-level		<level>
+#	threads			<initial #threads to use>
+#	max-threads		<maximum #threads to use>
+#	server-user             <user to run server as instead of root>
+#		server-user is ignored if nscd is started with -S parameters
+#       stat-user               <user who is allowed to request statistics>
+#	reload-count		unlimited|<number>
+#	paranoia		<yes|no>
+#	restart-interval	<time in seconds>
+#
+#       enable-cache		<service> <yes|no>
+#	positive-time-to-live	<service> <time in seconds>
+#	negative-time-to-live   <service> <time in seconds>
+#       suggested-size		<service> <prime number>
+#	check-files		<service> <yes|no>
+#	persistent		<service> <yes|no>
+#	shared			<service> <yes|no>
+#
+# Currently supported cache names (services): passwd, group, hosts
+#
+
+
+#	logfile			/var/log/nscd.log
+#	threads			6
+#	max-threads		128
+#	server-user		nobody
+#	stat-user		somebody
+	debug-level		0
+#	reload-count		5
+	paranoia		no
+#	restart-interval	3600
+
+	enable-cache		passwd		yes
+	positive-time-to-live	passwd		600
+#	negative-time-to-live	passwd		20
+	negative-time-to-live	passwd		3
+	suggested-size		passwd		211
+	check-files		passwd		yes
+#	persistent		passwd		yes
+	persistent		passwd		no
+	shared			passwd		yes
+
+	enable-cache		group		yes
+	positive-time-to-live	group		3600
+#	negative-time-to-live	group		60
+	negative-time-to-live	group		3
+	suggested-size		group		211
+	check-files		group		yes
+#	persistent		group		yes
+	persistent		group		no
+	shared			group		yes
+
+	enable-cache		hosts		yes
+	positive-time-to-live	hosts		3600
+	negative-time-to-live	hosts		20
+	suggested-size		hosts		211
+	check-files		hosts		yes
+	persistent		hosts		yes
+	shared			hosts		yes
Index: package_tags/sipb-xen-console/4/files/etc/nss-pgsql.conf
===================================================================
--- package_tags/sipb-xen-console/4/files/etc/nss-pgsql.conf	(revision 360)
+++ package_tags/sipb-xen-console/4/files/etc/nss-pgsql.conf	(revision 360)
@@ -0,0 +1,18 @@
+# example configfile for PostgreSQL NSS module
+
+# these are entries as used with the BOFHMS tool (sf.net/projects/bofhms)
+host		= sipb-xen-dev
+port		= 5432
+database	= sipb_xen
+login		= sipb-xen
+
+querypasswd = SELECT name, NULL, machine_id + 1000 as uid, machine_id + 1000 as gid, '', '/consolefs/'|| name, '/usr/bin/sipb-xen-consolesh' FROM machines
+querygroup = SELECT name, NULL, machine_id + 1000 as gid FROM machines
+querymembers = SELECT name FROM machines WHERE 1000 + machine_id = %d
+queryids = SELECT 1000 + machine_id AS gid FROM machines LIMIT 0
+
+passwd_name = name
+passwd_uid = 1000 + machine_id
+
+group_name = name
+group_gid = 1000 + machine_id
Index: package_tags/sipb-xen-console/4/files/etc/nsswitch.conf.sipb-xen
===================================================================
--- package_tags/sipb-xen-console/4/files/etc/nsswitch.conf.sipb-xen	(revision 360)
+++ package_tags/sipb-xen-console/4/files/etc/nsswitch.conf.sipb-xen	(revision 360)
@@ -0,0 +1,19 @@
+# /etc/nsswitch.conf
+#
+# Example configuration of GNU Name Service Switch functionality.
+# If you have the `glibc-doc-reference' and `info' packages installed, try:
+# `info libc "Name Service Switch"' for information about this file.
+
+passwd:         compat pgsql
+group:          compat pgsql
+shadow:         compat
+
+hosts:          files dns
+networks:       files
+
+protocols:      db files
+services:       db files
+ethers:         db files
+rpc:            db files
+
+netgroup:       nis
Index: package_tags/sipb-xen-console/4/files/etc/ssh/ssh_config.sipb-xen
===================================================================
--- package_tags/sipb-xen-console/4/files/etc/ssh/ssh_config.sipb-xen	(revision 360)
+++ package_tags/sipb-xen-console/4/files/etc/ssh/ssh_config.sipb-xen	(revision 360)
@@ -0,0 +1,47 @@
+
+# This is the ssh client system-wide configuration file.  See
+# ssh_config(5) for more information.  This file provides defaults for
+# users, and the values can be changed in per-user configuration files
+# or on the command line.
+
+# Configuration data is parsed as follows:
+#  1. command line options
+#  2. user-specific file
+#  3. system-wide file
+# Any configuration value is only changed the first time it is set.
+# Thus, host-specific definitions should be at the beginning of the
+# configuration file, and defaults at the end.
+
+# Site-wide defaults for some commonly used options.  For a comprehensive
+# list of available options, their meanings and defaults, please see the
+# ssh_config(5) man page.
+
+Host *
+   SendEnv VM_NAME
+#   ForwardAgent no
+#   ForwardX11 no
+#   ForwardX11Trusted yes
+#   RhostsRSAAuthentication no
+#   RSAAuthentication yes
+#   PasswordAuthentication yes
+#   HostbasedAuthentication no
+#   BatchMode no
+#   CheckHostIP yes
+#   AddressFamily any
+#   ConnectTimeout 0
+#   StrictHostKeyChecking ask
+#   IdentityFile ~/.ssh/identity
+#   IdentityFile ~/.ssh/id_rsa
+#   IdentityFile ~/.ssh/id_dsa
+#   Port 22
+#   Protocol 2,1
+#   Cipher 3des
+#   Ciphers aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour,aes192-cbc,aes256-cbc
+#   EscapeChar ~
+#   Tunnel no
+#   TunnelDevice any:any
+#   PermitLocalCommand no
+    SendEnv LANG LC_*
+    HashKnownHosts yes
+    GSSAPIAuthentication yes
+    GSSAPIDelegateCredentials no
Index: package_tags/sipb-xen-console/4/files/etc/ssh/ssh_known_hosts
===================================================================
--- package_tags/sipb-xen-console/4/files/etc/ssh/ssh_known_hosts	(revision 360)
+++ package_tags/sipb-xen-console/4/files/etc/ssh/ssh_known_hosts	(revision 360)
@@ -0,0 +1,3 @@
+|1|CoekhjakJDYiibQ38vZna+XKwCg=|Ts2GavZxl8KVEl++tnJnjqfn84s= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAsoOOazVHn04z6s+kQnoFcw9fv7dGB9s/9H1QygYW9QAbvklWx0q4J8KGTATXCFwjooLNqjHYONOQ8x0h1fZPDmhdoHk24wH/EBUAAyhtrwTMpsgfqZwG7yuRpcbO382F3wRv6CIRYZ6hyIlm0Zt3680mO/u7l2wAFoMTyYwSdZ8Gl9p5Ay750TFCZoEI/Z4EQY5lGPHrHIXN+uo0Yus//AmWIzY9y3TSKabHz77rPGIzJc8Y4XjDqA7LzXCY+KGw2Of059AseVHNTCMo6KzVIKgdZoRBtiY7fD1l7ystgKL6lGJr4C1UyWoM41EVkDqsRJZ70C4Elcr1x/MrQFLEgQ==
+|1|SFl+Ci6EXZcVvxvxDm4Cf85nGho=|InwYz5wWUf/NRbBQRa/TO3Lm2uQ= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAsoOOazVHn04z6s+kQnoFcw9fv7dGB9s/9H1QygYW9QAbvklWx0q4J8KGTATXCFwjooLNqjHYONOQ8x0h1fZPDmhdoHk24wH/EBUAAyhtrwTMpsgfqZwG7yuRpcbO382F3wRv6CIRYZ6hyIlm0Zt3680mO/u7l2wAFoMTyYwSdZ8Gl9p5Ay750TFCZoEI/Z4EQY5lGPHrHIXN+uo0Yus//AmWIzY9y3TSKabHz77rPGIzJc8Y4XjDqA7LzXCY+KGw2Of059AseVHNTCMo6KzVIKgdZoRBtiY7fD1l7ystgKL6lGJr4C1UyWoM41EVkDqsRJZ70C4Elcr1x/MrQFLEgQ==
+|1|52lp5FTRtu4Fyk8GvC3mH2idB+0=|fGJ+LwWltfUP9kC1fiMfJO5XrVk= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAsoOOazVHn04z6s+kQnoFcw9fv7dGB9s/9H1QygYW9QAbvklWx0q4J8KGTATXCFwjooLNqjHYONOQ8x0h1fZPDmhdoHk24wH/EBUAAyhtrwTMpsgfqZwG7yuRpcbO382F3wRv6CIRYZ6hyIlm0Zt3680mO/u7l2wAFoMTyYwSdZ8Gl9p5Ay750TFCZoEI/Z4EQY5lGPHrHIXN+uo0Yus//AmWIzY9y3TSKabHz77rPGIzJc8Y4XjDqA7LzXCY+KGw2Of059AseVHNTCMo6KzVIKgdZoRBtiY7fD1l7ystgKL6lGJr4C1UyWoM41EVkDqsRJZ70C4Elcr1x/MrQFLEgQ==
Index: package_tags/sipb-xen-console/4/files/usr/bin/sipb-xen-consolefs
===================================================================
--- package_tags/sipb-xen-console/4/files/usr/bin/sipb-xen-consolefs	(revision 360)
+++ package_tags/sipb-xen-console/4/files/usr/bin/sipb-xen-consolefs	(revision 360)
@@ -0,0 +1,248 @@
+#!/usr/bin/python
+
+import fuse
+from fuse import Fuse
+
+from time import time
+
+import stat	# for file properties
+import os	  # for filesystem modes (O_RDONLY, etc)
+import errno   # for error number codes (ENOENT, etc)
+			   # - note: these must be returned as negatives
+
+from syslog import *
+
+import sipb_xen_database
+
+fuse.fuse_python_api = (0, 2)
+
+realpath = "/home/machines/"
+
+def getDepth(path):
+	"""
+	Return the depth of a given path, zero-based from root ('/')
+	"""
+	if path == '/':
+		return 0
+	else:
+		return path.count('/')
+
+def getParts(path):
+	"""
+	Return the slash-separated parts of a given path as a list
+	"""
+	if path == '/':
+		return ['/']
+	else:
+		# [1:] because otherwise you get an empty list element from the
+		# initial '/'
+		return path[1:].split('/')
+
+class MyStat:
+	def __init__(self):
+		self.st_mode = 0
+		self.st_ino = 0
+		self.st_dev = 0
+		self.st_nlink = 0
+		self.st_uid = 0
+		self.st_gid = 0
+		self.st_size = 0
+		self.st_atime = 0
+		self.st_mtime = 0
+		self.st_ctime = 0
+	
+	def toTuple(self):
+		return (self.st_mode, self.st_ino, self.st_dev, self.st_nlink, self.st_uid, self.st_gid, self.st_size, self.st_atime, self.st_mtime, self.st_ctime)
+
+class ConsoleFS(Fuse):
+	"""
+	ConsoleFS creates a series of subdirectories each mirroring the same real
+	directory, except for a single file - the .k5login - which is dynamically
+	generated for each subdirectory
+	
+	This filesystem only implements the getattr, getdir, read, and readlink
+	calls, beacuse this is a read-only filesystem
+	"""
+	
+	def __init__(self, *args, **kw):
+		"""Initialize the filesystem and set it to allow_other access besides
+		the user who mounts the filesystem (i.e. root)
+		"""
+		Fuse.__init__(self, *args, **kw)
+		self.lasttime = time()
+		self.allow_other = 1
+		
+		openlog('sipb-xen-consolefs ', LOG_PID, LOG_DAEMON)
+		
+		syslog(LOG_DEBUG, 'Init complete.')
+	
+	def mirrorPath(self, path):
+		"""Translate a virtual path to its real path counterpart"""
+		return realpath + "/".join(getParts(path)[1:])
+	
+	def getMachines(self):
+		"""Get the list of VMs in the database, clearing the cache if it's 
+		older than 15 seconds"""
+		if time() - self.lasttime > 15:
+			self.lasttime = time()
+			sipb_xen_database.clear_cache()
+		return [machine.name for machine in sipb_xen_database.Machine.select()]
+	
+	def getUid(self, machine_name):
+		"""Calculate the UID of a machine-account, which is just machine_id+1000
+		"""
+		return sipb_xen_database.Machine.get_by(name=machine_name).machine_id + 1000
+	
+	def getK5login(self, machine_name):
+		"""Build the ACL for a machine and turn it into a .k5login file
+		"""
+		machine = sipb_xen_database.Machine.get_by(name=machine_name)
+		users = [acl.user for acl in machine.acl]
+		return "\n".join(map(self.userToPrinc, users) + [''])
+	
+	def userToPrinc(self, user):
+		"""Convert Kerberos v4-style names to v5-style and append a default
+		realm if none is specified
+		"""
+		if '@' in user:
+			(princ, realm) = user.split('@')
+		else:
+			princ = user
+			realm = "ATHENA.MIT.EDU"
+		
+		return princ.replace('.', '/') + '@' + realm
+	
+	def getattr(self, path):
+		"""
+		- st_mode (protection bits)
+		- st_ino (inode number)
+		- st_dev (device)
+		- st_nlink (number of hard links)
+		- st_uid (user ID of owner)
+		- st_gid (group ID of owner)
+		- st_size (size of file, in bytes)
+		- st_atime (time of most recent access)
+		- st_mtime (time of most recent content modification)
+		- st_ctime (platform dependent; time of most recent metadata change on Unix,
+					or the time of creation on Windows).
+		"""
+		
+		syslog(LOG_DEBUG, "*** getattr: " + path)
+		
+		depth = getDepth(path)
+		parts = getParts(path)
+		
+		st = MyStat()
+		# / is a directory
+		if path == '/':
+			st.st_mode = stat.S_IFDIR | 0755
+			st.st_nlink = 2
+		# /foo is a directory if foo is a machine - otherwise it doesn't exist
+		elif depth == 1:
+			if parts[-1] in self.getMachines():
+				st.st_mode = stat.S_IFDIR | 0755
+				st.st_nlink = 2
+				# Homedirs should be owned by the user whose homedir it is
+				st.st_uid = st.st_gid = self.getUid(parts[0])
+			else:
+				return -errno.ENOENT
+		# Catch the .k5login file, because it's a special case
+		elif depth == 2 and parts[-1] == '.k5login':
+			st.st_mode = stat.S_IFREG | 0444
+			st.st_nlink = 1
+			st.st_size = len(self.getK5login(parts[0]))
+			# The .k5login file should be owned by the user whose homedir it is
+			st.st_uid = st.st_gid = self.getUid(parts[0])
+		# For anything else, we get the mirror path and call out to the OS
+		else:
+			stats = list(os.lstat(self.mirrorPath(path)))
+			# Shadow the UID and GID from the original homedir
+			stats[4:6] = [self.getUid(parts[0])] * 2
+			return tuple(stats)
+		return st.toTuple()
+	
+	# This call isn't actually used in the version of Fuse on console, but we
+	# wanted to leave it implemented to ease the transition in the future
+	def readdir(self, path, offset):
+		"""Return a generator with the listing for a directory
+		"""
+		syslog(LOG_DEBUG, '*** readdir %s %s' % (path, offset))
+		for (value, zero) in self.getdir(path):
+			yield fuse.Direntry(value)
+	
+	def getdir(self, path):
+		"""Return a list of tuples of the form (item, 0) with the contents of
+		the directory path
+		
+		Fuse doesn't add '.' or '..' on its own, so we have to
+		"""
+		syslog(LOG_DEBUG, '*** getdir %s' % path)
+		
+		# '/' contains a directory for each machine
+		if path == '/':
+			contents = self.getMachines()
+		# The directory for each machine contains the same files as the realpath
+		# but also the .k5login
+		#
+		# The list is converted to a set so that we can handle the case where 
+		# there is already a .k5login in the realpath gracefully
+		elif getDepth(path) == 1:
+			contents = set(os.listdir(self.mirrorPath(path)) + ['.k5login'])
+		# If it's not the root of the homedir, just pass the call onto the OS
+		# for realpath
+		else:
+			contents = os.listdir(self.mirrorPath(path))
+		# Format the list the way that Fuse wants it - and don't forget to add
+		# '.' and '..'
+		return [(i, 0) for i in (list(contents) + ['.', '..'])]
+	
+	def read(self, path, length, offset):
+		"""Read length bytes starting at offset of path. In most cases, this
+		just gets passed on to the OS
+		"""
+		syslog(LOG_DEBUG, '*** read %s %s %s' % (path, length, offset))
+		
+		parts = getParts(path)
+		
+		# If the depth is less than 2, then either it's a directory or the file
+		# doesn't exist
+		# (realistically this doesn't appear to ever happen)
+		if getDepth(path) < 2:
+			return -errno.ENOENT
+		# If we're asking for a real .k5login file, then create it and return
+		# the snippet requested
+		elif parts[1:] == ['.k5login']:
+			if parts[0] not in self.getMachines():
+				return -errno.ENOENT
+			else:
+				return self.getK5login(parts[0])[offset:length + offset]
+		# Otherwise, pass the call onto the OS
+		# (note that the file will get closed when this call returns and the
+		# file descriptor goes out of scope)
+		else:
+			fname = self.mirrorPath(path)
+			if not os.path.isfile(fname):
+				return -errno.ENOENT
+			else:
+				f = open(fname)
+				f.seek(offset)
+				return f.read(length)
+	
+	def readlink(self, path):
+		syslog(LOG_DEBUG, '*** readlink %s' % path)
+		
+		# There aren't any symlinks here
+		if getDepth(path) < 2:
+			return -errno.ENOENT
+		# But there might be here
+		else:
+			return os.readlink(self.mirrorPath(path))
+
+if __name__ == '__main__':
+	sipb_xen_database.connect('postgres://sipb-xen@sipb-xen-dev.mit.edu/sipb_xen')
+	usage="""
+ConsoleFS [mount_path]
+"""
+	server = ConsoleFS()
+	server.flags = 0
+	server.main()
Index: package_tags/sipb-xen-console/4/files/usr/bin/sipb-xen-consolesh
===================================================================
--- package_tags/sipb-xen-console/4/files/usr/bin/sipb-xen-consolesh	(revision 360)
+++ package_tags/sipb-xen-console/4/files/usr/bin/sipb-xen-consolesh	(revision 360)
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+export VM_NAME="d_$USER"
+ssh console@black-mesa
