<?xml version="1.0" encoding="ISO-8859-1"?>
<chapter id="phase7">
  <title>Opvullen van de hiaten</title>

  <sect1>
    <title>Analyse</title>

    <para>De rootdisk heeft een lange weg afgelegd vanaf het nederige
begin als een statisch gelinkte shell. Het deelt nu veel features met de
populaire klaar-voor-gebruik zijnde distributies. Het heeft bijvoorbeeld:
    </para>

    <itemizedlist>
      <listitem>
        <para>Verscheidene algemene utility's, zoals <command>cat</command>, 
        <command>ls</command>, enzovoort.</para>
      </listitem>

      <listitem>
        <para>Opstartscripts die automatisch bestandssystemen controleren en
mounten.</para>
      </listitem>

      <listitem>
        <para>Een elegante manier om het systeem af te sluiten.</para>
      </listitem>

      <listitem>
        <para>Ondersteuning voor meerdere gebruikers en virtuele terminals.</para>
      </listitem>
    </itemizedlist>

    <para>Als laatste test kunnen we de rootdisk vergelijken met de vereisten
van de Filesystem Hierarchy Standard (FHS) voor het root bestandssysteem. 
(We zullen alles in de <filename>/usr</filename> hi&euml;rarchie negeren 
vanwege de ruimtebeperkingen.) Vergeleken met de FHS vereisten, ontbreken 
er slechts een paar bestanden in de <filename>/bin</filename> directory. 
In het bijzonder ontbreken op de rootdisk de volgende opdrachten:
    </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 aanvulling op de vereiste opdrachten, zou het fraai zijn om
de editor
    &#34;ed&#34; op te nemen die als een optie door de FHS wordt opgesomd.
Het is niet zo robuust als vi of emacs, maar het werkt en het zou nog passen op het kleine root bestandssysteem.
    </para>

    <para>Dus om deze fase van het project te voltooien, moeten we de
volgende doelen bewerkstelligen:
    </para>

    <itemizedlist>
      <listitem>
        <para>De opdrachten <command>more</command>, <command>ps</command> en 
<command>sed</command> toevoegen.</para>
      </listitem>

      <listitem>
        <para>De optionele editor <command>ed</command> installeren.</para>
      </listitem>
    </itemizedlist>
  </sect1>

  <sect1>
    <title>Ontwerp</title>

    <sect2>
      <title>more</title>

<para>Er bestaat een <command>more</command> opdracht die met util-linux wordt
geleverd, maar het zal voor dit project niet werken. De reden hiervan zijn
de library afhankelijkheden en ruimtebeperkingen. De util-linux dat
<command>more</command> meelevert heeft of de libncursus of libtermcap nodig
om te kunnen werken en er is gewoon niet voldoende ruimte op de rootdisk
om alles erop te krijgen. Dus voor een opdracht
<command>more</command> zullen we creatief moeten zijn.
      </para>

<para>De opdracht <command>more</command> wordt gebruikt om een bestand
pagina-voor-pagina weer te geven. Het lijkt wat op een <command>cat</command> 
opdracht die elke vijfentwintig regels pauzeert. De basislogica wordt hieronder
uiteengezet.
      </para>

      <itemizedlist>
        <listitem>
          <para>Lees een regel van het bestand.</para>
        </listitem>

        <listitem>
          <para>Toon de regel op het scherm.</para>
        </listitem>

        <listitem>
          <para>Pauzeer zodra 25 regels zijn getoond.</para>
        </listitem>

        <listitem>
          <para>Loop en doe het nogmaals.</para>
        </listitem>
      </itemizedlist>

      <para>Natuurlijk zijn er een aantal details achterwege gelaten zoals
wat te doen als de schermdimensies niet zijn waarop we anticipeerde, maar
in z'n totaal is het een duidelijke representatie van wat
<command>more</command> doet. Gegeven de logica van dit voorbeeldprogramma,
zou het niet al te moeilijk moeten zijn om een beknopt shellscript
samen te stellen dat de basisfunctionaliteit van 
<command>more</command> emuleert. De BASH(1) manpage en
      Adv-BASH-Scripting-Guide zullen als referenties dienen.</para>
    </sect2>

    <sect2>
      <title>Meer device bestanden</title>

      <para>Het <command>more</command> script zal toegang tot devicebestanden
nodig hebben die nog niet op de rootdisk aanwezig zijn.
      In het bijzonder heeft <command>more</command> <filename>stdin</filename>,<filename>stdout</filename> en <filename>stderr</filename> nodig,
      maar nu we er toch mee bezig zijn, kunnen we net zo goed op andere
