"How I Did It", by Victor Frankenstein

Notes on Building RWC/LFS

While on academic leave during the Spring semester in 2014, I built an updated Linux distribution for my System Administration course. It is based on Linux From Scratch and Beyond Linux From Scratch, versions 7.4. This page describes the build in all its gory details.

A word about the name: RWC stands for Raymond Walters College, the former name of University of Cincinnati Blue Ash College, where I teach. Raymond Walters was the longest-serving president of the University of Cincinnati, and was a champion of open-access education. It seems fitting to name an open-source software distribution in his honor.

And for those of you curious about the title (borrowed lovingly from Gene Wilder and Mel Brooks): much of the time during this project it did indeed feel like I was creating a monster. There were a few times when I thought it might get the better of me. We shall see.

The build processor was an Athlon XP 1880+, running on a motherboard with a VIA KT266-A chipset and 1 GB RAM. I chose this system as the most primitive one available compatible with the systems in our computer lab; hopefully this choice will permit students to use the distro on systems they have at home. It should run on a Pentium Pro class CPU or higher.

The base system is the RWC Linux distro dated September 4, 2010. The original LFS/BLFS 6.2 build date for this distro was November 8, 2006. When examining the host system requirements in LFS Prologue section vii, I found the following needed to be upgraded:

I did these essentially in the order implied by the LFS build process.

First I set up a simple script to retrieve packages and check their md5sums:

cat > getmd5 << "EOF"
wget "\$1"
f=\$(echo "\$1" | sed -e 's%^.*/%%')
if [ \$(md5sum "\$f" | sed -e 's/ .*$//') != "\$2" ]; then
   echo "\$f" download failed
else
   echo download OK
fi
EOF
chmod 700 getmd5
Note that the root filesystem of the base system is normally mounted read-only. I will omit the necessary remounts in the notes below.

Note too that I typically check the results of regression tests before proceeding with the installs. In cases where unspecified tests were known to fail, and for prohibitively lengthy tests, I elected to skip the tests. In either event, I kept the make output from every package for later reference in case problems crop up, or I need to know where something was installed. I did not keep the build directories; after the install step, they are mostly useless (with the exception of the linux kernel build directory).

Finally, note that while the recommendation is to do the builds as a non-root user, I did not want to pollute the build system with possible user tracks. Therefore everything after the toolbox was done as root.

What follows is a series of drop-down menus, one for each package. By clicking on the menu, you can see the complete set of commands used to build the package. Note that while I followed the LFS/BLFS instructions whenever possible, there were a number of instances where modification was necessary. There are also occasional comments about test results or the like interspersed with the commands.

I did xz and tar next because gawk is released as a .xz file.

Lesson Number 1

Since most of the required updates date from LFS 6.3, and the base system was LFS 6.2, it is clear that minimally one should check the required build software version numbers annually. This could save a significant amount of aggrevation when you need to update a package.

The build was carried out on /dev/hdb1 (30 GB). After moving to the new system, I used a 10 GB partition hdb2 for /var.

The first steps were to create the build filesystems (with destructive bad block checks), and retrieve the packages:

fdisk /dev/hdb
n
p
1
<default>
+30G
n
p
2
<default>
+10G
w
mke2fs -c -c /dev/hdb1
mke2fs -c -c /dev/hdb2
export LFS=/mnt/lfs
mkdir -pv $LFS
mount -t ext2 /dev/hdb1 $LFS
mkdir -v $LFS/sources
chmod -v a+wt $LFS/sources
wget http://www.linuxfromscratch.org/lfs/view/stable/wget-list
wget http://www.linuxfromscratch.org/lfs/view/stable/md5sums
wget -i wget-list -P $LFS/sources
9 packages were unavailable from the sites in wget-list, so I got them manually from the archives. I also installed several BLFS packages during the LFS phase for greater convenience in building the BLFS packages:

LFS builds are split into two major components:

  1. building of a toolbox of all packages necessary for a complete build, using the host system software; and
  2. building of the complete LFS system, using only the toolbox software (and the host system kernel).

The toolbox build was done under the user lfs:

mkdir -v $LFS/tools
ln -sv $LFS/tools /
groupadd lfs
useradd -s /bin/bash -g lfs -m -k /dev/null lfs
passwd lfs
chown -v lfs $LFS/tools
chown -v lfs $LFS/sources
su lfs
A bash build environment was set up:
cat > ~/.bash_profile << "EOF"
exec env -i HOME=$HOME TERM=$TERM PS1='\u:\w\$ ' /bin/bash
EOF
cat > ~/.bashrc << "EOF"
set +h
umask 022
LFS=/mnt/lfs
LC_ALL=POSIX
LFS_TGT=$(uname -m)-lfs-linux-gnu
PATH=/tools/bin:/bin:/usr/bin
export LFS LC_ALL LFS_TGT PATH
EOF
source ~/.bash_profile
cd $LFS/sources
The toolbox build began here; the 2-pass approach for binutils and gcc are explained in LFS section 5.2, "Toolchain Technical Notes". Note the repeated use of the dummy c program to check that everything is where it should be. This bit is vitally important, and one of the many reasons I am deeply indebted to the LFS folks.

Note that I installed the 3.10.10 headers, but eventually used kernel 3.13.3. So far there has been no ill effects from the mismatch, but anytime you upgrade kernels, you should check to make sure the header files are consistent with the ones you have. If not, it's time to do another complete LFS build.

Note that I did not install expect, dejagnu and check in the final system; they are only needed for the toolbox.

After finishing the toolbox, I tarred the output files and backed up the tools directory.

exit
chown -R root:root /mnt/lfs/tools
tar -cf LFS-7.4.chapter.5.out.tar *.out.gz
rm *.out.gz
tar -czf LFS-7.4.chapter.5.tools.tgz ../tools/
chmod 444 LFS-7.4.chapter.5.*

Section 6.3 makes an excellent point: if any of the toolchain packages need to be upgraded to a new minor version, rebuild LFS.

Now begins the actual build. See LFS 7.4 Chapter 6. The build takes place in a chroot environment to minimize pollution of the new system by the old. Note that we are still using the old kernel.

The chroot environment needs the following directories and files:

mkdir -v $LFS/{dev,proc,sys}
mknod -m 600 $LFS/dev/console c 5 1
mknod -m 666 $LFS/dev/null c 1 3

To enter the chroot environment, bind /dev to the chroot filesystem and mount the virtual filesystems there as well. The following sequence needs to be repeated whenever returning to the chroot environment.

export LFS=/mnt/lfs
mount -v --bind /dev $LFS/dev
mount -vt devpts devpts $LFS/dev/pts -o gid=5,mode=620
mount -vt proc proc $LFS/proc
mount -vt sysfs sysfs $LFS/sys
if [ -h $LFS/dev/shm ]; then
  link=$(readlink $LFS/dev/shm)
  mkdir -p $LFS/$link
  mount -vt tmpfs shm $LFS/$link
  unset link
else
  mount -vt tmpfs shm $LFS/dev/shm
fi
chroot "$LFS" /tools/bin/env -i \
    HOME=/root                  \
    TERM="$TERM"                \
    PS1='\u:\w\$ '              \
    PATH=/bin:/usr/bin:/sbin:/usr/sbin:/tools/bin \
    /tools/bin/bash --login +h

When leaving, it is necessary to do the following umounts:

umount /mnt/lfs/dev/pts
umount /mnt/lfs/{dev,proc,sys}

The creation of the filesystem layout is NOT verbatim from the LFS book. I am going to make etc, home, root, run, srv and tmp symbolic links into directories in /var so that I can mount /var from a separate filesystem and keep the root filesystem read-only during normal operation.

*** NB *** ANY modifications to /etc/fstab, /etc/inittab, /etc/sysconfig/rc.site or /etc/rc.d/rcS.d MUST be done to both the / and /var filesystems !!!

During boot, those files are read from the root filesystem, but as soon as /var is mounted, the files on /var are used.

In the following I denote significant differences between the base system and the new build as NEW.

NEW: We now have /run instead of /var/run, and /run/lock instead of /var/lock

install -d /var/{etc,home,root,srv,tmp}
cd /
ln -s var/etc etc
ln -s var/home home
ln -s var/root root
ln -s var/srv srv
ln -s var/tmp tmp
chmod 0750 /var/root
chmod 1777 /var/tmp
mkdir -pv /{bin,boot,etc/{opt,sysconfig},lib,mnt,opt,run}
mkdir -pv /{media/{floppy,cdrom,usbstg},sbin}
mkdir -pv /usr/{,local/}{bin,include,lib,sbin,src}
mkdir -pv /usr/{,local/}share/{doc,info,locale,man}
mkdir -v  /usr/{,local/}share/{misc,terminfo,zoneinfo}
mkdir -pv /usr/{,local/}share/man/man{1..8}
for dir in /usr /usr/local; do
  ln -sv share/{man,doc,info} $dir
done
mkdir -v /var/{log,mail,spool}
ln -sv /run /var/run
ln -sv /run/lock /var/lock
mkdir -pv /var/{opt,cache,lib/{misc,locate},local}
cd ..

Now I am back in sync with LFS Chapter 6. Here we link the toolbox into place and create a few necessary files.

ln -sv /tools/bin/{bash,cat,echo,pwd,stty} /bin
ln -sv /tools/bin/perl /usr/bin
ln -sv /tools/lib/libgcc_s.so{,.1} /usr/lib
ln -sv /tools/lib/libstdc++.so{,.6} /usr/lib
sed 's/tools/usr/' /tools/lib/libstdc++.la > /usr/lib/libstdc++.la
ln -sv bash /bin/sh
ln -sv /proc/self/mounts /etc/mtab
cat > /etc/passwd << "EOF"
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/dev/null:/bin/false
nobody:x:99:99:Unprivileged User:/dev/null:/bin/false
EOF
cat > /etc/group << "EOF"
root:x:0:
bin:x:1:
sys:x:2:
kmem:x:3:
tape:x:4:
tty:x:5:
daemon:x:6:
floppy:x:7:
disk:x:8:
lp:x:9:
dialout:x:10:
audio:x:11:
video:x:12:
utmp:x:13:
usb:x:14:
cdrom:x:15:
mail:x:34:
nogroup:x:99:
EOF
exec /tools/bin/bash --login +h
touch /var/log/{btmp,lastlog,wtmp}
chgrp -v utmp /var/log/lastlog
chmod -v 664  /var/log/lastlog
chmod -v 600  /var/log/btmp
Here begin the "real" builds:

This step is from LFS section 6.10, "Adjusting the Toolchain". After this, all links will take place against the newly-installed C libraries. I've included the commands to check that all is well; all was well.

