mirror of https://github.com/tLDP/LDP
383 lines
13 KiB
XML
383 lines
13 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
|
<chapter id="phase7">
|
|
<title>Filling in the Gaps</title>
|
|
|
|
<sect1>
|
|
<title>Analysis</title>
|
|
|
|
<para>The root disk has come a long way since its humble beginnings as a
|
|
statically-linked shell. It now shares many features with the popular,
|
|
ready-made distributions. For example it has:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>Several common utilities like <command>cat</command>,
|
|
<command>ls</command> and so on.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Startup scripts that automatically check and mount
|
|
filesystems.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Graceful shutdown capability.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Support for multiple users and virtual terminals.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<para>As a final test, we can put the root disk up against the Filesystem
|
|
Hierarchy Standard (FHS) requirements for the root filesystem. (We will
|
|
ignore anything in the <filename>/usr</filename> hierarchy because of
|
|
space constraints.) Compared to FHS requirement, the only files missing
|
|
are a few commands in the <filename>/bin</filename> directory.
|
|
Specifically, the root disk lacks the following commands:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><command>more</command></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><command>ps</command></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><command>sed</command></para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<para>In addition to the required commands, it might be nice to include
|
|
the "ed" editor listed as an option by the FHS. It is not as robust as vi
|
|
or emacs, but it works and it should fit onto the tiny root
|
|
filesystem.</para>
|
|
|
|
<para>So in order to finish up this phase of the project, we need to
|
|
accomplish the following goals:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>Add the <command>more</command>, <command>ps</command> and
|
|
<command>sed</command> commands.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Install the optional <command>ed</command> editor.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</sect1>
|
|
|
|
<sect1>
|
|
<title>Design</title>
|
|
|
|
<sect2>
|
|
<title>more</title>
|
|
|
|
<para>There is a <command>more</command> command that comes with
|
|
util-linux, but it will not work for this project. The reason is because
|
|
of library dependencies and space constraints. The util-linux supplied
|
|
<command>more</command> needs either the libncurses or libtermcap to
|
|
work and there just is not enough space on the root disk floppy to fit
|
|
everything in. So, in order to have a <command>more</command> command we
|
|
will have to get creative.</para>
|
|
|
|
<para>The <command>more</command> command is used to display a file page
|
|
by page. It's a little like having a <command>cat</command> command that
|
|
pauses every twenty-five lines. The basic logic is outlined
|
|
below.</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>Read one line of the file.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Display the line on the screen.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>If 25 lines have been displayed, pause.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>Loop and do it again.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<para>Of course there are some details left out like what to do if the
|
|
screen dimensions are not what we anticipated, but overall it is a fair
|
|
representation of what <command>more</command> does. Given this simple
|
|
program logic, it should not be hard to put together a short shell
|
|
script that emulates the basic functionality of <command>more</command>.
|
|
The BASH(1) manpage and Adv-BASH-Scripting-Guide will serve as
|
|
references.</para>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>More device files</title>
|
|
|
|
<para>The <command>more</command> script will need access to device
|
|
files that are not on the root disk yet. Specifically
|
|
<command>more</command> needs to have <filename>stdin</filename>,
|
|
<filename>stdout</filename> and <filename>stderr</filename>, but while
|
|
we are at it we should check for any other missing
|
|
<filename>/dev</filename> files. The Linux Standard Base requires
|
|
<filename>null</filename>, <filename>zero</filename> and
|
|
<filename>tty</filename> to be present in the <filename>/dev</filename>
|
|
directory. Files for <filename>null</filename> and
|
|
<filename>tty</filename> already exist from previous phases of the
|
|
project, but we still need <filename>/dev/zero</filename>. We can refer
|
|
to <filename>devices.txt</filename> in the Linux source code
|
|
<filename>Documentation</filename> directory for major and minor
|
|
numbers.</para>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>ps, sed & ed</title>
|
|
|
|
<para>These three packages can be found by using the Internet resources
|
|
we have used before plus one new site. The "sed" and "ed" packages can
|
|
be found at the same place we found BASH, on the <ulink
|
|
url="ftp://ftp.gnu.org">GNU FTP server</ulink>. The procps package shows
|
|
up in an Ibiblio LSM search, but it is an old version. In order to find
|
|
the latest version we can go to the Freshmeat website at <ulink
|
|
url="http://freshmeat.net">http://freshmeat.net</ulink> and search for
|
|
"procps" in projects.</para>
|
|
|
|
<para>Both "sed" and "ed" packages feature GNU's familiar
|
|
<command>configure</command> script and are therefore very easy to
|
|
build. There is no <command>configure</command> script for "procps" but
|
|
this does not make things too difficult. We can just read the package's
|
|
<filename>README</filename> file to find out about how to set various
|
|
configuration options. We can use one of these options to avoid the
|
|
complexity of using and installing libproc. Setting
|
|
<parameter>SHARED=0</parameter> makes <filename>libproc</filename> an
|
|
integrated part of <command>ps</command> rather than a separate, shared
|
|
library.</para>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1>
|
|
<title>Construction</title>
|
|
|
|
<sect2>
|
|
<title>Write a "more" script</title>
|
|
|
|
<para>Create the following script with a text editor and save it as
|
|
<filename>~/staging/bin/more.sh</filename></para>
|
|
|
|
<para><programlisting>#!/bin/sh
|
|
#
|
|
# more.sh - emulates the basic functions of the "more" binary without
|
|
# requiring ncurses or termcap libraries.
|
|
#
|
|
# Assume input is coming from STDIN unless a valid file is given as
|
|
# a command-line argument.
|
|
if [ -f $1 ]; then
|
|
INPUT="$1"
|
|
else
|
|
INPUT="/dev/stdin"
|
|
fi
|
|
#
|
|
# Set IFS to newline only. See BASH(1) manpage for details on IFS.
|
|
IFS=$'\n'
|
|
#
|
|
# If terminal dimensions are not already set as shell variables, take
|
|
# a guess of 80x25.
|
|
if [ "$COLUMNS" = "" ]; then
|
|
let COLUMNS=80;
|
|
fi
|
|
if [ "$LINES" = "" ]; then
|
|
let LINES=25;
|
|
fi
|
|
#
|
|
# Initialize line counter variable
|
|
let LINE_COUNTER=$LINES
|
|
#
|
|
# Read the input file one line at a time and display on STDOUT until
|
|
# the page fills up. Display "Press <Enter>" message on STDERR and wait
|
|
# for keypress from STDERR. Continue until the end of the input file.
|
|
# Any input line greater than $COLUMNS characters in length is wrapped
|
|
# and counts as multiple lines.
|
|
#
|
|
while read -n $COLUMNS LINE_BUFFER; do
|
|
echo "$LINE_BUFFER"
|
|
let LINE_COUNTER=$LINE_COUNTER-1
|
|
if [ $LINE_COUNTER -le 1 ]; then
|
|
echo "Press <ENTER> for next page or <CTRL>+C to quit.">/dev/stderr
|
|
read</dev/stderr
|
|
let LINE_COUNTER=$LINES
|
|
fi
|
|
done<$INPUT
|
|
#
|
|
# end of more.sh</programlisting></para>
|
|
|
|
<para>Create a symbolic link for <filename>more</filename></para>
|
|
|
|
<para><programlisting><prompt>bash#</prompt> ln -s more.sh ~/staging/bin/more</programlisting></para>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Create additional device files</title>
|
|
|
|
<para><programlisting><prompt>bash#</prompt> ln -s /proc/self/fd ~/staging/dev/fd
|
|
<prompt>bash#</prompt> ln -s fd/0 ~/staging/dev/stdin
|
|
<prompt>bash#</prompt> ln -s fd/1 ~/staging/dev/stdout
|
|
<prompt>bash#</prompt> ln -s fd/2 ~/staging/dev/stderr
|
|
bash# mknod -m644 ~/staging/dev/zero c 1 5</programlisting></para>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Install ps</title>
|
|
|
|
<para>Get the latest procps source package from <ulink
|
|
url="http://procps.sourceforge.net/">http://procps.sourceforge.net/</ulink></para>
|
|
|
|
<para><programlisting><prompt>bash#</prompt> cd /usr/src/procps-3.2.3
|
|
<prompt>bash#</prompt> make SHARED=0 CC="gcc -mcpu=i386"
|
|
<prompt>bash#</prompt> cd ps
|
|
<prompt>bash#</prompt> cp ps ~/staging/bin</programlisting></para>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Install sed</title>
|
|
|
|
<para>Download GNU's sed from <ulink
|
|
url="ftp://ftp.gnu.org/gnu/sed/">ftp://ftp.gnu.org/gnu/sed/</ulink></para>
|
|
|
|
<para><programlisting><prompt>bash#</prompt> cd /usr/src/sed-4.1.2
|
|
<prompt>bash#</prompt> export CC="gcc -mcpu=i386"
|
|
<prompt>bash#</prompt> ./configure --host=i386-pc-linux-gnu
|
|
<prompt>bash#</prompt> make
|
|
<prompt>bash#</prompt> cd sed
|
|
<prompt>bash#</prompt> cp sed ~/staging/bin</programlisting></para>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Install ed</title>
|
|
|
|
<para>The ed package also comes from GNU at <ulink
|
|
url="ftp://ftp.gnu.org/gnu/ed/">ftp://ftp.gnu.org/gnu/ed/</ulink></para>
|
|
|
|
<para><programlisting><prompt>bash#</prompt> cd /usr/src/ed-0.2
|
|
<prompt>bash#</prompt> ./configure --host=i386-pc-linux-gnu
|
|
<prompt>bash#</prompt> make
|
|
<prompt>bash#</prompt> cp ed ~/staging/bin</programlisting></para>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Strip binaries to save space</title>
|
|
|
|
<para><programlisting><prompt>bash#</prompt> strip ~/staging/bin/*</programlisting></para>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Ensure proper permissions</title>
|
|
|
|
<para><programlisting><prompt>bash#</prompt> chown 0:0 ~/staging/bin/*
|
|
<prompt>bash#</prompt> chmod -R 755 ~/staging/bin
|
|
<prompt>bash#</prompt> chmod 4750 ~/staging/bin/su</programlisting></para>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Create the root disk image</title>
|
|
|
|
<para><programlisting><prompt>bash#</prompt> cd /
|
|
<prompt>bash#</prompt> dd if=/dev/zero of=/dev/ram7 bs=1k count=4096
|
|
<prompt>bash#</prompt> mke2fs -m0 /dev/ram7 4096
|
|
<prompt>bash#</prompt> mount /dev/ram7 /mnt
|
|
<prompt>bash#</prompt> cp -dpR ~/staging/* /mnt
|
|
<prompt>bash#</prompt> umount /dev/ram7
|
|
<prompt>bash#</prompt> dd if=/dev/ram7 of=~/phase7-image bs=1k
|
|
<prompt>bash#</prompt> gzip -9 ~/phase7-image</programlisting></para>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Copy the image to diskette</title>
|
|
|
|
<para>Insert the diskette labeled "root disk" into drive fd0.</para>
|
|
|
|
<para><programlisting><prompt>bash#</prompt> dd if=~/phase7-image.gz of=/dev/fd0 bs=1k</programlisting></para>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1>
|
|
<title>Implementation</title>
|
|
|
|
<sect2>
|
|
<title>System startup</title>
|
|
|
|
<para>Boot from the diskset in the usual way and log in as root.</para>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Test the "more" script</title>
|
|
|
|
<para>Display kernel messages by piping the output of
|
|
<command>dmesg</command> to <command>more</command>.</para>
|
|
|
|
<para><programlisting><prompt>bash#</prompt> dmesg | more</programlisting></para>
|
|
|
|
<para>Examine the <filename>local_fs</filename> script by using
|
|
<command>more</command> with a command-line argument.</para>
|
|
|
|
<para><programlisting><prompt>bash#</prompt> more /etc/init.d/local_fs</programlisting></para>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Use ps to show running processes</title>
|
|
|
|
<para>Display processes for the user currently logged in.</para>
|
|
|
|
<para><programlisting><prompt>bash#</prompt> ps</programlisting></para>
|
|
|
|
<para>Display all available information about all running
|
|
processes.</para>
|
|
|
|
<para><programlisting><prompt>bash#</prompt> ps -ef</programlisting></para>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Run a simple sed script</title>
|
|
|
|
<para>Use <command>sed</command> to display an alternate version of
|
|
<filename>/etc/passwd</filename>.</para>
|
|
|
|
<para><programlisting><prompt>bash#</prompt> sed -e "s/Legacy/Old School/" /etc/passwd</programlisting></para>
|
|
|
|
<para>Verify that sed did not make the changes permanent.</para>
|
|
|
|
<para><programlisting><prompt>bash#</prompt> cat /etc/passwd</programlisting></para>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Test the "ed" editor</title>
|
|
|
|
<para>Use <command>ed</command> to change properties on the "daemon"
|
|
user.</para>
|
|
|
|
<para><programlisting><prompt>bash#</prompt> ed -p*
|
|
<prompt>ed*</prompt> r /etc/passwd
|
|
<prompt>ed*</prompt> %p
|
|
<prompt>ed*</prompt> /daemon/s/Legacy/Old School/
|
|
<prompt>ed*</prompt> %p
|
|
<prompt>ed*</prompt> w
|
|
<prompt>ed*</prompt> q</programlisting></para>
|
|
|
|
<para>Verify that the changes are permanent (at least until the system
|
|
is restarted.)</para>
|
|
|
|
<para><programlisting><prompt>bash#</prompt> cat /etc/passwd</programlisting></para>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>System shutdown</title>
|
|
|
|
<para>Bring the system down gracefully with the
|
|
<command>shutdown</command> command.</para>
|
|
</sect2>
|
|
</sect1>
|
|
</chapter> |