Chapter 8. Filling in the Gaps

Table of Contents

1. Analysis
2. Design
2.1. more
2.2. More device files
2.3. ps, sed & ed
3. Construction
3.1. Write a "more" script
3.2. Create additional device files
3.3. Install ps
3.4. Install sed
3.5. Install ed
3.6. Strip binaries to save space
3.7. Ensure proper permissions
3.8. Create the root disk image
3.9. Copy the image to diskette
4. Implementation
4.1. System startup
4.2. Test the "more" script
4.3. Use ps to show running processes
4.4. Run a simple sed script
4.5. Test the "ed" editor
4.6. System shutdown

1. Analysis

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.

2. Design

2.1. more

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.

2.2. More device files

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.

2.3. ps, sed & ed

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.

3. Construction

3.1. Write a "more" script

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.sh

Create a symbolic link for more

bash# ln -s more.sh ~/staging/bin/more

3.2. Create additional device files

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

3.3. Install ps

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

3.4. Install sed

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

3.5. Install ed

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

3.6. Strip binaries to save space

bash# strip ~/staging/bin/*

3.7. Ensure proper permissions

bash# chown 0:0 ~/staging/bin/*
bash# chmod -R 755 ~/staging/bin
bash# chmod 4750 ~/staging/bin/su

3.8. Create the root disk image

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

3.9. Copy the image to diskette

Insert the diskette labeled "root disk" into drive fd0.

bash# dd if=~/phase7-image.gz of=/dev/fd0 bs=1k

4. Implementation

4.1. System startup

Boot from the diskset in the usual way and log in as root.

4.2. Test the "more" script

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

4.3. Use ps to show running processes

Display processes for the user currently logged in.

bash# ps

Display all available information about all running processes.

bash# ps -ef

4.4. Run a simple sed script

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

4.5. Test the "ed" editor

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

4.6. System shutdown

Bring the system down gracefully with the shutdown command.