mv -v /tools/bin/{ld,ld-old}
mv -v /tools/$(gcc -dumpmachine)/bin/{ld,ld-old}
mv -v /tools/bin/{ld-new,ld}
ln -sv /tools/bin/ld /tools/$(gcc -dumpmachine)/bin/ld
gcc -dumpspecs | sed -e 's@/tools@@g'                   \
    -e '/\*startfile_prefix_spec:/{n;s@.*@/usr/lib/ @}' \
    -e '/\*cpp:/{n;s@$@ -isystem /usr/include@}' >      \
    `dirname $(gcc --print-libgcc-file-name)`/specs
echo 'main(){}' > dummy.c
cc dummy.c -v -Wl,--verbose &> dummy.log
readelf -l a.out | grep ': /lib'
grep -o '/usr/lib.*/crt[1in].*succeeded' dummy.log
grep -B1 '^ /usr/include' dummy.log
grep 'SEARCH.*/usr/lib' dummy.log |sed 's|; |\n|g'
grep "/lib.*/libc.so.6 " dummy.log
grep found dummy.log
rm -v dummy.c a.out dummy.log
The remainder of the package builds start here:

NEW: user mailboxes are now in /var/mail, and are now created automatically at useradd time.

Note that from this point on, the chroot environment is entered with the new bash:

export LFS=/mnt/lfs
mount -v --bind /dev $LFS/dev
mount -vt devpts devpts $LFS/dev/pts -o gid=5,mode=620
mount -vt proc proc $LFS/proc
mount -vt sysfs sysfs $LFS/sys
if [ -h $LFS/dev/shm ]; then
  link=$(readlink $LFS/dev/shm)
  mkdir -p $LFS/$link
  mount -vt tmpfs shm $LFS/$link
  unset link
else
  mount -vt tmpfs shm $LFS/dev/shm
fi
chroot "$LFS" /usr/bin/env -i \
    HOME=/root                  \
    TERM="$TERM"                \
    PS1='\u:\w\$ '              \
    PATH=/bin:/usr/bin:/sbin:/usr/sbin:/tools/bin \
    /bin/bash --login +h
Continuing with the actual package builds:

Note that I omitted vlock because it requires PAM, which I did not want to include in the distro.

Note that the kmod man pages were not created because of a dependency on libxslt.

The system log file structure is now:

I did not strip the debugging symbols because they are not loaded automatically at execution time.

Note that at this stage the chroot environment no longer includes the toolbox in its path:

export LFS=/mnt/lfs
mount -v --bind /dev $LFS/dev
mount -vt devpts devpts $LFS/dev/pts -o gid=5,mode=620
mount -vt proc proc $LFS/proc
mount -vt sysfs sysfs $LFS/sys
if [ -h $LFS/dev/shm ]; then
  link=$(readlink $LFS/dev/shm)
  mkdir -p $LFS/$link
  mount -vt tmpfs shm $LFS/$link
  unset link
else
  mount -vt tmpfs shm $LFS/dev/shm
fi
chroot "$LFS" /usr/bin/env -i \
    HOME=/root                  \
    TERM="$TERM"                \
    PS1='\u:\w\$ '              \
    PATH=/bin:/usr/bin:/sbin:/usr/sbin \
    /bin/bash --login
I installed several BLFS packages for convenience before I get Xorg and a browser installed. Most of these are perl modules dependencies for the wget test.

As you might have noticed in the notes above, I originally installed openssl-1.0.1e. However, in early June of 2014, another bug was fixed, so the day it hit the papers I installed openssl-1.0.1h. The notes here reflect that version.

Anyone installing this at home should do this after installing sshd:

echo "PermitRootLogin no" >> etc/ssh/sshd_config
but I need to ssh as root to my students in the lab, so I didn't do it here.

The following commands were used to tar the source tarballs and output files from the build (after removing the toolbox permanently).

rm -rf ../tools
tar -cf LFS-7.4.chapter.6.out.tar *.out.gz
rm *.out.gz
chmod 444 LFS-7.4.chapter.6.out.tar
mv LFS-7.4.chapter.5.out.tar ..
mv LFS-7.4.chapter.5.tools.tgz ..
mv LFS-7.4.chapter.6.out.tar ..
mv getmd5 ..
mv grub-2.00.tar.xz ..
mv lfs-bootscripts-20130821.tar.bz2 ..
mv linux-3.10.10.tar.xz ..
mv md5sums ..
mv wget-list ..
tar -cf ../LFS-7.4.sources.tar *
chmod 444 ../LFS-7.4.sources.tar
rm *
for f in `find ../ -maxdepth 1 -type f`; do mv $f . ; done
The following installs the LFS boot scripts:
tar -xjf lfs-bootscripts-20130821.tar.bz2
cd lfs-bootscripts-20130821
(make install 2>&1 | tee -a ../lfs-bootscripts-20130821.out && exit $PIPESTATUS)
cd ..
gzip lfs-bootscripts-20130821.out
rm -rf lfs-bootscripts-20130821

I had to patch mountfs since / is to remain read-only:

cat > krk.lfs-7.4.mountfs.patch << "EOF"
--- mountfs.lfs 2014-01-21 14:17:04.000000000 -0500
+++ mountfs     2014-01-23 14:46:39.000000000 -0500
@@ -32,9 +32,9 @@
 
 case "${1}" in
    start)
-      log_info_msg "Remounting root file system in read-write mode..."
-      mount -o remount,rw / >/dev/null
-      evaluate_retval
+#      log_info_msg "Remounting root file system in read-write mode..."
+#      mount -o remount,rw / >/dev/null
+#      evaluate_retval
 
       # Remove fsck-related file system watermarks.
       rm -f /fastboot /forcefsck
@@ -55,7 +55,7 @@
       evaluate_retval
 
       # Make sure / is mounted read only (umount bug)
-      mount -o remount,ro /
+#      mount -o remount,ro /
 
       # Make all LVM volume groups unavailable, if appropriate
       # This fails if swap or / are on an LVM partition
