Table of Contents
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:
Several common utilities like cat, ls and so on.
Startup scripts that automatically check and mount filesystems.
Graceful shutdown capability.
Support for multiple users and virtual terminals.
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 /usr hierarchy because of space constraints.) Compared to FHS requirement, the only files missing are a few commands in the /bin directory. Specifically, the root disk lacks the following commands:
more
ps
sed
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.
So in order to finish up this phase of the project, we need to accomplish the following goals:
Add the more, ps and sed commands.
Install the optional ed editor.
There is a more 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 more 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 more command we will have to get creative.
The more command is used to display a file page by page. It's a little like having a cat command that pauses every twenty-five lines. The basic logic is outlined below.
Read one line of the file.
Display the line on the screen.
If 25 lines have been displayed, pause.
Loop and do it again.
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 more does. Given this simple program logic, it should not be hard to put together a short shell script that emulates the basic functionality of more. The BASH(1) manpage and Adv-BASH-Scripting-Guide will serve as references.
The more script will need access to device files that are not on the root disk yet. Specifically more needs to have stdin, stdout and stderr, but while we are at it we should check for any other missing /dev files. The Linux Standard Base requires null, zero and tty to be present in the /dev directory. Files for null and tty already exist from previous phases of the project, but we still need /dev/zero. We can refer to devices.txt in the Linux source code Documentation directory for major and minor numbers.
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 GNU FTP server. 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 http://freshmeat.net and search for "procps" in projects.
Both "sed" and "ed" packages feature GNU's familiar configure script and are therefore very easy to build. There is no configure script for "procps" but this does not make things too difficult. We can just read the package's README 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 SHARED=0 makes libproc an integrated part of ps rather than a separate, shared library.
Create the following script with a text editor and save it as ~/staging/bin/more.sh
#!/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.shCreate a symbolic link for more
bash# ln -s more.sh ~/staging/bin/more
bash# ln -s /proc/self/fd ~/staging/dev/fd bash# ln -s fd/0 ~/staging/dev/stdin bash# ln -s fd/1 ~/staging/dev/stdout bash# ln -s fd/2 ~/staging/dev/stderr bash# mknod -m644 ~/staging/dev/zero c 1 5
Get the latest procps source package from http://procps.sourceforge.net/
bash# cd /usr/src/procps-3.2.3 bash# make SHARED=0 CC="gcc -mcpu=i386" bash# cd ps bash# cp ps ~/staging/bin
Download GNU's sed from ftp://ftp.gnu.org/gnu/sed/
bash# cd /usr/src/sed-4.1.2 bash# export CC="gcc -mcpu=i386" bash# ./configure --host=i386-pc-linux-gnu bash# make bash# cd sed bash# cp sed ~/staging/bin
The ed package also comes from GNU at ftp://ftp.gnu.org/gnu/ed/
bash# cd /usr/src/ed-0.2 bash# ./configure --host=i386-pc-linux-gnu bash# make bash# cp ed ~/staging/bin
bash# chown 0:0 ~/staging/bin/* bash# chmod -R 755 ~/staging/bin bash# chmod 4750 ~/staging/bin/su
bash# cd / bash# dd if=/dev/zero of=/dev/ram7 bs=1k count=4096 bash# mke2fs -m0 /dev/ram7 4096 bash# mount /dev/ram7 /mnt bash# cp -dpR ~/staging/* /mnt bash# umount /dev/ram7 bash# dd if=/dev/ram7 of=~/phase7-image bs=1k bash# gzip -9 ~/phase7-image
Display kernel messages by piping the output of dmesg to more.
bash# dmesg | more
Examine the local_fs script by using more with a command-line argument.
bash# more /etc/init.d/local_fs
Display processes for the user currently logged in.
bash# ps
Display all available information about all running processes.
bash# ps -ef
Use sed to display an alternate version of /etc/passwd.
bash# sed -e "s/Legacy/Old School/" /etc/passwd
Verify that sed did not make the changes permanent.
bash# cat /etc/passwd
Use ed to change properties on the "daemon" user.
bash# ed -p* ed* r /etc/passwd ed* %p ed* /daemon/s/Legacy/Old School/ ed* %p ed* w ed* q
Verify that the changes are permanent (at least until the system is restarted.)
bash# cat /etc/passwd