packaging improved

simplified use of uml-start script
This commit is contained in:
lars 2006-11-22 15:21:21 +00:00
parent 855bf4742c
commit a66e5d3512
24 changed files with 380 additions and 100 deletions

View file

@ -29,22 +29,38 @@ build:
install: $(BUILD_DIR)-stamp
## programs
$(INSTALL) -d -m 755 $(LIB_DIR)
$(INSTALL) -c -m 755 bin/*.py $(LIB_DIR)/
$(INSTALL) -c -m 755 bin/*.sh $(LIB_DIR)/
## language files
$(INSTALL) -d -m 755 $(SHARE_DIR)/lang
$(INSTALL) -c -m 644 lang/* $(SHARE_DIR)/lang/
## template files
$(INSTALL) -d -m 755 $(SHARE_DIR)/templates
$(INSTALL) -c -m 644 templates/*.cs $(SHARE_DIR)/templates
## html data
$(INSTALL) -d -m 755 $(SHARE_DIR)/html
$(INSTALL) -c -m 644 www-data/*.css $(SHARE_DIR)/html/
$(INSTALL) -c -m 644 www-data/*.png $(SHARE_DIR)/html/
$(INSTALL) -c -m 644 www-data/*.gif $(SHARE_DIR)/html/
## screenshots
$(INSTALL) -d -m 755 $(SHARE_DIR)/html/screenshots
$(INSTALL) -c -m 644 www-data/screenshots/*.png $(SHARE_DIR)/html/screenshots/
$(INSTALL) -d -m 755 $(DOC_DIR)/html/en
$(INSTALL) -d -m 755 $(DOC_DIR)/html/de
$(INSTALL) -c -m 644 doc/html/en/* $(DOC_DIR)/html/en/
$(INSTALL) -c -m 644 doc/html/de/* $(DOC_DIR)/html/de/
## documentation files (html)
ls doc/html | while read lang ;\
do test -d "doc/html/$$lang" && \
$(INSTALL) -d -m 755 "$(DOC_DIR)/html/$$lang" && \
$(INSTALL) -c -m 644 "doc/html/$$lang"/* "$(DOC_DIR)/html/$$lang/" ;\
done; true
## configuration examples
$(INSTALL) -d -m 755 $(DOC_DIR)/conf-examples
$(INSTALL) -c -m 644 conf-examples/* $(DOC_DIR)/conf-examples/
## plugins
$(INSTALL) -d -m 755 $(SHARE_DIR)/plugins
for e in plugins/*; do cp -r "$$e" "$(SHARE_DIR)/plugins"; done
## event scripts
$(INSTALL) -c -m 644 hook-scripts/README $(DOC_DIR)/README.events
clean:

View file

@ -146,7 +146,7 @@ class CryptoBoxPlugin:
if self.cbox.prefs.pluginConf[self.getName()]["rank"] is None:
return self.rank
return int(self.cbox.prefs.pluginConf[self.getName()]["rank"])
except KeyError, TypeError:
except (KeyError, TypeError):
return self.rank

View file

@ -141,7 +141,7 @@ def isPartOfBlockDevice(parent, subdevice):
if (str(par_major), str(par_minor)) == tuple([e for e in file(blpath)][0].strip().split(":",1)):
parent_path = os.path.join(root, bldev)
break
except IndexError, OSError:
except (IndexError, OSError):
pass
else:
## no block device with this major/minor combination found below '/sys/block'
@ -153,7 +153,7 @@ def isPartOfBlockDevice(parent, subdevice):
if (str(sub_major), str(sub_minor)) == tuple([e for e in file(subblpath)][0].strip().split(":",1)):
## the name of the subdevice node is not important - we found it!
return True
except IndexError, OSError:
except (IndexError, OSError):
pass
return False

View file

@ -1,6 +1,7 @@
#!/usr/bin/python2.4
import os
import WebInterfaceSites
from CryptoBoxExceptions import *
import sys
try:
@ -9,11 +10,21 @@ except:
print "Could not import the cherrypy module! Try 'apt-get install python-cherrypy'."
sys.exit(1)
## TODO: it should be possible to override this via commandline arguments
PID_FILE = '/var/run/cryptobox/webserver.pid'
class CryptoBoxWebserver:
'''this class starts the cherryp webserver and serves the single sites'''
def __init__(self):
cherrypy.root = WebInterfaceSites.WebInterfaceSites()
try:
cherrypy.root = WebInterfaceSites.WebInterfaceSites()
except (CBConfigError,CBEnvironmentError), errMsg:
sys.stderr.write("The CryptoBox is misconfigured - please fix it!\n")
sys.stderr.write("%s\n" % str(errMsg))
sys.exit(1)
#expose static content:
#I currently have no idea how to cleanly extract the stylesheet path from
#the config object without an extra CryptoBox.CryptoBoxProps instance.
@ -24,15 +35,76 @@ class CryptoBoxWebserver:
cherrypy.config.configMap.update({
"/cryptobox-misc": {
"staticFilter.on" : True,
"staticFilter.dir": os.path.abspath("../www-data" )}
"staticFilter.dir": os.path.abspath("/usr/share/cryptobox/html" )}
})
def start(self):
# just use this config, when we're started directly
cherrypy.config.update(file = "cryptoboxwebserver.conf")
cherrypy.config.update(file = "/etc/cryptobox/cryptoboxwebserver.conf")
cherrypy.server.start()
if __name__ == "__main__":
cbw = CryptoBoxWebserver()
cbw.start()
def fork_to_background():
## this is just copy'n'pasted from http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/278731
## check the original for exhaustive comments
try:
pid = os.fork()
except OSError, errMsg:
sys.stderr.write("Failed to fork cryptobox daemon process!\n")
sys.stderr.write("%s\n" % errMsg)
sys.exit(1)
if pid == 0: # the first child
os.setsid()
try:
pid = os.fork()
except OSError, errMsg:
sys.stderr.write("Failed to fork second cryptobox daemon process!\n")
sys.stderr.write("%s\n" % errMsg)
sys.exit(1)
if pid == 0: # the second child
os.chdir(os.path.sep)
os.umask(0)
else:
os._exit(0)
else:
os._exit(0)
import resource # Resource usage information.
maxfd = resource.getrlimit(resource.RLIMIT_NOFILE)[1]
if (maxfd == resource.RLIM_INFINITY):
maxfd = 1024
for fd in range(0, maxfd):
try:
os.close(fd)
except OSError: # ERROR, fd wasn't open to begin with (ignored)
pass
os.open(os.devnull, os.O_RDWR) # standard input (0)
os.dup2(0, 1) # standard output (1)
os.dup2(0, 2) # standard error (2)
def write_pid_file(pid_file):
try:
pidf = open(pid_file,"w")
pidf.write(str(os.getpid()))
pidf.close()
except (IOError, OSError), errMsg:
sys.stderr.write("Failed to write pid file (%s): %s\n" % (pid_file, errMsg))
## it is just a warning - no need to break
if __name__ == "__main__":
## TODO: add some argument checking: configFile, daemonMode, ...
cbw = CryptoBoxWebserver()
## run the webserver as a daemon process
fork_to_background()
## write pid file
write_pid_file(PID_FILE)
try:
cbw.start()
except Exceptions, errMsg:
sys.stderr.write("Failed to start the CryptoBox webserver!\n")
sys.stderr.write("%s\n" % str(errMsg))
sys.stderr.write("Check the log file for details.\n")
sys.exit(1)
sys.exit(0)

View file

@ -37,7 +37,7 @@ class WebInterfaceSites:
def __init__(self):
import logging
import logging,sys
self.cbox = CryptoBox.CryptoBoxProps()
self.log = logging.getLogger("CryptoBox")
self.prefs = self.cbox.prefs

View file

@ -1,39 +0,0 @@
#!/bin/sh
CBXSERVER=CryptoBoxWebserver.py
if test -e "./$CBXSERVER"
then CBXPATH=$(pwd)
else CBXPATH=/usr/lib/cryptobox
fi
set -e
case "$1" in
start)
echo -n "Starting $DESC: "
start-stop-daemon --background --chdir "$CBXPATH" --chuid "$RUNAS" --start --quiet --user "$RUNAS" --make-pidfile --pidfile "$PIDFILE" --exec "$DAEMON" -- $DAEMON_OPTS
echo "$NAME."
;;
stop)
echo -n "Stopping $DESC: "
# does the pid file exist?
test ! -e "$PIDFILE" && echo "pid file ($PIDFILE) not found!" && exit 1
# kill all process with the parent pid that we saved before
pkill -f -P "$(cat $PIDFILE)" -u "$RUNAS" && rm "$PIDFILE"
echo "$NAME."
;;
restart )
"$0" stop
"$0" start
;;
*)
echo "Usage: $(basename $0) {start|stop|restart}" >&2
exit 1
;;
esac
exit 0

View file

@ -1,10 +1,17 @@
#!/bin/sh
ROOT_IMG=/home/lars/devel-stuff/devel-chroots/cryptobox.img
ROOT_IMG=$(dirname $0)/cryptobox.img
TEST_IMG=test.img
TEST_SIZE=256
TEST_SIZE=128
MEM_SIZE=128M
if test ! -e "$ROOT_IMG"
then echo "Could not find the cryptobox system image ($ROOT_IMG)"
echo " see stuff/uml-howto.txt for information on how to build a system image"
echo " store (or link) the result as '$ROOT_IMG'"
exit 1
fi
# Preparations:
# echo "tun" >>/etc/modules
# follow the instructions in /usr/share/doc/uml-utilities/README.Debian

View file

@ -0,0 +1,17 @@
# CryptoBox configuration file
#
# the following directives allow you to use the cryptobox web interface behind apache
#
# you need to enable the following modules:
# - proxy
# - headers
# (for debian: run "a2enmod MOD_NAME")
#
# IMPORTANT: for now it does not work! Any comments are appreciated ...
#
<Location /cbox>
ProxyPass http://localhost:8080
ProxyPassReverse http://localhost:8080
RequestHeader set CBOX-Location /cbox
</Location>

View file

@ -0,0 +1,83 @@
[Main]
# comma separated list of possible prefixes for accesible devices
# beware: .e.g "/dev/hd" grants access to _all_ harddisks
AllowedDevices = /dev/loop, /dev/ubdb
# use separate config partition? (1=yes / 0=no)
UseConfigPartition = 1
# the default name prefix of not unnamed containers
DefaultVolumePrefix = "Disk "
# which cipher should cryptsetup-luks use?
#TODO: uml does not support this module - DefaultCipher = aes-cbc-essiv:sha256
DefaultCipher = aes-plain
# label of the configuration partition (you should never change this)
ConfigVolumeLabel = cbox_config
# which plugins should be disabled? (comma seperated list)
#DisabledPlugins = network, shutdown, partition
[Locations]
# where should we mount volumes?
# this directory must be writeable by the cryptobox user (see above)
MountParentDir = /var/cache/cryptobox/mnt
# settings directory: contains name database and plugin configuration
SettingsDir = /var/cache/cryptobox/settings
# where are the clearsilver templates?
TemplateDir = /usr/share/cryptobox/templates
# path to language files
LangDir = /usr/share/cryptobox/lang
# path to documentation files
DocDir = /usr/share/doc/cryptobox/html
# path to the plugin directory
PluginDir = /usr/share/cryptobox/plugins
# path to the hook directory (e.g. containing some scripts)
HookDir = /etc/cryptobox/events.d
[Log]
# possible values are "debug", "info", "warn" and "error" or numbers from
# 0 (debug) to 7 (error)
Level = debug
# where to write the log messages to?
# possible values are: file
# syslog support will be added later
Destination = file
# depending on the choosen destination (see above) you may select
# details. Possible values for the different destinations are:
# file: $FILENAME
# syslog: $LOG_FACILITY
Details = /var/log/cryptobox.log
[WebSettings]
# URL of default stylesheet
Stylesheet = /cryptobox-misc/cryptobox.css
# default language
Language = de
[Programs]
cryptsetup = /sbin/cryptsetup
mkfs-data = /sbin/mkfs.ext3
blkid = /sbin/blkid
blockdev = /sbin/blockdev
mount = /bin/mount
umount = /bin/umount
super = /usr/bin/super
# this is the "program" name as defined in /etc/super.tab
CryptoBoxRootActions = CryptoBoxRootActions

View file

@ -0,0 +1,17 @@
[global]
server.socketPort = 8080
#server.environment = "production"
server.environment = "development"
server.logToScreen = False
server.log_tracebacks = True
server.threadPool = 1
server.reverseDNS = False
server.logFile = "/var/log/cryptoboxwebserver.log"
[/favicon.ico]
static_filter.on = True
# TODO: use live-cd/live-cd-tree.d/var/www/favicon.ico
static_filter.file = "/usr/share/doc/python-cherrypy/cherrypy/favicon.ico"
[/test_stream]
stream_response = True

1
debian/compat vendored Normal file
View file

@ -0,0 +1 @@
5

7
debian/control vendored
View file

@ -2,13 +2,14 @@ Source: cryptobox
Section: admin
Priority: extra
Maintainer: Lars Kruse <devel@sumpfralle.de>
Build-Depends: debhelper (>>3.0.0), dpatch
Standards-Version: 3.6.2
Build-Depends: debhelper (>= 5.0.37.2), dpatch, python-all-dev (>= 2.4)
Standards-Version: 3.7.2
Package: cryptobox
Architecture: any
Depends: bash (>=2.0), sed (>=4.0), coreutils, grep (>=2.0), httpd-cgi, hashalot, cryptsetup (>=20050111), dmsetup, initscripts, e2fsprogs (>= 1.27), adduser, python (>=2.4), python-clearsilver, super, dosfstools, python-cherrypy, python-confobj
Depends: ${python:Depends}, bash (>=2.0), sed (>=4.0), coreutils, grep (>=2.0), hashalot, cryptsetup (>=20050111), dmsetup, initscripts, e2fsprogs (>= 1.27), adduser, python (>=2.4), python-clearsilver, super, dosfstools, python-cherrypy, python-configobj
Suggests: samba, stunnel, openssl
XB-Python-Version: 2.4
Description: Web interface for an encrypting fileserver
This web interface allows you to manage the encrypted and plaintext
disks of your system. The data is platform independently available

View file

@ -4,8 +4,8 @@
#
# the default setup of the cryptobox is complete inactivity
# set to "1" to turn off the cryptobox - otherwise "0"
# set to "0" to enable the startup of the cryptobox - otherwise "1"
NO_START=1
# the use that should execute the cryptobox
RUNAS=lars
RUNAS=cryptobox

55
debian/cryptobox.init vendored Executable file → Normal file
View file

@ -7,6 +7,16 @@
# see LICENSE file in this package for details
#
### BEGIN INIT INFO
# Provides: cryptobox
# Required-Start: $network $local_fs $remote_fs
# Required-Stop: $network $local_fs $remote_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: start CryptoBox webserver
### END INIT INFO
# read the default setting file, if it exists
[ -e /etc/default/cryptobox ] && source /etc/default/cryptobox
@ -18,7 +28,7 @@ if [ "$NO_START" = "1" ]
then [ $# -eq 0 ] && exit 0
[ "$1" = "status" ] && exit 1
[ "$1" = "stop" ] && exit 0
echo "CryptoBox is disabled by default"
echo "CryptoBox is disabled by default (check /etc/default/cryptobox)"
exit 0
fi
@ -29,39 +39,58 @@ if test -e "./$CBXSERVER"
else CBXPATH=/usr/lib/cryptobox
fi
PIDFILE=/var/run/cryptobox.pid
PIDFILE=/var/run/cryptobox/webserver.pid
DAEMON=/usr/bin/python2.4
DAEMON_OPTS=$CBXPATH/$CBXSERVER
NAME=cryptoboxd
DESC="CryptoBox Daemon (webinterface)"
# check if the package is installed
test -e "$CBXPATH/$CBXSERVER" || exit 0
# include some useful functions to unify our output format
. /lib/lsb/init-functions
case "$1" in
start )
# TODO: mount config dir
# TODO: create certificate
# TODO: run stunnel
# the lines above should go into the live-cd scripts
echo -n "Starting $DESC: "
start-stop-daemon --background --chdir "$CBXPATH" --chuid "$RUNAS" --start --quiet --user "$RUNAS" --make-pidfile --pidfile "$PIDFILE" --exec "$DAEMON" -- $DAEMON_OPTS
echo "$NAME."
test -e "$PIDFILE" && log_warning_msg "CryptoBox seems to running already (pid file exists) - we will try to start it anyway ..."
log_daemon_msg "Starting cryptobox webserver" "$DESC"
if start-stop-daemon \
--chdir "$CBXPATH" --chuid "$RUNAS" --quiet --start \
-oknodo --user "$RUNAS" --pidfile "$PIDFILE" \
--exec "$DAEMON" -- $DAEMON_OPTS
then log_end_msg 0
else log_end_msg 1
exit 1
fi
;;
stop )
echo -n "Stopping $DESC: "
# does the pid file exist?
test ! -e "$PIDFILE" && echo "pid file ($PIDFILE) not found!" && exit 1
# kill all process with the parent pid that we saved before
pkill -f -P "$(cat $PIDFILE)" -u "$RUNAS" && rm "$PIDFILE"
echo "$NAME."
if test ! -e "$PIDFILE"
then log_warning_msg "CryptoBox is not running (no pid file found)"
exit 0
fi
log_daemon_msg "Stopping cryptobox webserver" "$DESC"
if start-stop-daemon --quiet --stop --pidfile "$PIDFILE"
then rm "$PIDFILE"
log_end_msg 0
else log_end_msg 1
exit 1
fi
;;
force-reload | restart )
reload | force-reload | restart )
"$0" stop
sleep 1
"$0" start
;;
* )
echo "invalid action specified - try { start | stop | restart }" >&2
echo "Usage: $0 {start|stop|restart|reload|force-reload}" >&2
exit 1
;;
esac
exit 0

2
debian/dirs vendored
View file

@ -1,6 +1,6 @@
etc/cryptobox
etc/cryptobox/events.d
etc/default
etc/init.d
usr/lib/cryptobox
usr/share/cryptobox
var/cache/cryptobox

68
debian/postinst vendored Executable file → Normal file
View file

@ -1,25 +1,71 @@
#!/bin/sh
LOG_FILE=/var/log/cryptobox.log
WEBLOG_FILE=/var/log/cryptoboxwebserver.log
PID_DIR=/var/run/cryptobox
CRYPTOBOX_USER=cryptobox
USER_HOME=/var/cache/cryptobox
SUPER_FILE=/etc/super.tab
# create mount and config directories with appropriate permissions
test ! -e "$LOG_FILE" && mkdir -p "$(dirname $LOG_FILE)" && touch "$LOG_FILE" && chown "$CRYPTOBOX_USER" "$LOG_FILE"
if getent passwd "$CRYPTOBOX_USER" 2>/dev/null >/dev/null
then # do nothing - the user already exists
true
else # create cryptobox user
create_user_home()
{
# if the user already exists -> do nothing
getent passwd "$CRYPTOBOX_USER" 2>/dev/null >/dev/null && return 0
# create cryptobox user
echo "Creating new user '$CRYPTOBOX_USER' ..."
USER_HOME=/var/cache/cryptobox
adduser --system --group --home "$USER_HOME" cryptobox
mkdir "$USER_HOME/mnt"
adduser --system --group --groups disk --home "$USER_HOME" cryptobox
mkdir -p "$USER_HOME/mnt"
mkdir -p "$USER_HOME/settings"
chown -R ${CRYPTOBOX_USER}: "$USER_HOME"
# only members of the cryptobox group may access the user directory
chmod 750 "$USER_HOME"
fi
}
create_log_file()
{
# create config directories with appropriate permissions
test ! -e "$LOG_FILE" && mkdir -p "$(dirname $LOG_FILE)" && touch "$LOG_FILE" && chown "$CRYPTOBOX_USER" "$LOG_FILE"
test ! -e "$WEBLOG_FILE" && mkdir -p "$(dirname $WEBLOG_FILE)" && touch "$WEBLOG_FILE" && chown "$CRYPTOBOX_USER" "$WEBLOG_FILE"
}
create_add_super_permission()
{
## this will add some lines to the configuration file of 'super'
## do nothing, if there is already a CryptoBox line
grep -q "CRYPTOBOX_MARKER" "$SUPER_FILE" && return 0
echo >>"$SUPER_FILE" "## CRYPTOBOX_MARKER - please do not remove!"
echo >>"$SUPER_FILE" "CryptoBoxRootActions /usr/lib/cryptobox/CryptoBoxRootActions.py $CRYPTOBOX_USER"
}
create_pid_dir()
{
test ! -e "$PID_DIR" && mkdir -p "$PID_DIR" && chown "$CRYPTOBOX_USER" "$PID_DIR"
}
#################### main ######################
case "$1" in
configure)
create_user_home
create_log_file
create_pid_dir
create_add_super_permission
# continue at the end
;;
abort-upgrade|abort-remove|abort-deconfigure)
# nothing to be done
exit 0
;;
*)
echo "postinst called with unknown argument \`$1'" >&2
exit 0
;;
esac
#DEBHELPER#
true
exit 0

33
debian/postrm vendored Executable file → Normal file
View file

@ -1,11 +1,44 @@
#!/bin/sh
LOG_FILE=/var/log/cryptobox.log
WEBLOG_FILE=/var/log/cryptoboxwebserver.log
PID_DIR=/var/run/cryptobox
SUPER_FILE=/etc/super.tab
remove_super_lines()
{
## do nothing, if there is no CryptoBox line
grep -q "CRYPTOBOX_MARKER" "$SUPER_FILE" || return 0
sed -i /CRYPTOBOX_MARKER/d "$SUPER_FILE"
sed -i /CryptoBoxRootActions/d "$SUPER_FILE"
}
remove_log_files()
{
test -e "$LOG_FILE" && rm "$LOG_FILE"
test -e "$LOG_FILE" && rm "$WEBLOG_FILE"
}
remove_pid_dir()
{
test -e "$PID_DIR" && rm -r "$PID_DIR"
}
################## main ###################
if test "$1" = "purge" && getent passwd cryptobox 2>/dev/null >/dev/null \
&& test "$(cd ~cryptobox;pwd)" = /var/cache/cryptobox
then echo "Removing user 'cryptobox' ..."
userdel -r cryptobox
remove_log_files
remove_pid_dir
fi
## always remove the lines from the 'super' configuration file
remove_super_lines
#DEBHELPER#
# return without error

1
debian/pycompat vendored Normal file
View file

@ -0,0 +1 @@
2

14
debian/rules vendored
View file

@ -9,9 +9,6 @@
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
# This is the debhelper compatibility version to use.
export DH_COMPAT=4
# necessary for dpatch
.NOTPARALLEL:
@ -55,7 +52,8 @@ install: build
dh_clean -k
dh_installdirs
$(MAKE) install PREFIX=$(DEB_BUILD_DIR)/usr
install -c -m 644 bin/cryptobox.conf $(DEB_BUILD_DIR)/etc/cryptobox/
install -c -m 644 conf-examples/cryptobox.conf-dist $(DEB_BUILD_DIR)/etc/cryptobox/cryptobox.conf
install -c -m 644 conf-examples/cryptoboxwebserver.conf-dist $(DEB_BUILD_DIR)/etc/cryptobox/cryptoboxwebserver.conf
# Build architecture-independent files here.
@ -68,19 +66,13 @@ binary-arch: build install
dh_installchangelogs
dh_installdocs
dh_installexamples
# dh_install
# dh_installmenu
# dh_installdebconf
# dh_installlogrotate
dh_installlogrotate
dh_installinit
# dh_installcron
dh_installman
dh_link
dh_strip
dh_compress
dh_fixperms
dh_python
# dh_makeshlibs
dh_installdeb
dh_shlibdeps
dh_gencontrol

View file

@ -1,11 +1,11 @@
Hook scripts for CryptoBox events
Event scripts for CryptoBox events
If you want to execute specific actions according to changes of the cryptobox,
then you can just add your own scripts to this directory.
For every supported event of the CryptoBox, all scripts are called with root user
permissions.
The common synopsis for all hook scripts is:
The common synopsis for all event scripts is:
SCRIPTNAME EVENT [[EVENT_INFOS]...]
Supported events:
@ -18,7 +18,7 @@ Supported events:
- mount_dir: mountpoint of the volume
Every hook script has to fulfill the following conditions:
Every event script has to fulfill the following conditions:
- be executable (for the cryptobox user and for root)
- be writeable for root only
- its parent directories must be writeable for root only

View file

@ -340,7 +340,6 @@ class partition(CryptoBoxPlugin.CryptoBoxPlugin):
def __formatPartitions(self, paramParts):
import threading
parts = paramParts[:]
part_num = 1
## maybe a config partition?

5
stuff/uml-howto.txt Normal file
View file

@ -0,0 +1,5 @@
debootstrap etch _builddir
chroot _builddir
sed -i "/respawn:\/sbin\/getty/d" /etc/inittab
echo "0:1235:respawn:/sbin/getty 38400 console linux" >>/etc/inittab