EOF
patch -ubz .lfs /etc/rc.d/init.d/mountfs krk.lfs-7.4.mountfs.patch
I wrote the following boot script to handle the mounting of /var. We want to be able to run any given session from RAM disk, a hard drive partition or a flash drive. Once it is installed on a hard drive partition, modify BOTH fstabs to reflect that and the script will automatically mount /var on that partition.
cat > /etc/rc.d/init.d/mountvar << "EOF"
#!/bin/sh
#/etc/rc.d/init.d/mountvar
NORMAL="\\033[0;39m"
QUERY="\\033[1;36m"
ERROR="\e[1;31m"
while ! mountpoint /var >/dev/null; do
    if ! grep /etc/fstab -e '^#/dev/var?' >/dev/null; then
	vardev=$(grep /etc/fstab -e /var | cut -f1 -d' ')
	fsck -a -C -T $vardev
	if [ $? -lt 2 ]; then
	    mount /var
	fi
    else
        echo -en $QUERY
	read -p 'Enter device file for /var (ie., sdb2, or RAM to use a ram disc): ' vardev
        echo -en $NORMAL
	if [ "$vardev" = "RAM" ]; then
	    mke2fs /dev/ram0 >/dev/null
	    vardev=ram0
	fi
	if [ ! -b /dev/$vardev ]; then
	    echo -e $ERROR /dev/$vardev is not a valid block device file $NORMAL
	else
	    mount -t ext2 /dev/$vardev /mnt >/dev/null
	    if [ $? -ne 0 ]; then
		echo -e $ERROR /dev/$vardev does not seem to contain a valid ext2 file system $NORMAL
	    else
		if [ -e /mnt/etc/fstab ]; then
		    umount /mnt
		    fsck -a -C -T /dev/$vardev
		    if [ $? -lt 2 ]; then
			mount -t ext2 /dev/$vardev /var
		    fi
		else
		    cp -a /var/* /mnt/
		    sed -i -e "s%^#/dev/var?%/dev/$vardev%" /mnt/etc/fstab
		    if grep /mnt/etc/fstab -e '^/dev/root' >/dev/null; then
			rootdev=$(cat /proc/cmdline | tr ' ' '\n' | grep -e '^root=' | sed -e 's/root=//')
			sed -i -e "s%^/dev/root%$rootdev%" /mnt/etc/fstab
		    fi
		    umount /mnt
		    mount -t ext2 /dev/$vardev /var
		    rm -f /etc/udev/rules.d/70-persistent-net.rules
		fi
	    fi
	fi
    fi
done
EOF
chmod 754 /etc/rc.d/init.d/mountvar
ln -sf /etc/rc.d/init.d/mountvar /etc/rc.d/rcS.d/S01mountvar
I wrote this boot script to allow at-boot configuration of networking. If any of the four files /etc/sysconfig/network, /etc/hosts, /etc/resolv.conf or /etc/sysconfig/ifconfig.* do not exist, it allows reconfiguration of any or all (by answering "no" to the last question) of them.
cat > /etc/rc.d/init.d/netconfigure << "EOF"
#!/bin/bash
#/etc/rc.d/init.d/netconfigure
NORMAL="\\033[0;39m"
QUERY="\\033[1;36m"
ok=no
if [ -f /etc/sysconfig/network -a -f /etc/hosts -a -n "$(ls /etc/sysconfig/ifconfig.* 2>/dev/null)" ]; then
    ok=yes
fi
while [ "$ok" != "yes" ]; do
    if [ ! -f /etc/sysconfig/network ]; then
        echo -en $QUERY
	read -p 'Enter hostname (ie., ken.local): ' hn
        echo -en $NORMAL
	h=$(echo $hn | sed -e 's/\..*$//')
	echo "HOSTNAME=$h" > /etc/sysconfig/network
        echo -en $QUERY
	read -p 'Enter IP address, DHCP or none: ' ip
        echo -en $NORMAL
    else
	h=$(grep /etc/sysconfig/network -e 'HOSTNAME=' | sed -e 's/HOSTNAME=//')
	hn=$(echo "$h" ".local" | sed -e 's/ //g')
    fi
    if [ ! -f /etc/hosts ]; then
	if [ "$ip" = DHCP -o "$ip" = none ]; then
	    echo "127.0.0.1 $hn $h localhost" > /etc/hosts
	else
	    echo "127.0.0.1 localhost" > /etc/hosts
	    echo "$ip $hn $h" >> /etc/hosts
	fi
    else
	if [ "$ip" != DHCP -a "$ip" != none ]; then
	    ip=$(grep /etc/hosts -e '[0-9]*\.[0-9]*\.[0-9]*\.[0-9]' | 
		grep -ve '127\.0\.0\.1' |
		tr -s ' ' |
		cut -f1 -d' ')
	fi
    fi
    if [ ! -f /etc/sysconfig/ifconfig.eth0 -a "$ip" != none ]; then
	echo "ONBOOT=yes" > /etc/sysconfig/ifconfig.eth0
	echo "IFACE=eth0" >> /etc/sysconfig/ifconfig.eth0
	if [ "$ip" = DHCP ]; then
	    echo "SERVICE=dhclient" >> /etc/sysconfig/ifconfig.eth0
	else
	    echo "SERVICE=ipv4-static" >> /etc/sysconfig/ifconfig.eth0
	    echo "IP=$ip" >> /etc/sysconfig/ifconfig.eth0
            echo -en $QUERY
	    read -p 'Enter IP address of gateway: ' gw
            echo -en $NORMAL
	    echo "GATEWAY=$gw" >> /etc/sysconfig/ifconfig.eth0
            echo -en $QUERY
	    read -p 'Enter number of bits in the network portion of your IP address: ' nm
            echo -en $NORMAL
	    echo "PREFIX=$nm" >> /etc/sysconfig/ifconfig.eth0
            echo -en $QUERY
	    read -p 'Enter broadcast address: ' bc
            echo -en $NORMAL
	    echo "BROADCAST=$bc" >> /etc/sysconfig/ifconfig.eth0
	fi
    fi
    if [ ! -f /etc/resolv.conf -a "$ip" != none -a "$ip" != DHCP ]; then
        echo -en $QUERY
	read -p 'Enter IP address of DNS server: ' dns
        echo -en $NORMAL
	echo "nameserver $dns" > /etc/resolv.conf
    fi
    echo '***** This is your current network configuration: *****'
    echo '   /etc/hosts: '
    cat /etc/hosts
    echo '   /etc/sysconfig/network: ' $(cat /etc/sysconfig/network)
    echo '   /etc/sysconfig/ifconfig.eth0: '
    cat /etc/sysconfig/ifconfig.eth0
    if [ "$ip" != none -a "$ip" != DHCP ]; then
	echo '   /etc/resolv.conf: ' $(cat /etc/resolv.conf)
    fi
    echo -en $QUERY
    read -p 'Enter yes if you are happy with this: ' ok
    echo -en $NORMAL
    ok=$(echo $ok | tr 'A-Z' 'a-z')
    if [ "$ok" != yes ]; then
        rm /etc/hosts
	rm /etc/sysconfig/network
	rm /etc/sysconfig/ifconfig.eth0
	rm /etc/resolv.conf
    fi
done
EOF
chmod 754 /etc/rc.d/init.d/netconfigure
ln -sf /etc/rc.d/init.d/netconfigure /etc/rc.d/rcS.d/S06netconfigure
# this is necessary for netconfigure to run the first time
rm /etc/hosts
I wrote this boot script because udev will rename eth0 for us, but in general we won't know what the name will be until it does it.
cat > /etc/rc.d/init.d/renameth0 << "EOF"
#!/bin/bash
#/etc/rc.d/init.d/renameth0
newname=$(ls -1 /sys/class/net | grep -e en | head -n1)
if [ "$newname" != "eth0" ]; then
    if [ -f /etc/sysconfig/ifconfig.eth0 ]; then
        cp /etc/sysconfig/ifconfig.eth0 /etc/sysconfig/ifconfig.$newname
	mv /etc/sysconfig/ifconfig.eth0 /etc/sysconfig/former.ifconfig.eth0
	sed -i -e "s/eth0/$newname/" /etc/sysconfig/ifconfig.$newname
    fi
fi
EOF
chmod 754 /etc/rc.d/init.d/renameth0
ln -sf /etc/rc.d/init.d/renameth0 /etc/rc.d/rcS.d/S60renameth0
Here I install the boot scripts for the BLFS daemons I have already installed.
tar -xjf blfs-bootscripts-20130908.tar.bz2
cd blfs-bootscripts-20130908
make install-gpm
make install-random
make install-sshd
cd ..
This is our inittab; we will change the default runlevel to 4 once we get to Samba in the System Administration class.
cat > /etc/inittab << "EOF"
# Begin /etc/inittab
id:3:initdefault:
si::sysinit:/etc/rc.d/init.d/rc S
l0:0:wait:/etc/rc.d/init.d/rc 0
l1:S1:wait:/etc/rc.d/init.d/rc 1
l2:2:wait:/etc/rc.d/init.d/rc 2
l3:3:wait:/etc/rc.d/init.d/rc 3
l4:4:wait:/etc/rc.d/init.d/rc 4
l5:5:wait:/etc/rc.d/init.d/rc 5
l6:6:wait:/etc/rc.d/init.d/rc 6
ca:12345:ctrlaltdel:/sbin/shutdown -t1 -a -r now
su:S016:once:/sbin/sulogin
1:2345:respawn:/sbin/agetty --noclear tty1 9600
2:2345:respawn:/sbin/agetty tty2 9600
3:2345:respawn:/sbin/agetty tty3 9600
4:2345:respawn:/sbin/agetty tty4 9600
5:2345:respawn:/sbin/agetty tty5 9600
6:2345:respawn:/sbin/agetty tty6 9600
# End /etc/inittab
EOF
We assume the hardware clock will be the same as the system clock; this is necessary for machines which also run windows.
cat > /etc/sysconfig/clock << "EOF"
# Begin /etc/sysconfig/clock
UTC=0
# Set this to any options you might need to give to hwclock,
# such as machine hardware clock type for Alphas.
CLOCKPARAMS=
# End /etc/sysconfig/clock
EOF
I want the students to see the fsck progress during boot.
sed -i -e 's/#VERBOSE_FSCK=no/VERBOSE_FSCK=yes/' /etc/sysconfig/rc.site
I changed the default LFS inputrc file to get an audible bell.
cat > /etc/inputrc << "EOF"
# Begin /etc/inputrc
# Modified by Chris Lynn 
# Allow the command prompt to wrap to the next line
set horizontal-scroll-mode Off
# Enable 8bit input
set meta-flag On
set input-meta On
# Turns off 8th bit stripping
set convert-meta Off
# Keep the 8th bit for display
set output-meta On
# none, visible or audible
set bell-style audible
# All of the following map the escape sequence of the value
# contained in the 1st argument to the readline specific functions
"\eOd": backward-word
"\eOc": forward-word
# for linux console
"\e[1~": beginning-of-line
"\e[4~": end-of-line
"\e[5~": beginning-of-history
"\e[6~": end-of-history
"\e[3~": delete-char
"\e[2~": quoted-insert
# for xterm
"\eOH": beginning-of-line
"\eOF": end-of-line
# for Konsole
"\e[H": beginning-of-line
"\e[F": end-of-line
# End /etc/inputrc
EOF
Note that /var options are set to noauto; it will be taken care of by mountvar. The commented lines will be modified by the students during installation.
cat > /etc/fstab << "EOF"
# Begin /etc/fstab
# file system  mount-point  type     options             dump  fsck
#                                                              order
/dev/root      /            ext2     ro                   1     1
#/dev/var?      /var         ext2     noauto               0     0
#/dev/????      swap         swap     pri=1                0     0
proc           /proc        proc      nosuid,noexec,nodev 0     0
sysfs          /sys         sysfs     nosuid,noexec,nodev 0     0
devpts         /dev/pts     devpts    gid=5,mode=620      0     0
tmpfs          /run         tmpfs     defaults            0     0
devtmpfs       /dev         devtmpfs  mode=0755,nosuid    0     0
#/dev/sr0       /media/cdrom iso9660   noauto,user,ro      0     0
#/dev/usb?      /media/usbstg auto     noauto,user         0     0
# End /etc/fstab
EOF
This message will preceed the login prompt:
echo 'Linux From Scratch 7.4 on \n using kernel \r' > /etc/issue
I created the bash startup files (from the BLFS book) but "cleaned" them up a little. The profile file in the book still allowed root history to be saved until I set HISTFILESIZE to 0 for root.
cat > /etc/profile << "EOF"
# Begin /etc/profile
export LANG=en_US.ISO-8859-1
if [ $EUID -eq 0 ] ; then
        unset HISTFILE
	export HISTFILESIZE=0
fi
export PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/opt/bin
export HISTSIZE=1000
export HISTIGNORE="&:[bf]g:exit"
# Setup a red prompt for root and a green one for users.
NORMAL="\[\e[0m\]"
RED="\[\e[1;31m\]"
GREEN="\[\e[1;32m\]"
if [[ $EUID == 0 ]] ; then
  PS1="$RED\u [ $NORMAL\w$RED ]# $NORMAL"
else
  PS1="$GREEN\u [ $NORMAL\w$GREEN ]\$ $NORMAL"
fi
for script in /etc/profile.d/*.sh ; do
        if [ -r $script ] ; then
                . $script
        fi
done
# End /etc/profile
EOF
install --directory --mode=0755 --owner=root --group=root /etc/profile.d
cat > /etc/profile.d/dircolors.sh << "EOF"
# Setup for /bin/ls to support color, the alias is in /etc/bashrc.
if [ -f "/etc/dircolors" ] ; then
        eval $(dircolors -b /etc/dircolors)
        if [ -f "$HOME/.dircolors" ] ; then
                eval $(dircolors -b $HOME/.dircolors)
        fi
fi
alias ls='ls --color=auto'
EOF
cat > /etc/profile.d/extrapaths.sh << "EOF"
if [ -d /usr/local/lib/pkgconfig ] ; then
        PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig
fi
if [ -d ~/bin ]; then
        PATH=~/bin:$PATH
fi
export PATH
export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/lib/pkgconfig
EOF
cat > /etc/profile.d/readline.sh << "EOF"
# Setup the INPUTRC environment variable.
if [ -z "$INPUTRC" -a ! -f "$HOME/.inputrc" ] ; then
        INPUTRC=/etc/inputrc
fi
export INPUTRC
EOF
cat > /etc/profile.d/umask.sh << "EOF"
# By default, the umask should be set.
if [ "$(id -gn)" = "$(id -un)" -a $EUID -gt 99 ] ; then
  umask 007
else
  umask 022
fi
EOF
cat > /etc/bashrc << "EOF"
# Begin /etc/bashrc
# Written for Beyond Linux From Scratch
# by James Robertson 
# updated by Bruce Dubbs 
# System wide aliases and functions.
# System wide environment variables and startup programs should go into
# /etc/profile.  Personal environment variables and startup programs
# should go into ~/.bash_profile.  Personal aliases and functions should
# go into ~/.bashrc
# Provides a colored /bin/ls command.  Used in conjunction with code in
# /etc/profile.
alias ls='ls --color=auto'
# Provides prompt for non-login shells, specifically shells started
# in the X environment. [Review the LFS archive thread titled
# PS1 Environment Variable for a great case study behind this script
# addendum.]
NORMAL="\[\e[0m\]"
RED="\[\e[1;31m\]"
GREEN="\[\e[1;32m\]"
if [[ $EUID == 0 ]] ; then
  PS1="$RED\u [ $NORMAL\w$RED ]# $NORMAL"
else
  PS1="$GREEN\u [ $NORMAL\w$GREEN ]\$ $NORMAL"
fi
# End /etc/bashrc
EOF
dircolors -p > /etc/dircolors
mkdir /etc/skel
cat > /etc/skel/.bash_profile << "EOF"
# Begin /etc/skel/.bash_profile
if [ -f "$HOME/.bashrc" ] ; then
  source $HOME/.bashrc
fi
# End /etc/skel/.bash_profile
EOF
cat > /etc/skel/.bashrc << "EOF"
# Begin /etc/skel/.bashrc
if [ -f "/etc/bashrc" ] ; then
  source /etc/bashrc
fi
# End /etc/skel/.bashrc
EOF
cat > /etc/skel/.bash_logout << "EOF"
# Begin /etc/skel/.bash_logout
# End /etc/skel/.bash_logout
EOF
cp /etc/skel/.bash* ~/
cat > /etc/shells << "EOF"
# Begin /etc/shells
/bin/sh
/bin/bash
# End /etc/shells
EOF
LFS specifies kernel 3.10.10, but I installed 3.13 (the latest stable kernel at this point).
wget https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.13.tar.xz
wget https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.13.tar.sign
unxz linux-3.13.tar.xz
# NB: next two commands must be run under host system as we do not have gpg yet!
gpg --recv-keys 6092693E
gpg --verify linux-3.13.tar.sign
tar -xf linux-3.13.tar
cd linux-3.13
(make mrproper 2>&1 | tee -a ../linux-3.13.out && exit $PIPESTATUS)
make defconfig
cp .config ../linux-3.13.default.config
make LANG=$LANG LC_ALL= menuconfig
The menuconfig process is interactive, so I could not save the output. This list details how I configured the kernel. In general, I omitted all VMWare-related software (have a long-standing bad taste for virtual machines ever since learning about VM/370). All config options not specified here were defaulted EXCEPT EXPERIMENTAL options. In general, I built just about all possible device support as modules, in the hope that this distro will be more usable for my students at home.
Some interested new features: the kernel now randomizes heap placement to foil heap exploits. Also, by enabling -fstack-protector, the kernel will detect buffer overflow exploits using a stack canary in each function call.

NEW: IDE drives are now /dev/sd !

Here is the actual kernel build:

cp .config ../linux-3.13.lfs.config
(make 2>&1 | tee -a ../linux-3.13.out && exit $PIPESTATUS)
(make modules_install 2>&1 | tee -a ../linux-3.13.out && exit $PIPESTATUS)
cp -v arch/x86/boot/bzImage /boot/vmlinuz-3.13
cp -v System.map /boot/System.map-3.13
cp -v .config /boot/config-3.13
install -d /usr/share/doc/linux-3.13
cp -r Documentation/* /usr/share/doc/linux-3.13
cd ..
chown -R 0:0 linux-3.13
install -v -m755 -d /etc/modprobe.d
cat > /etc/modprobe.d/usb.conf << "EOF"
# Begin /etc/modprobe.d/usb.conf
install ohci_hcd /sbin/modprobe ehci_hcd ; /sbin/modprobe -i ohci_hcd ; true
install uhci_hcd /sbin/modprobe ehci_hcd ; /sbin/modprobe -i uhci_hcd ; true
# End /etc/modprobe.d/usb.conf
EOF
gzip linux-3.13.out
Note that after qt is installed, it's more convenient to "make xconfig" instead of "make menuconfig".

I installed grub on hdb (sdb) so that the BLFS build could take place on the new system with no possible dependency on the build system software. I change the boot order in the BIOS to switch between hda and hdb.

If using on a RAID system, remove the raid=noautodetect option.

grub-install /dev/hdb
# NB: set root=(hd0,1) is hd RELATIVE TO WHERE GRUB IS INSTALLED IN MBR
cat > /boot/grub/grub.cfg << "EOF"
# Begin /boot/grub/grub.cfg
set default=0
set timeout=5
insmod ext2
set root=(hd0,1)
menuentry "lfs-7.4: vmlinuz-3.13" {
        linux   /boot/vmlinuz-3.13 root=/dev/sdb1 ro raid=noautodetect
}
EOF
After booting to the new system, I added a swap partition and rebooted so the kernel would see the new partition table:
fdisk /dev/sdb
n
p
3
<default>
+2G
t
3
82
w

After the reboot, I tested mountvar; on the last test boot, I placed /var on sdb2. Then I initialized the new swap partition and fixed up fstab so mountvar would bypass configuration.

mkswap /dev/sdb3
sed -i -e 's%#/dev/????%/dev/sdb3%' /etc/fstab
sed -i -e 's%#/dev/sr0%/dev/sr0%' /etc/fstab
sed -i -e 's%#/dev/usb?%/dev/sdc1%' /etc/fstab
sed -i -e 's%#/dev/var?%/dev/sdb2%' /mnt/lfs/etc/fstab
By this time, a new kernel was out, and I figured the best way to check out the new system was to build it:
cd /sources
mount -wo remount /
wget https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.13.3.tar.xz
wget https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.13.3.tar.sign
unxz linux-3.13.3.tar.xz
# NB: next two commands had to be run under the host system as I did not have gpg yet!
gpg --recv-keys 6092693E
gpg --verify linux-3.13.3.tar.sign
tar -xf linux-3.13.3.tar
cd linux-3.13.3
(make mrproper 2>&1 | tee -a ../linux-3.13.3.out && exit $PIPESTATUS)
make defconfig
cp .config ../linux-3.13.3.default.config
cp ../linux-3.13.lfs.config .config
make LANG=$LANG LC_ALL= menuconfig
cp .config ../linux-3.13.3.lfs.config
(make 2>&1 | tee -a ../linux-3.13.3.out && exit $PIPESTATUS)
(make modules_install 2>&1 | tee -a ../linux-3.13.3.out && exit $PIPESTATUS)
cp -v arch/x86/boot/bzImage /boot/vmlinuz-3.13.3
cp -v System.map /boot/System.map-3.13.3
cp -v .config /boot/config-3.13.3
cd ..
gzip linux-3.13.3.out
# add the following lines to grub.cfg
menuentry "lfs-7.4: vmlinuz-3.13.3" {
        linux   /boot/vmlinuz-3.13.3 root=/dev/sdb1 ro raid=noautodetect
}
mount -ro remount /
I rebooted and have been running on 3.13.3 ever since.

From this point on, the plan was to:

  1. stage the build of a package on the production system;
  2. sftp it to the build system;
  3. cat it in virtual terminal 2; and
  4. copy and paste commands from terminal 2 to terminal 1 to do the actual build.

Before and after each session, the root system was remounted writeable, then readonly as in the 3.13.3 build. Those commands will be assumed in the following.

The remainder of the install will be based on BLFS-7.4; it was supplemented as necessary. The first step was to identify those packages I desired from an "end-user" point of view. And therein lies a tale.

Lesson Number 2

Previous editions of this distro included a file manager called Endeavour Mark II. It was very capable, and I fully expected to include it in this version. But building it turned into a nightmare. It has not been updated since October 2012, which at first sight doesn't seem so bad. But it is not compatible with a large number of the libraries I was using, and in the process of trying to get it to compile, I had to install old versions of glib, gtk, imlib, libungif, libpng and libmng. In addition, I had to modify a number of includes and fix a couple of syntax errors. After finally getting it to make cleanly, I sat back and realized that this is going to be a tremendous pain in the tuckus forever after. The lesson is to not use software that is not being actively maintained. I left the old libraries intact in case they might be useful in the future; no use burning too many bridges. As it turns out, that may have been a mistake; some packages get very confused when there are two versions of libpng lying around.

So what was I going to use for a file manager? I very much like the lightweight environment that WindowMaker provides, but I have gotten very used to being able to quickly browse file trees in order to find things, and I have gotten VERY used to the image browser. I did not want to get into a desktop system, nor did I want to end up building a lot of gnome libraries for a single purpose. Then I found Geeqie, and so far am quite happy with it. So what to do about file browsing? I spent a couple of hours on a shell script called lstree which I think will meet my needs. And I get the added bonus of not allowing my students to continue to be spoiled by GUI file and directory interfaces.

The final package "wish-list" was

  1. alsa-lib
  2. ALSA-OSS
  3. alsa-plugins
  4. alsa-tools
  5. alsa-utils
  6. Apache
  7. Aspell
  8. audacity
  9. BIND
  10. CDParanoia
  11. cdrtools
  12. Cups
  13. cups-filters
  14. CVS
  15. ddclient
  16. ddd
  17. DHCP
  18. dosfstools
  19. dvdauthor
  20. dvd+rw-tools
  21. Emacs
  22. Fcron
  23. FFmpeg
  24. FLAC
  25. GDB
  26. Geeqie
  27. ghostscript
  28. Gimp
  29. Git
  30. GPM (already installed)
  31. GnuPG
  32. Gutenprint
  33. Hdparm
  34. IcedTea-Web
  35. Iptables
  36. ISOLinux
  37. LAME
  38. libid3tag
  39. LibreOffice
  40. lm_sensors
  41. MathMLfonts
  42. Memtest86
  43. MJPEGTools
  44. mp3gain
  45. mp3info
  46. Mplayer
  47. Nano (already installed)
  48. netcat
  49. Net-tools
  50. Nmap
  51. ntp
  52. OpenJDK
  53. OpenSSH (already installed)
  54. pciutils
  55. Postfix
  56. Python
  57. Samba
  58. SeaMonkey
  59. sox
  60. strace
  61. Subversion
  62. Traceroute
  63. Transcode
  64. ufraw
  65. UnZip
  66. usbutils
  67. Vim (already installed)
  68. Wget (already installed)
  69. Which (already installed)
  70. WindowMaker
  71. Wireless Tools
  72. Wireshark
  73. wpa_supplicant
  74. wxGTK
  75. xcalc
  76. xfsprogs
  77. xman
  78. Xorg
  79. xosview
  80. xpdf
  81. XScreenSaver
  82. Zip

Examining the dependencies, I constructed the following build matrix, specifying an order which will hopefully satisfy all of them; note that some of these were moved around during install because of unadvertised dependencies. The intention was to install as many low-dependency libraries as possible first; these were done mostly in alphabetical order with some random insertions for reasons that are no longer clear. I also decided to install a number of "stand-alone" packages (mostly in alphabetical prder, mixed in with the libraries) under the theory that additional builds are decent system tests (and you never know when you might need one of them).

This list is 210 "packages" long, but it encompasses approximately 400 actual package installs.

Packagerequires:
strace
memtest86
apr
attr
ntfs-3g
libcap2attr
libeventopenssl
nettleopenssl
ntplibcap2, openssl
cdparanoia
cpio
dhcp
dosfstools
libpng
freetypewhich, libpng
libdvdread
elfutils
exiv2expat
faac
faad2
giflib
gperf
hdparm
hicoloricontheme
ijs
iptables
jsonc
liba52
libatomic_ops
libburn
libdvdcss
libdvdnavlibdvdread
libexif
libffi
libisofs
nasm
libjpegturbonasm
libmad
libnl
libogg
libvorbislibogg
pixmanlibpng, #gtk+2- circular through pango
libtasn1
libusb
libpcaplibnl, libusb
lua
lzo
mathmlfonts
mp3info
mtdev
flaclibogg, nasm
netcat
nettools
nspr
pciutils
ddclientperl, perlmodules
intltoolperlmodules
cacertsopenssl, wget
curlcacerts, openssl
gnutlsnettle, cacerts, libtasn1
bablpkgconfig
libtirpcpkgconfig
usbutilslibusb, pkgconfig
popt
tcl
openjdkglib to build certs
dbtcl, openjdk
traceroute
unixodbc
unrar
unzip
mp3gainunzip
sqliteunzip
aprutilapr, db, expat, sqlite, unixodbc, openssl
apacheaprutil, db, pcre, lua, openssl
nssnspr, sqlite
aspellwhich
lm_sensorswhich
wirelesstools
xfsprogs
zip
libid3tagzlib
python2openssl, sqlite, expat, libffi, pkgconfig, db, #tk-needs xorglibs
yasmpython2
libvpxyasm, which
xvidyasm
gdbpython2
alsalibpython2
alsaossalsalib
libsndfilealsalib, flac, libogg, libvorbis, sqlite
lamelibsndfile, nasm
libsampleratelibsndfile
alsautilsalsalib, libsamplerate
sconspython2
serfaprutil, openssl, scons
libxml2python2
dvdauthorlibpng, freetype, libdvdread, libxml2
libxsltlibxml2, python2
bindlibcap2, libxml2, openssl, perlmodules, nettools, libxslt
fontconfigfreetype, expat, libxml2
xorg-pt1wget, pkgconfig, python2, libxml2, libxslt, fontconfig; includes BLFS sections up to and including libxcb
xorglibsxorg-pt1, fontconfig; includes BLFS xcb sections
libdrmxorglibs
libvdpauxorglibs
llvmlibxml2, zip, libffi, python2
icullvm
boosticu, python2
mesalibexpat, libdrm, libxml2, elfutils, llvm, libvdpau
freeglutmesalib
libtifflibjpegturbo, xorglibs, freeglut
lcmslibjpegturbo, libtiff
libmnglibjpegturbo, lcms
xorg-pt2xorg-pt1, libpng, mesalib, intltool, openssl, pixman, mtdev; includes rest of BLFS x chapter after Mesalib
windowmakerxorg-pt2, freetype, fontconfig, libpng, zlib, libtiff, libjpeg, giflib
xcalcxorg-pt2
xmanxorg-pt2
emacsxorg-pt2, libjpegturbo, libpng, libtiff, aspell
xosviewxorg-pt2
motifxorg-pt2
dddmotif, gdb
dbusexpat, libxml2, python2, xorglibs, #dbus-glib- circular
gliblibffi, pkgconfig, python2, pcre, dbus, attr
libgusbglib, libusb
dbusglibdbus, expat, glib
atkglib
libcrocoglib, libxml2
qt4alsalib, mesalib, cacerts, dbus, glib, icu, libjpegturbo, libmng, libpng, libtiff, openssl, sqlite
wpa_supplicantdbus, libxml2, qt4, pciutils, libnl, openssl
cairolibpng, glib, pixman, libdrm, lzo, mesalib, fontconfig, xorglibs, qt4
harfbuzzglib, icu, freetype, cairo
pangocairo, harfbuzz, xorglibs
gdkpixbufglib, libjpegturbo, libpng, libtiff, xorglibs
gtk+2atk, gdkpixbuf, pango, hicoloricontheme
libgladelibxml2, gtk+2, python2
xscreensaverbc, libglade, xorg-pt2
gstreamerglib, libxml2
gstpluginsbasegstreamer, pango, cdparanoia, alsalib, libogg, libvorbis, xorglibs
seamonkeyalsalib, gtk+2, zip, unzip, dbusglib, sqlite, libevent, nspr, nss, wirelesstools, wget, yasm, libvpx, gstreamer
atspi2coredbus, glib, intltool, xorg-pt2
atspi2atkatspi2core, atk
colorddbus, libgusb, lcms, sqlite
cupsopenssl, python2, colord, dbus, libusb
gtk+3atspi2atk, gdkpixbuf, pango, colord, cups
wxgtkgtk+3, bison, flex, xorg-pt2
alsatoolsalsalib, gtk+2, gtk+3
librsvggdkpixbuf, libcroco, pango, gtk+2, gtk+3
imlibfreetype
openjpeglcms, libpng, libtiff, pkgconfig
popplerfontconfig, curl, gtk+2, lcms, libtiff, libxml2, openjpeg, qt4, cairo, libjpegturbo, libpng
qpdfpcre, libxslt
cupsfilterscups, ijs, lcms, poppler, qpdf, libjpegturbo, libpng, libtiff
ghostscriptcairo, fontconfig, gtk+2, cups, lcms, xorg-pt2, expat, freetype, libjpegturbo, libpng, libtiff
sambalibtirpc, cups, xfsprogs, python2, libxslt, libcap2, popt
pulseaudiointltool, jsonc, libsndfile, pkgconfig, libsamplerate, glib, gtk+2, alsalib, dbus, libcap2, openssl, xorg-pt2
libaoxorg-pt2, alsalib, pulseaudio, libatomic_ops
sdlalsalib, pulseaudio, nasm, libusb, xorg-pt2
libdvpopt, pkgconfig, sdl, xorg-pt2
libmpeg2xorg-pt2, sdl
libgpgerror
libgcryptlibgpgerror
wiresharkglib, libpcap, pkgconfig, gtk+3, openssl, python2, pcre, gnutls, lua, libgcrypt - not advertised!
ffmpegfontconfig, faac, freetype, lame, openjpeg, pulseaudio, libvorbis, libvpx, xvid, openssl, sdl, xorg-pt2, yasm, gnutls
alsapluginsalsalib, ffmpeg, libsamplerate, pulseaudio
libarchive
cmakelibarchive
audacitywxgtk, cmake, libid3tag, ffmpeg, libmad, libsndfile
gstpluginsgoodgstpluginsbase, libdv, pulseaudio, gtk+3, cairo, flac, libjpegturbo, libpng, xorglibs
gstffmpeggstpluginsbase, yasm
libquicktimealsalib, faac, faad2, ffmpeg, gtk+2, lame, libdv, libjpegturbo, libpng, libvorbis, xorg-pt2
mplayeryasm, gtk+2, fontconfig, freetype, unrar, libxslt, cdparanoia, samba, libdvdread, libdvdnav, libdvdcss, alsalib, pulseaudio, sdl, giflib, libjpegturbo, libmng, libpng, openjpeg, ffmpeg, libmad, lzo, liba52, faac, xvid, libvpx, lame, libdv
xulrunneralsalib, gstpluginsbase, gstffmpeg, gtk+2, zip, unzip, curl, dbusglib, wget, wirelesstools, libevent, libvpx, nspr, nss, sqlite, yasm
napai-sdk
icedteawebopenjdk, xulrunner, npapi-sdk
mjpegtoolsglib, libjpegturbo, gtk+3, sdl, libquicktime, libdv
soxlibao, ffmpeg, flac, lame, libmad, libid3tag, libogg, libvorbis, libsndfile
transcodeffmpeg, faac, freetype, liba52, libdv, libdvdread, libjpegturbo, libogg, libquicktime, libvorbis, libxml2, lzo, sdl, xvid, alsalib, lame, libmpeg2, xorg-pt2
tktcl, xorg-pt2
libisoburnlibburn, libisofs, attr, tk
dvd+rwtoolslibisoburn
rubydb, openssl, tk
jasperunzip, libjpegturbo, xorg-pt2, freeglut
cyrussaslopenssl, sqlite, db
postfixdb, pcre, sqlite, cyrussasl, openssl
cvsopenssh, postfix, ghostscript, nano
fcronpostfix, nano
gnupgcurl, postfix
python3db, openssl, sqlite, tk, expat, libffi, pkgconfig
dbuspythondbusglib, python2
py2cairopython2, cairo
pygobjectglib, py2cairo
pygtkpython2, dbusglib, cairo, pygobject, py2cairo, atk, pango, gtk+2, libglade
gsettings-desktop-schemasglib, intltool
glibnetworkinggnutls, cacerts, gsettings-desktop-schemas
libsoupglibnetworking, libxml2, sqlite, curl, apache, samba
enchantglib, dbusglib, aspell
gconfdbusglib, intltool, libxml2, gtk+3
geocluedbusglib, gconf, libxslt, gtk+2
geglbabl, cairo, exiv2, ffmpeg, gdkpixbuf, libjpegturbo, libpng, librsvg, lua, pango, python2, ruby, sdl
webkitgtkgperf, gstpluginsbase, gtk+2, icu, libsoup, mesalib, ruby, sqlite, which, curl, enchant, geoclue
gimpgegl, gtk+2, intltool, alsalib, curl, dbusglib, ghostscript, jasper, lcms, libexif, libmng, librsvg, poppler, postfix, webkitgtk, pygtk
gtkimageviewgtk
ufrawlcms, glib, gtk+3, exiv2, libjpeg, libtiff, zlib, gtkimageview
geeqiegtk
gutenprintijs, cups, gimp
subversionaprutil, sqlite, apache, cyrussasl, dbus, python2, openjdk, ruby, openssl, serf
gitpcre, subversion, tk, curl, expat, openssl, python2
nmapopenssl, pygtk, python2, subversion, libpcap, lua, pcre
libreofficegperf, gtk+2, perlmodules, unzip, wget, which, zip, gtk+3, boost, cups, curl, dbus, expat, gstpluginsbase, icu, lcms, librsvg, libxml2, libxslt, mesalib, nss, openssl, poppler, python3, unixodbc
xpdffreetype, motif
cdrtools
isolinux
As a general rule, I decided not to install additional documentation until I need it.

Here I go; and right off the bat I have to fix a duplicate include in strace. As it turns out, adjustments were necessary for many of the packages that are not part of the BLFS book.

Note that I did not have URLs for some of the sourceforge packages; these were downloaded on my production system and transferred to the build system (until SeaMonkey was installed).

Memtest, too, needing patching.

Note that the DHCP server boot scripts wre not installed.

Also, the sample dhcpd.conf file included a nonsupported ddns line that had to be removed, and BLFS forgot to tell us to touch /var/lib/dhcpd/dhcpd.leases.

I modified the rc.iptables file from the "personal firewall" example in the book. Specifically, the default output policy (which only covers packets ORIGINATING from this PC) was set to ACCEPT. I also removed the logging of unrelated input in order to avoid filling sys.log, and allowed pings, and ssh from the instructor's PC (so I can help students with problems).

Note that the net-tools configuration is interactive: I responded y for GNU gettext, and n for IPX/SPX, Appletalk, AX25, NET/ROM, Rose, X.25, Econet, Ash, ARCnet, SLIP, PPP, DLCI/FRAD, FDDI, HIPPI, (Cisco)-HDLC/LAPB and EUI64. All others were defaulted.

Note that ddclient boot scripts and configuration were not done at this time (for obvious reasons).

Since you have to install an OpenJDK binary before you can build it, and I had no need to change any of the build parameters, I elected to not bother re-building it.

Note that the mkcacerts script could not be run until after glib was installed.

Before building apache, I modified /etc/default/useradd to get rid of the irritating group 1000 doesn't exist error.

I also changed the boot script link in /etc/rc.d/rc3.d so that httpd will only start in runlevels 4 or 5.

After booting, run sensors-detect to configure /etc/sysconfig/lm_sensors.

After installing alsa-utils, I used alsamixer to unmute master, PCM and line, and set all three to 81.

After installing bind, I modified the boot script to only use ipv4; this eliminates some irritating log file messages.

Here is the start of the Xorg build:

export XORG_PREFIX="/usr"
export XORG_CONFIG="--prefix=$XORG_PREFIX --sysconfdir=/etc --localstatedir=/var --disable-static"
cat > /etc/profile.d/xorg.sh << "EOF"
XORG_PREFIX="/usr"
XORG_CONFIG="--prefix=$XORG_PREFIX --sysconfdir=/etc --localstatedir=/var --disable-static"
export XORG_PREFIX XORG_CONFIG
EOF
chmod 644 /etc/profile.d/xorg.sh
I adopted a slightly different syntax for Xorg - BLFS wanted us to create multiple subdirectories, which I did not do, but this code should be slightly less brittle if I missed something. NB: apparently not all Xorg packages recognize all options in XORG_CONFIG (ie., --disable-static).

The Mesalib Wiki suggested that I needed to leave the source tree for Xorg; after the fact, it appears not to have been necessary. At any rate, I did not delete it until after the Xorg build was complete.

NB: on any given system, the unused drivers can be moved or removed and Xorg might start a little quicker

NEW: you must be a member of the video group in order to use hardware acceleration (DRI2).

At this point I tested Xorg, and cleaned up some directories which I might have needed but no longer should need.

startx
grep /var/log/Xorg.0.log -e DRI
glxinfo
glxgears
rm -rf xorg-server-1.14.3
rm -rf Mesa-9.2.0
rm -rf glu-9.0.0
tar -czf linux-3.13.built.tgz linux-3.13
tar -czf linux-3.13.3.built.tgz linux-3.13.3
rm -rf linux-3.13
rm -rf linux-3.13.3
In building WindowMaker, I had to disable gifs because I have giflib v5 and this version doesn't handle it correctly.

I used wprefs to tailor WindowMaker's behavior to my liking:

I started xclock, and set up Xdefaults for xterm, changing colors (so my students can see this better on the projector in the lab), setting jumpscroll, savelines, scrollbar and scrollkey.

In previous versions of WindowMaker, xclock run with the geometry +0-0 would behave oddly: each time you started WindowMaker, the clock would creep a little further up the left side of the screen. Then after a few rounds of that, it would disappear. The disappearence seems to have been fixed, but the creeping is still there. The fix (once you have decided what screen resolution you want), is to replace the +0-0 designation with

+0+<your vertical screen height - 32>

xclock -strftime "%a, %b %e - %l:%M %P" -g 172x32+0-0 -digital -update 1 &
# removed title bar and icon
cat > .Xdefaults << "EOF"
#ifdef COLOR
*customization: -color
#endif
emacs*Background: White
emacs*Foreground: Black
emacs*pointerColor: Blue
emacs*cursorColor: Blue
emacs*bitmapIcon: on
emacs*font: fixed
emacs.geometry: 80x25
Seyon.modems: /dev/modem
xterm*background: White
xterm*foreground: Black
xterm*cursorColor: Blue
xterm*pointerColor: Blue
xterm*reverseVideo: false
xterm*jumpScroll: true
xterm*savelines: 5000
xterm*scrollBar: true
xterm*reverseWrap: true
xterm*font: fixed
xterm*fullCursor: true
xterm*scrollTtyOutput: off
xterm*scrollKey: on
xterm*VT100.Translations: #override\n\
	Prior : scroll-back(1,page)\n\
	Next : scroll-forw(1,page)
xterm*titleBar: false
xterm_color*background: White
xterm_color*foreground: Black
xterm_color*cursorColor: Blue
xterm_color*pointerColor: Blue
xterm_color*reverseVideo: false
xterm_color*jumpScroll: true
xterm_color*scrollBar: true
xterm_color*saveLines: 5000
xterm_color*reverseWrap: true
xterm_color*font: fixed
xterm_color.geometry: 80x25+20+20
xterm_color*fullCursor: true
xterm_color*scrollTtyOutput: off
xterm_color*scrollKey: on
xterm_color*VT100.Translations: #override\n\
	Prior : scroll-back(1,page)\n\
	Next : scroll-forw(1,page)
xterm_color*titleBar: false
EOF

Emacs behavior seems to have changed since version 22; I set it up to inhibit the splash screen and go back to the old copy and paste behavior (making it easy to use gpm to copy and paste between xterm windows and emacs ).

Lesson Number 3

We elected to install Xorg in /usr instead of /usr/X11 or /usr/X11Rn, but there are still packages which expect X to be there; xosview was one. For those packages, we added
--x-includes=/usr/include --x-libraries=/usr/lib
to the ./configure parameters so the build would find Xorg. We also found a patch we needed to use, and fixed the location of the APPLOADDIR. Finally, we had to set CFLAGS='-fpermissive' to get lmstemp to compile.

And then I decided I wanted to be able to monitor my core temperatures. But this version of xosview looks in the wrong spot for my system. So I hacked linux/lmstemp.cc a little and set some Xdefaults and it's pretty cool.

ddd needed a patch too:

Now we could run mkcacerts for OpenJDK. Results follow.

/opt/jdk/bin/mkcacerts -d "/etc/ssl/certs/"  -k "/opt/jdk/bin/keytool" -s "/usr/bin/openssl" -o "/opt/jdk/jre/lib/security/cacerts"
# NB: sed error on ca-certificates.crt - did
cd /opt/jdk
bin/keytool -list -keystore jre/lib/security/cacerts
# and it looks OK....

Since I was building this on an AMD-based system, there were a couple of cpu capabilities which I knew were not going to be available on my production systems, or in the lab. These were 3DNOW and 3DNOWEXT. In addition, Intels, for instance, do not have MMXEXT/MMX2, although they do have SSEn, which covers MMXEXT capabilities.

So for packages which make use of the 3DNOW technology, I attempted to stop the package from using it. This was in some cases easier said than done. I added -no-3dnow to the ./configure parameters; then found that the Makefiles still included it. So I tried to disable it by hand with a sed script, after which I found no occurrences of the string MMXEXT. After the make, there were 2452. Unwilling to waste any more time on it, I let it go. I'm not sure I'm going to be using qt much; I really only built it because a handful of packages (wpa_supplicant, cairo and poppler) require it. And the only reference to 3DNOW is in qdrawhelper_x86_p.h. And on top of everything else, hopefully sse will cover my rear on this one.

Note that I did not install wpa_supplicant boot scripts or ifconfig files at this time (again, for obvious reasons).

This a handy little script I use to lock my Xorg screen, which syncs the filesystems before locking:

cat > /usr/bin/lock << "EOF"
#!/bin/sh
#/usr/bin/lock
sync
xscreensaver-command -lock
EOF
chmod 744 /usr/bin/lock

Lesson Number 4

Here begins another tale. BLFS 7.4 includes SeaMonkey 2.20. After installation, I got the message
GLib-CRITICAL **: g_slice_set_config: assertion `sys_page_size == 0' failed
followed by a seg fault in Xorg at location 0xc. I focused on the first error, while I should have focused on the seg fault. I decided to try SeaMonkey 2.24 from BLFS 7.5, which required

Of course, the assetion error was still there (although it seems to be benign). It turns out the seg fault was a bug in the mach64 Xorg driver, so I could have stuck with seamonkey 2.20. More to follow.

You can go to http://www.youtube.com/html5 and click on 'Join the HTML5 Trial' to view youtube videos with SeaMonkey.

After installation, I opened a browser window to about:config (see http://preferential.mozdev.org/preferences.html) and cleared printer headers, footerright (my own preference).

As I mentioned before, the main problem was a mach64 driver issue. You can work around that by

cat > /etc/X11/xorg.conf.d/videocard-0.conf << "EOF"
Section "Device"
    Identifier  "Videocard0"
    Driver      "mach64"
    Option      "ExaNoComposite" "true"
EndSection
EOF
However, SeaMonkey runs like a dog. It turns out to run much better on the vesa driver; I also set my resolution at the same time, and made a copy for the DVD image. And I thought it might be good to provide a skeleton Xorg configuration for a dual-head system:
rm /etc/X11/xorg.conf.d/videocard-0.conf
cat > /etc/X11/xorg.conf << "EOF"
Section "Device"
        Identifier      "Card0"
        Driver          "vesa"
EndSection
Section "Screen"
        Identifier      "Screen0"
        Device          "Card0"
        SubSection      "Display"
                Depth   24
                Virtual 1024 768
                Modes   "1024x768"
        EndSubSection
EndSection
EOF
cp /etc/X11/xorg.conf /mnt/root/xorg.conf.vesa.fallback
cat > /mnt/root/xorg.conf.dual.head << "EOF"
Section "Device"
        Identifier  "Card0"
        Option      "Monitor-DVI-0" "Monitor0"
        Option      "Monitor-DVI-1" "Monitor1"
EndSection
Section "ServerLayout"
        Identifier     "Dual Head Layout"
        Screen         "Screen0"
EndSection
Section "Monitor"
        Identifier   "Monitor0"
        Option       "DPMS" "true"
EndSection
Section "Monitor"
        Identifier   "Monitor1"
        Option "Right Of" "Monitor0"
        Option       "DPMS" "true"
EndSection
Section "Screen"
        Identifier "Screen0"
        Device     "Card0"
        SubSection "Display"
                Depth     24
                Virtual   2560 1024
        EndSubSection
EndSection
EOF
I also made the following changes in SeaMonkey's preferences:

However, you won't have these when running the distro. SeaMonkey does a goofy thing for a Unix environment: it creates a new user profile, whose directory name is randomly generated. I have not had much luck getting anything in /etc/skel to work. But I did include my bookmark and preferences files in /root in case you want to use them.

mathmlfonts must be installed from within seamonkey; see https://addons.mozilla.org/en-US/firefox/addon/mathml-fonts/

To add a new printer (this example is for a networked postscript printer):

  1. Open /usr/share/doc/cups-1.6.3/index.html in SeaMonkey, and go to the Overview/Administration link.
  2. Give it a name and point it to lpd on <printer's IP address>.
  3. make it the default printer, type raw, and add root as a user.

The following installs were done before I decided to lose endeavour. I'm leaving them in place in case they are useful at some point in the future. More about this later.

I installed libungif into /usr/local to avoid conflict with giflib 5.

Since imlib1 needs libpng12, I moved the libpng16 links temporarily so imlib1 would find the older version.

After installing imlib1, I put the libpng16 links back. I included some (commented out) commands in the following libmng build in case I ever need to build against the old version.

I'm leaving out all of the hassles I had trying to install endeavour. I built it a half dozen times, each time running up against new problems (many of them syntax errors), before I gave up.

Here is my lstree script. It runs well if the directory tree you are browsing is not too large; if you want to speed it up for large trees, take the sort out of the find pipe. It supports the ls -a option and uses ls --color. It does not indent directory names, but it does indent file names, and it shows the fully qualified file name so you can copy it with the mouse and middle-click on a docked application to open the file. Some applications do better than others, but emacs does fine with that, and that was my primary intention.

cat > /usr/bin/lstree << "EOF"
#!/bin/sh
#/usr/bin/lstree
if [ "$1" = "-a" ]; then
    shift
    hidden=yes
elif [ "$2" = "-a" ]; then
    hidden=yes
fi
if [ $# = 0 ]; then
    dir=$(pwd)
else
    dir=$1
fi
(for f in `find $dir -xdev -ls | sed -e 's/^ *//' | tr -s ' ' | cut -d' ' -f11 | grep -ve '^\.$' | sed -e 's%^\./%%' | sort`; do
    if [ -e $f ] ; then
	if [ -n "$(echo $f | grep -ve '^\.\|/\.' 2>/dev/null)" -o "$hidden" = yes ]; then
	    if [ -d $f ]; then
		echo $(ls --color -d -l $f | tr -s ' ' | cut -f9- -d' ')
	    else
		prefix=''
		n=$f
		i=$(expr index "$n" '/')
		while [ $i -gt 0 ]; do
		    prefix=$prefix'\t'
		    n=$(expr substr "$n" $[$i+1] $(expr length "$n"))
		    i=$(expr index "$n" '/')
		done
		echo -e $prefix $(ls --color -d -l $f | tr -s ' ' | cut -f9- -d' ')
	    fi
	fi
    fi