ontbrekende <filename>/dev</filename> bestanden controleren. 
De Linux Standard Base vereist
dat <filename>null</filename>, <filename>zero</filename> en <filename>tty</filename> aanwezig zijn in de <filename>/dev</filename> directory. Bestanden voor
<filename>null</filename> en <filename>tty</filename> bestaan reeds vanuit 
eerdere fasen in het project, maar we hebben nog wel 
<filename>/dev/zero</filename> nodig. We kunnen refereren naar
<filename>devices.txt</filename> in de <filename>Documentation</filename>
directory van de Linux broncode voor major en minor nummers.
</para>
    </sect2>

    <sect2>
      <title>ps, sed &#38; ed</title>

      <para>Deze drie packages kunnen worden gevonden door gebruik te
maken van dezelfde Internetbronnen als we eerder deden. Het procps
package komt tevoorschijn in een Ibiblio LSM zoekactie
      (<ulink url="http://www.ibiblio.org/pub/linux/">http://www.ibiblio.org/pub/linux/</ulink>)
      op het trefwoord &#34;ps&#34;. De &#34;sed&#34; en &#34;ed&#34;
      packages zijn te vinden op de GNU ftp server op <ulink
      url="ftp://ftp.gnu.org">ftp://ftp.gnu.org</ulink>.</para>

<para>Zowel &#34;sed&#34; als &#34;ed&#34; packages kenmerken GNU&#39;s bekende <command>configure</command> script en zijn daarom makkelijk te bouwen. Er is
geen <command>configure</command> script voor &#34;procps&#34; maar dit maakt 
het niet al te moeilijk. We kunnen gewoon het bestand 
<filename>INSTALL</filename> lezen om erachter te komen hoe de diverse 
configuratie-opties in te stellen. We kunnen &eacute;&eacute;n van deze 
opties gebruiken om de complexiteit in het gebruik en het installeren van 
libproc te voorkomen. De instelling <parameter>SHARED=0</parameter> maakt
<filename>libproc</filename> een ge&iuml;ntegreerd deel van 
<command>ps</command> in plaats van een aparte, gedeelde library.</para>
    </sect2>
  </sect1>

  <sect1>
    <title>Constructie</title>

    <sect2>
      <title>Schrijf een &#34;more&#34; script</title>

      <para>Maak het volgende script aan met een teksteditor en sla het op 
als <filename>~/fase/bin/more.sh</filename></para>

      <para><programlisting>#!/bin/sh
#
# more.sh - emuleert de basisfuncties van de &#34;more&#34; binary zonder
#           dat hier ncurses of termcap library's voor nodig zijn.
#
# Veronderstel dat invoer van STDIN komt, tenzij als opdrachtregelargument
# een geldig bestand is opgegeven.
if [ -f &#34;$1&#34; ]; then
  INPUT=&#34;$1&#34;
else
  INPUT=&#34;/dev/stdin&#34;
fi
#
# Stel IFS in op een newline. Zie BASH(1) manpage voor details over IFS.
IFS=$&#39;\n&#39;
#
# Als de terminaldimensies niet reeds zijn ingesteld als shellvariabelen,
# gok dan op 80 x 25.
if [ &#34;$COLS&#34; = &#34;&#34; ]; then
  COLS=80;
fi
if [ &#34;$ROWS&#34; = &#34;&#34; ]; then
  ROWS=25;
fi
#
# Initialiseer de row counter variabele
ROW_COUNTER=$ROWS
#
# Lees &eacute;&eacute;n regel tegelijkertijd in van het invoerbestand 
# en toon het op STDOUT totdat het scherm is gevuld.
# Toon een &#34;Press &#60;Enter&#62;&#34; melding op STDERR en wacht op een
# toetsaanslag van STDERR. Ga verder tot aan het einde van het invoerbestand.
# Van elke invoerregel groter dan $COLS tekens in lengte wordt de tekst
# naar de volgende regel geplaatst en deze tellen als meerdere regels.
#
while read -n $COLS LINE_BUFFER; do
  echo &#34;$LINE_BUFFER&#34;
  ROW_COUNTER=$(($ROW_COUNTER - 1))
  if [ $ROW_COUNTER -le 1 ]; then
    echo &#34;Press &#60;ENTER&#62; for next page or &#60;CTRL&#62;+C to quit.&#34;&#62;/dev/stderr
    read&#60;/dev/stderr
    ROW_COUNTER=$ROWS
  fi
done&#60;$INPUT
#
# einde van more.sh</programlisting></para>

      <para>Maak een symbolische link naar <filename>more</filename> aan</para>

      <para><programlisting><prompt>bash#</prompt> ln -s more.sh ~/fase/bin/more</programlisting></para>
    </sect2>

    <sect2>
      <title>Maak extra devicebestanden aan</title>

      <para><programlisting>
<prompt>bash#</prompt> ln -s /proc/self/fd ~/fase/dev/fd
<prompt>bash#</prompt> ln -s fd/0 ~/fase/dev/stdin
<prompt>bash#</prompt> ln -s fd/1 ~/fase/dev/stout
<prompt>bash#</prompt> ln -s fd/2 ~/fase/dev/sterr
<prompt>bash#</prompt> mknod -m644 ~/fase/dev/zero c 1 5</programlisting></para>
    </sect2>

    <sect2>
      <title>Installeer procps</title>

<para><programlisting>
<prompt>bash#</prompt> cd /usr/src/procps-2.07
<prompt>bash#</prompt> make SHARED=0 CC=&#34;gcc -mcpu=i386&#34;
<prompt>bash#</prompt> cd ps
<prompt>bash#</prompt> cp ps ~/fase/bin</programlisting></para>
    </sect2>

    <sect2>
      <title>Installeer sed</title>

<para><programlisting>
<prompt>bash#</prompt> cd /usr/src/sed-3.02
<prompt>bash#</prompt> ./configure --host=i386-pc-linux-gnu
<prompt>bash#</prompt> make
<prompt>bash#</prompt> cd sed
<prompt>bash#</prompt> cp sed ~/fase/bin</programlisting></para>
    </sect2>

    <sect2>
      <title>Installeer ed</title>

      <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 ~/fase/bin</programlisting></para>
    </sect2>

    <sect2>
      <title>Strip binary's om ruimte te besparen</title>

      <para><programlisting>
<prompt>bash#</prompt> strip ~/fase/bin/*</programlisting></para>
    </sect2>

    <sect2>
      <title>Verzeker je van de juiste permissies</title>

      <para><programlisting>
<prompt>bash#</prompt> chown 0:0 ~/fase/bin/*
<prompt>bash#</prompt> chmod -R 755 ~/fase/bin
<prompt>bash#</prompt> chmod 4750 ~/fase/bin/su</programlisting></para>
    </sect2>

    <sect2>
      <title>Maak het rootdisk image aan</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
<prompt>bash#</prompt> mount /dev/ram7 /mnt
<prompt>bash#</prompt> cp -dpR ~/fase/* /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>Kopieer de image naar diskette</title>

      <para>Doe de diskette met het label &#34;rootdisk&#34; in het
diskettestation fd0.</para>

<para><programlisting>
<prompt>bash#</prompt> dd if=~/phase7-image.gz of=/dev/fd0 bs=1k</programlisting></para>
    </sect2>
  </sect1>

  <sect1>
    <title>Implementatie</title>

    <sect2>
      <title>Systeemstart</title>

<para>Boot op de gebruikelijke manier vanaf de diskset en log in als root.</para>
    </sect2>

    <sect2>
      <title>Test het &#34;more&#34; script</title>

<para>Geef de kernelmeldingen weer door de uitvoer van 
<command>dmesg</command> door te geven als invoer voor 
<command>more</command>:</para>

      <para><programlisting><prompt>bash#</prompt> dmesg | more</programlisting></para>

      <para>Bestudeer het <filename>local_fs</filename> script door 
<command>more</command> met een opdrachtregelargument te gebruiken.
      </para>

      <para><programlisting><prompt>bash#</prompt> more /etc/init.d/local_fs</programlisting></para>
    </sect2>

    <sect2>
      <title>Gebruik ps om de actieve processen te tonen</title>

      <para>Geef de processen weer van de gebruiker die thans is ingelogd.</para>

      <para><programlisting><prompt>bash#</prompt> ps</programlisting></para>

      <para>Toon alle beschikbare informatie over alle actieve processen.</para>

      <para><programlisting><prompt>bash#</prompt> ps -ef</programlisting></para>
    </sect2>

    <sect2>
      <title>Voer een simpel sed script uit</title>

      <para>Gebruik <command>sed</command> om een alternatieve versie van 
<filename>/etc/passwd</filename> weer te geven.</para>

      <para><programlisting><prompt>bash#</prompt> sed -e &#34;s/Legacy/Old School/&#34; /etc/passwd</programlisting></para>

      <para>Verifieer dat sed de wijzigingen niet permanent aanbracht.</para>

      <para><programlisting><prompt>bash#</prompt> cat /etc/passwd</programlisting></para>
    </sect2>

    <sect2>
      <title>Test de &#34;ed&#34; editor</title>

      <para>Gebruik <command>ed</command> om de eigenschappen van de gebruiker
&#34;daemon&#34; te wijzigen.</para>

      <para><programlisting><prompt>bash#</prompt> ed -p*
<prompt>ed*</prompt> r /etc/passwd
<prompt>ed*</prompt> %p
<prompt>ed*</prompt> /bin/s/Legacy/Old School/
<prompt>ed*</prompt> %p
<prompt>ed*</prompt> w
<prompt>ed*</prompt> q</programlisting></para>

      <para>Verifieer dat de wijzigingen permanent zijn (tenminste totdat
het systeem wordt herstart).
      </para>

      <para><programlisting><prompt>bash#</prompt> cat /etc/passwd</programlisting></para>
    </sect2>

    <sect2>
      <title>Systeem afsluiten</title>

      <para>Sluit het systeem elegant af met de opdracht 
<command>shutdown</command>.
      </para>
    </sect2>
  </sect1>
</chapter>