done) | less -R
EOF
chmod 744 /usr/bin/lstree
The builds continue. Note that openjpeg seems to have linked against libpng12, but see below.

During the Samba make htmlman, I had to modify smb.conf.5.xml to point to the local copy of parameters.all.xml and re-issue the make. It continued from there without problem.

Interestingly, the html man page links were broken, so I had to fix them.

In trying to build audicity 2.0.5 I find it needs EXACTLY wxwidgets 2.8.12 - who would have guessed?

Audacity has been something of a problem. 2.0.5 builds fine (with --with-ffmpeg=local), but at execution time displays an error

Audacity could not read its default theme.
Please report the problem.
Then the program starts, but all of the controls are blacked out. I reported the problem, but got no help. There were numerous references to "dark themes" and "light themes", but since I am not running in a desktop environment, they were of little use. I have built it a number of times, trying experimental theming, and I attempted to load the icons from an ImageCache.png file with several different files, but each time got the error
Audacity could not load file:
/root/.audacity-data/Theme/ImageCache.png
Bad png format perhaps?
followed by the other error. Audacity linked against libpng16, and I thought that might have been the problem for a while, but the more I play with it, the more I think it just doesn't like to work outside of a desktop. My next effort was to undef XPMS_RETIRED and build using the old xpm icons (but there were issues with CleanSpeech and LinkTracks). I lost all of the errors, but the controls were still blacked out.

I believe the program will actually work, but it is a bit hard to use. So I decided to hunt for a version dating from before the new theme code. The only one I could find was 1.2.6, which is the one I have used on my production system since late 2009. But it works, and does what I need it to do.

BUT it needs wxGTK 2.4. AND I had to disable soundtouch and ladspa to get it to build cleanly.

I had to disable 3DNOW manually with gst-ffmpeg because configure did not recognize disable options.

After installing MPlayer, had to echo 'vo=x11' >> ~/.mplayer/config because the output driver it defaults to wasn't working. x11 works fine.

Since I installed seamonkey from blfs 7.5, I had to do the same with xulrunner and icedteaweb.

The xulrunner build is said to require a total of 6 GB of RAM/swap, so I increased the size of my swap partition:

/etc/rc.d/init.d/swap stop
fdisk -l /dev/sdb
d
3
n
p
3
<default>
+8G
w
<reboot>
/etc/rc.d/init.d/swap stop
mkswap -c /dev/sdb3
/etc/rc.d/init.d/swap start
Even though I have libpng 10609, it complained about needing 10606 or better, so I disabled png.

The mjpegtools build would not ignore libpng12 even if told to, so I had to quarantine the libpng12 files.

That wasn't even enough for sox, so I just disabled png.

Lesson Number 5

If you looked carefully at the dependency table, you saw a note in the Python requirements about Python2 requiring Tk, but Tk requires the Xorg libraries, and Python2 is required to build Xorg. Such circular dependencies are uncommon but not rare. Since BLFS listed Tk as optional for Python2, but the Xorg libraries as required for Tk, I built them shown above. It wasn't until I tried to install SnapPy (a math package I use in my research, but which really didn't belong in the distro) that I discovered that Tkinter (the Python Tk interface) was only a stub, because when I built Python2, Tk hadn't been built yet. As a consequence, after Tk is installed, it is necessary to rebuild Python2.

Since by this time I had already burned a number of DVD release candidates, I had to first rebuild it on my production system, and make sure that SnapPy would work. Then I had to rebuild it on the build system. But before I did that, I touched the file /root/timestamp. So when it was time to copy the files installed during the Python2 rebuild into the staging filesystem, I had only to

find /usr/ -xdev -type f -newer timestamp > python.install.manifest
tar -czf python.install.tgz -T python.install.manifest
cd /mnt
tar -xzf /root/python.install.tgz

There was a bad path in the postfix boot script which I fixed.

Also, BLFS forgot to tell us to create the aliases.db file.

NEW: fcron logs to its own log file. I set up a root fcrontab to update the usb and pci id files weekly.

Unfortunately gegl, webkitgtk and gimp all get confused about libpng, so I quarantined libpng12 again:

mkdir pngsave
mv /usr/local/bin/libpng* pngsave/
mv /usr/local/include/png* pngsave/
mv /usr/local/include/libpng12 pngsave/
mv /usr/local/lib/libpng* pngsave/
mv /usr/local/lib/pkgconfig/libpng* pngsave
ldconfig

Lesson Number 6

Don't install multiple versions again! poppler seems to have linked fine against libpng16, but the gimp link won't proceed because libpoppler needs libpng12.

For the record: the following libraries linked against libpng12, which I learned using

for f in `find /usr/lib -type f`; do if (nm -g $f 2>/dev/null | grep -e PNG12 > /dev/null 2>&1) ; then echo $f ; fi ; done

To fix (hopefully) the problem for good, I quarantined the libpng12 header and config files.

mkdir pngsave/bin
mv pngsave/libpng*config pngsave/bin
mkdir pngsave/include
mv pngsave/libpng12 pngsave/include/
mv pngsave/png* pngsave/include/
mkdir -p pngsave/lib/pkgconfig
mv pngsave/*.pc pngsave/lib/pkgconfig/
mv pngsave/* /usr/local/lib
mv pngsave /usr/local/
ldconfig

After all this, I installed gimp 2.8.6, but it did not run well. The tool dialog box was corrupted (which was video driver related; changing from mach64 to vesa fixed that). More irritatingly, gimp help does not render the html, it just displays the raw html; also, it seems unable to use the web browser for help. However, using the help with seamonkey works fine.

So I decided to install 2.8.10. Gimp help has the same problems, but a lot of folks discuss this issue and even the gimp site tells us that it may or may not work. So we'll use seamonkey.

These next two were not in the required list, but the gimp-help install goes much better with them; still doesn't fix the html rendering problem, though.

I accidentally applied the system neon patch and had to back it out (patch -R -b) when the compile of NeonSession.cxx failed. The make continued fine from there.

Oddly, xpdf doesn't seem to like WindowMaker, or vise versa. When started, there is no application icon, nor is there an "Application Specific" Attributes tab on the window. Makes it hard to dock. But open a help or find dialog box, and there's an icon you can dock.

This comes last because I simply forgot it the first time around.

That's all the packages, except ISOLinux, which we'll do below.

I downloaded the compressdoc script, compressed the man and info pages, and built the index.

cd /usr/sbin
wget http://anduin.linuxfromscratch.org/files/BLFS/svn/compressdoc
chmod -v 755 /usr/sbin/compressdoc
cd
compressdoc --bz2
mandb
I also rebuilt the WindowMaker menu, and changed hard coded /root/ to ~/ in two of its files.
wmgenmenu > $HOME/GNUstep/Defaults/WMRootMenu
sed -i GNUstep/Defaults/WindowMaker -e 's%/root/%~/%'
sed -i GNUstep/Defaults/WMWindowAttributes -e 's%/root/%~/%'

Next I created a staging partition for the ISO image:

fdisk /dev/sdb
n
e
<default>
<default>
n
<default>
+10G
w

After reboot, I recreated the modified filesystem structure on the staging partition:

mke2fs -c -c /dev/sdb5
mount -t ext2 /dev/sdb5 /mnt
cd /mnt
install -d var/{etc,home,root,srv,tmp}
ln -s var/etc etc
ln -s var/home home
ln -s var/root root
ln -s var/srv srv
ln -s var/tmp tmp
chmod 0750 var/root
chmod 1777 var/tmp
mkdir -pv {dev,home,mnt,proc,run,sys}
mkdir -pv media/{floppy,cdrom,usbstg}
mkdir -pv var/{log/{cups,httpd,samba/cores/{nmbd,smbd}},mail,spool}
cd var
ln -sv ../run run
ln -sv ../run/lock lock
cd /mnt
mkdir -pv var/{cache,db,games/emacs,lib/{misc,locate},local,opt}
mknod -m 600 dev/console c 5 1
mknod -m 666 dev/null c 1 3
and then set about populating the staging filesystem (making sure not to carry over files used for testing):
cp -a /bin .
cp -a /boot .
cp -a /etc/* var/etc/
cp -a /include .
cp -a /lib .
cp -a /sbin .
cp -a /srv/* var/srv/
cp -a /usr .
cd /var/cache
for d in `find . -type d`; do mkdir -pv /mnt/var/cache/$d ; done
cd /mnt
chgrp lp var/cache/cups -R
cp -a /var/lib var/
rm var/lib/alsa/asound.state.lock
rm var/lib/postfix/master.lock
cd /var/log
for f in `find . -type f -name '*.log'`; do touch /mnt/var/log/$f ; done
cd /mnt
cp -a /var/mail/* var/mail/
cp -a /var/spool/* var/spool/
rm var/spool/cups/{c,d}*
rm var/spool/postfix/pid/master.pid
touch var/log/{btmp,lastlog,wtmp}
chgrp -v utmp var/log/lastlog
chmod -v 664  var/log/lastlog
chmod -v 600  var/log/btmp
I had to put the original fstab in place, and touch fastboot so that e2fsck will not try to fsck the DVD:
cat > etc/fstab << "EOF"
# Begin /etc/fstab
# file system  mount-point  type     options             dump  fsck
#                                                              order
/dev/root      /            ext2     ro                   1     1
#/dev/var?      /var         ext2     noauto               0     0
#/dev/????      swap         swap     pri=1                0     0
proc           /proc        proc      nosuid,noexec,nodev 0     0
sysfs          /sys         sysfs     nosuid,noexec,nodev 0     0
devpts         /dev/pts     devpts    gid=5,mode=620      0     0
tmpfs          /run         tmpfs     defaults            0     0
devtmpfs       /dev         devtmpfs  mode=0755,nosuid    0     0
#/dev/sr0       /media/cdrom iso9660   noauto,user,ro      0     0
#/dev/usb?      /media/usbstg auto     noauto,user         0     0
# End /etc/fstab
EOF
touch fastboot
Hopefully this is the last 3DNOW piece (if you have an AMD, you can take it back out). I removed the bind boot script link from /etc/rc.d/rc3.d so it will only run in runlevels 4 and 5. We also have to remove build-system-specific configuration files, especially the networking ones so netconfigure will run at boot time:
echo 'export MESA_NO_3DNOW=1' >> etc/bashrc
rm etc/rc.d/rc3.d/S22bind
cp -P etc/rc.d/rc2.d/K49bind etc/rc.d/rc3.d/
rm etc/X11/xorg.conf
rm etc/cups/printers.*
rm etc/sysconfig/network
rm etc/hosts
rm etc/sysconfig/ifconfig.*
rm /etc/resolv.conf
Now to populate /root (additional .bashrc commands useful when su-ing):
mkdir root/bin
cat > /root/.bashrc << "EOF"
# Begin /root/.bashrc
if [ -f "/etc/bashrc" ] ; then
  source /etc/bashrc
fi

export PATH=/root/bin:$PATH:/usr/local/bin:/usr/local/sbin:/opt/bin:/opt/jdk/bin:/opt/qt/bin:/opt/schily/bin

unset HISTFILE
export HISTFILESIZE=0

umask 022

# End /root/.bashrc
EOF
cp /root/.bash* root/
cp /root/.emacs root/
cp /root/fcrontab.txt root/
cp -a /root/GNUstep root/
cp -a /root/.mozilla root/
cp -a /root/.mplayer root/
cp /root/xclock.cmd root/
cp /root/.Xdefaults root/
cp /root/.xinitrc root/
# exported bookmarks from seamonkey
cp /root/bookmarks.html root/
# copy seamonkey prefs
for f in `find /root/.mozilla/ -name prefs.js`; do cp $f root/prefs.js ; done
# and of course a copy of this page
cp /root/rwclfs.html  root/
and /etc/skel:
cp -a root/* etc/skel/
rm etc/skel/fcrontab.txt
cp -a root/{.emacs,.mplayer,.Xdefaults,.xinitrc} etc/skel/
mkdir root/bin
After building
Fcron, I had set up a root fcrontab to update the usb and pci id files weekly. Those files are kept in /usr/share/misc, which will be read-only when the jobs are executed. As a result, I had to move the misc directory to /var/share:
mkdir var/share
mv usr/share/misc var/share/
ln -s var/share/misc usr/share/misc
The total space used cannot exceed 4.7 billion bytes, so I tarred a few things to save space:

I also removed all of the mandb index stuff except the main (English) file.

tar -cJf opt.tar.xz opt/
rm -rf opt/
cd lib/modules
tar -cJf 3.13.0.tar.xz 3.13.0/
rm -rf 3.13.0/
cd /mnt/share/doc
tar -cJf db-6.0.20.tar.xz db-6.0.20/
rm -rf db-6.0.20/
cd ..
tar -cJf gtk-doc.tar.xz gtk-doc/
rm -rf gtk-doc/
cd /mnt/var/cache/man/
rm -rf *
cp /var/cache/man/index.* .
Now it's time to install ISOLinux (they tell us to use the pre-built binary, and in fact the source would not compile even though I have nasm). I also set up the configuration and message files:
cd /sources/
wget https://www.kernel.org/pub/linux/utils/boot/syslinux/syslinux-6.02.tar.xz
wget https://www.kernel.org/pub/linux/utils/boot/syslinux/syslinux-6.02.tar.sign
unxz -k syslinux-6.02.tar.xz
gpg --recv-keys 8D233D55
gpg syslinux-6.02.tar.sign
tar -xf syslinux-6.02.tar
rm syslinux-6.02.tar
mkdir /mnt/boot/isolinux
# until things are working, it might be best to use the debug version
cp syslinux-6.02/bios/core/isolinux-debug.bin /mnt/boot/isolinux/
cp syslinux-6.02/bios/core/isolinux.bin /mnt/boot/isolinux/
cp syslinux-6.02/bios/com32/elflink/ldlinux/ldlinux.c32 /mnt/boot/isolinux/
cd /sources
rm -rf syslinux-6.02
cat > /mnt/boot/isolinux/isolinux.cfg << "EOF"
default linux
prompt 1
timeout 300
display boot.msg
F1 about.msg
F2 parms.msg
label linux
  kernel vmlinuz
  append root=/dev/sr0 panic=20
label memtest86
  kernel /boot/memtest
EOF
cat > /tmp/boot.msg << "EOF"
%
^04     Welcome to RWC/LFS^07


 - Type linux and press Enter to boot Linux
 - Type memtest86 to test memory
 - Additional Help Available though function keys 

^02[F1-About] [F2-Parameters]^07
EOF
The percent sign above will be changed to 0x0C, which clears the screen and homes the cursor (see the
wiki). The carets will be changed to 0x0F, which changes colors (02 is dark green on black, 04 is dark red on black and 07 is light grey on black).
cat /tmp/boot.msg | tr '%' '\014' | tr '^' '\017' > /mnt/boot/isolinux/boot.msg
cat > /mnt/boot/isolinux/about.msg << "EOF"
RWC/LFS is a bootable ISO-9660 image containing a modified Linux From Scratch 7.4
system. It may be run solely from the DVD-ROM, or may be installed to one or more
hard drive partitions. Minimum CPU required is a Pentium Pro (or equivalent).
The Linux kernel version is 3.13.3. Please see
    kias.dyndns.org/rwclfs.html and
    kias.dyndns.org/sysadmin.html
for more information. In order to fit the system on a single-layer DVD, the following directories
were tarred:
   /opt -> opt.tar.xz
   /lib/modules/3.13.0 -> /lib/modules/3.13.0.tar.xz
   /usr/share/doc/db-6.0.20 -> /usr/share/doc/db-6.0.20.tar.xz
   /usr/share/gtk-doc -> /usr/share/gtk-doc.tar.xz
All can be untarred after installation to disk using tar -xJf 
   Note: Java, cdrtools and QT are not available when running from the DVD.
This Linux distribution is Copyright 2014, Kenneth R. Koehler. All Rights Reserved. 
It may be freely reproduced under the GNU Public License.
Please send comments or questions to Professor Koehler at kenneth.koehler@uc.edu
EOF
cat > /mnt/boot/isolinux/parms.msg << "EOF"
This DVD-ROM may be used to boot a disk-based Linux filesystem by entering (at the boot: prompt)
     linux root=/dev/sdxn
where x is a (first disk), b (second disk), etc., and n is the partition number of the root filesystem.
If you have sufficient RAM, you can increase the RAM-disk size from 64 MB using, for instance
     linux ramdisk_size=262144
for 256 MB of RAM-disk.
Additional kernel parameters are documented in /usr/doc/linx-3.13/kernel-parameters.txt
You may also specify memtest86 at the boot: prompt to start the memory tester.
EOF
# NB: added spacing to README which doesn't fit on boot screen
cp /mnt/boot/isolinux/about.msg /mnt/root/README
Note that ISOLinux doesn't like extensions, and it likes everything to be in its directory:
cp /mnt/boot/vmlinuz-3.13.3 /mnt/boot/isolinux/vmlinuz
cp /mnt/boot/memtest.bin /mnt/boot/isolinux/memtest
Finally, we create the ISO image, and burn it to a DVD:
cd
xorrisofs -l -o rwclfs.140804.iso -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table \
	  --sort-weight 2 boot/isolinux/isolinux.bin --sort-weight 1 boot/isolinux /mnt
growisofs -speed=1 -dvd-compat -Z /dev/sr0=rwclfs.140804.iso

It's Alive !!!!!!!

That's not to say it's perfect. As I continue to test, I'll fix the odd problem, and this page will change to reflect that. Who knows, maybe I'll get the gimp help browser working.


Please send questions or comments to kenneth.koehler@uc.edu.

©2015, Kenneth R. Koehler. All Rights Reserved.