]> git.ipfire.org Git - ipfire-2.x.git/commitdiff
GD-Graph fuer Maniac eingebaut
authorms <ms@ea5c0bd1-69bd-2848-81d8-4f18e57aeed8>
Sun, 18 Mar 2007 21:34:35 +0000 (21:34 +0000)
committerms <ms@ea5c0bd1-69bd-2848-81d8-4f18e57aeed8>
Sun, 18 Mar 2007 21:34:35 +0000 (21:34 +0000)
Kernel laedt ab jetzt keine Module mehr ungefragt.
Nash aktualisiert um richtige Ramdisks zu erstellen (noch unstable).
pppsetup.cgi vom Maniac eingefuegt.

git-svn-id: http://svn.ipfire.org/svn/ipfire/trunk@450 ea5c0bd1-69bd-2848-81d8-4f18e57aeed8

21 files changed:
config/kernel/kernel.config.i586
config/kernel/kernel.config.i586.smp
config/rootfiles/common/GD-Graph [new file with mode: 0644]
config/rootfiles/common/modutils
doc/packages-list.txt
html/cgi-bin/pppsetup.cgi
lfs/GD-Graph [new file with mode: 0644]
lfs/initrd
make.sh
src/install+setup/install/main.c
src/install+setup/install/probecntrl.sh
src/install+setup/install/unattended.c
src/install+setup/install/usb.c
src/nash/Makefile
src/nash/linux_fs.h
src/nash/mkinitrd
src/nash/mount_by_label.c
src/nash/mount_by_label.h
src/nash/name_to_dev_t.c [new file with mode: 0644]
src/nash/nash.8
src/nash/nash.c

index 7a2916e5b0eff9f8b194e9ff5b9c0490db7b19b2..2354e7e150f29f9e1f6000c8f0b8cf08a13b6551 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.16.42-ipfire
-# Fri Mar 16 12:03:27 2007
+# Sun Mar 18 16:54:28 2007
 #
 CONFIG_X86_32=y
 CONFIG_SEMAPHORE_SLEEPERS=y
@@ -66,7 +66,7 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_OBSOLETE_MODPARM=y
 CONFIG_MODVERSIONS=y
 # CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
+# CONFIG_KMOD is not set
 
 #
 # Block layer
index 3ef83905f9a92b4c3b992e3f0f512ca6548f0bf0..06391324a67d17b64b8ea4a79bfec9db65329ab9 100644 (file)
@@ -67,7 +67,7 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_OBSOLETE_MODPARM=y
 CONFIG_MODVERSIONS=y
 # CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
+# CONFIG_KMOD is not set
 CONFIG_STOP_MACHINE=y
 
 #
diff --git a/config/rootfiles/common/GD-Graph b/config/rootfiles/common/GD-Graph
new file mode 100644 (file)
index 0000000..8c9a8d9
--- /dev/null
@@ -0,0 +1,27 @@
+#usr/lib/perl5/site_perl/5.8.8/GD
+#usr/lib/perl5/site_perl/5.8.8/GD/Graph
+usr/lib/perl5/site_perl/5.8.8/GD/Graph.pm
+usr/lib/perl5/site_perl/5.8.8/GD/Graph/Data.pm
+usr/lib/perl5/site_perl/5.8.8/GD/Graph/Error.pm
+usr/lib/perl5/site_perl/5.8.8/GD/Graph/FAQ.pod
+usr/lib/perl5/site_perl/5.8.8/GD/Graph/area.pm
+usr/lib/perl5/site_perl/5.8.8/GD/Graph/axestype.pm
+#usr/lib/perl5/site_perl/5.8.8/GD/Graph/axestype.pm.orig
+usr/lib/perl5/site_perl/5.8.8/GD/Graph/bars.pm
+#usr/lib/perl5/site_perl/5.8.8/GD/Graph/bars.pm.orig
+usr/lib/perl5/site_perl/5.8.8/GD/Graph/colour.pm
+usr/lib/perl5/site_perl/5.8.8/GD/Graph/hbars.pm
+usr/lib/perl5/site_perl/5.8.8/GD/Graph/lines.pm
+usr/lib/perl5/site_perl/5.8.8/GD/Graph/linespoints.pm
+usr/lib/perl5/site_perl/5.8.8/GD/Graph/mixed.pm
+usr/lib/perl5/site_perl/5.8.8/GD/Graph/pie.pm
+usr/lib/perl5/site_perl/5.8.8/GD/Graph/points.pm
+usr/lib/perl5/site_perl/5.8.8/GD/Graph/utils.pm
+#usr/lib/perl5/site_perl/5.8.8/i586-linux/auto/GD/Graph
+#usr/lib/perl5/site_perl/5.8.8/i586-linux/auto/GD/Graph/.packlist
+#usr/share/man/man3/GD::Graph.3
+#usr/share/man/man3/GD::Graph::Data.3
+#usr/share/man/man3/GD::Graph::Error.3
+#usr/share/man/man3/GD::Graph::FAQ.3
+#usr/share/man/man3/GD::Graph::colour.3
+#usr/share/man/man3/GD::Graph::hbars.3
index 4944e386d26a914d9fa9940ccbaa9c3e7ece98de..f6533340c1f2b2a2c190d1410bf88669df502614 100644 (file)
@@ -1,8 +1,8 @@
 bin/lsmod
 sbin/depmod
-#sbin/generate-modprobe.conf
+sbin/generate-modprobe.conf
 sbin/insmod
-#sbin/insmod.static
+sbin/insmod.static
 sbin/modinfo
 sbin/modprobe
 sbin/rmmod
index 05f96c49b60cbfa1ebc31ecf1ffe007755c6c876..9ec6e6508ffdb9c6d0c7285bc0de97826f3e2b31 100644 (file)
@@ -10,6 +10,7 @@
 * Digest-HMAC-1.01
 * Digest-SHA1-2.10
 * GD-2.35
+* GDGraph-1.4308
 * Geo-IP-PurePerl-1.17
 * HTML-Parser-3.45
 * HTML-Tagset-3.04
index aeaaf5c5258cca23185e5c8ff9c6e0d123acd8d1..d81a4fe7a6a0d8fc4fa8c2ca19be278232aea19d 100644 (file)
@@ -457,11 +457,10 @@ $checked{'DNS'}{'Manual'} = '';
 $checked{'DNS'}{$pppsettings{'DNS'}} = "checked='checked'";
 
 &Header::openpage($Lang::tr{'ppp setup'}, 1, '');
-
 &Header::openbigbox('100%', 'left', '', $errormessage);
 
 if ($errormessage) {
-       &Header::openbox('100%', 'left', $Lang::tr{'error messages'});
+       &Header::openbox('100%', 'center', $Lang::tr{'error messages'});
        print "<CLASS name='base'>$errormessage\n";
        print "&nbsp;</CLASS>\n";
        &Header::closebox();
@@ -472,13 +471,13 @@ if ($errormessage) {
 ### Box for selecting profile
 ###
 print "<form method='post' action='$ENV{'SCRIPT_NAME'}'>\n";
-&Header::openbox('100%', 'left', $Lang::tr{'profiles'});
+&Header::openbox('100%', 'center', $Lang::tr{'profile'});
 print <<END
-<table width='100%'>
+<table width='95%' cellspacing='0'>
 <tr>
-       <td align='right'>$Lang::tr{'profile'}:</td>
-       <td>
-       <select name='PROFILE'>
+       <td align='left'>$Lang::tr{'profile'}</td>
+       <td align='left'>
+       <select name='PROFILE' style="width: 165px">
 END
 ;
 for ($c = 1; $c <= $maxprofiles; $c++)
@@ -487,21 +486,25 @@ for ($c = 1; $c <= $maxprofiles; $c++)
 }
 print <<END
        </select></td>
-       <td><input type='submit' name='ACTION' value='$Lang::tr{'select'}' /></td>
-       <td><input type='submit' name='ACTION' value='$Lang::tr{'delete'}' /></td>
-       <td width='30%'><input type='submit' name='ACTION' value='$Lang::tr{'restore'}' /></td>
+       <td align='left'><input type='submit' name='ACTION' value='$Lang::tr{'select'}' /></td>
+       <td align='left'><input type='submit' name='ACTION' value='$Lang::tr{'delete'}' /></td>
+       <td align='left'><input type='submit' name='ACTION' value='$Lang::tr{'restore'}' /></td>
 </tr>
 </table>
+<br></br>
+<hr></hr>
 END
 ;
+
 &Header::closebox();
-&Header::openbox('100%', 'left', $Lang::tr{'connection'}.':');
+&Header::openbox('100%', 'center', $Lang::tr{'connection'});
+
 print <<END
-<table width='100%'>
+<table width='95%' cellspacing='0'>
 <tr>
-       <td align='right'>$Lang::tr{'interface'}:</td>
-       <td>
-       <select name='TYPE'>
+       <td width='25%'>$Lang::tr{'interface'}:</td>
+       <td width='25%'>
+       <select name='TYPE' style="width: 165px">
        <option value='modem' $selected{'TYPE'}{'modem'}>$Lang::tr{'modem'}</option>
        <option value='serial' $selected{'TYPE'}{'serial'}>$Lang::tr{'serial'}</option>
 END
@@ -529,32 +532,29 @@ END
 }
        print <<END
        <option value='fritzdsl' $selected{'TYPE'}{'fritzdsl'}>Fritz!DSL</option>
-       <option value='pulsardsl' $selected{'TYPE'}{'pulsardsl'}>Pulsar ADSL</option>
-       <option value='bewanadsl' $selected{'TYPE'}{'bewanadsl'}>Bewan ADSL PCI st/USB st</option>
-       <option value='conexantpciadsl' $selected{'TYPE'}{'conexantpciadsl'}>Conexant PCI ADSL</option>
        </select></td>
-       <td width='50%'><input type='submit' name='ACTION' value='$Lang::tr{'refresh'}' /></td>
+       <td colspan='2' width='50%'><input type='submit' name='ACTION' value='$Lang::tr{'refresh'}'></td>
        </tr>
        <tr>
-       <td align='right'>USB:</td>
+       <td colspan='2' width='50%'>USB:</td>
 END
 ;
 if (-f "/proc/bus/usb/devices") {
        my $usb=`lsmod | cut -d ' ' -f1 | grep -E "hci"`;
        if ($usb eq '') {
-               print "\t<td>$Lang::tr{'not running'}</td></tr>\n";
+               print "\t<td colspan='2' width='50%'>$Lang::tr{'not running'}</td></tr>\n";
        } else {
-               print "\t<td>$usb</td></tr>\n";
+               print "\t<td colspan='2' width='50%'>$usb</td></tr>\n";
        }
 }
 
 if ($pppsettings{'TYPE'}) {
-       print "</table><table width='100%'>";
+       print "<tr><td colspan='4' width='100%'><br></br></td></tr>";
        if ($pppsettings{'TYPE'} =~ /^(modem|serial|isdn)$/) {
                print <<END
 <tr>
-       <td align='right'>$Lang::tr{'interface'}:</td>
-       <td><select name='COMPORT'>
+       <td colspan='3' width='75%'>$Lang::tr{'interface'}:</td>
+       <td width='25%'><select name='COMPORT' style="width: 165px">
 END
 ;
                if ($pppsettings{'TYPE'} =~ /^(modem|serial)$/ ) {
@@ -576,13 +576,15 @@ END
                <option value='isdn1' $selected{'COMPORT'}{'isdn1'}>$Lang::tr{'isdn1'}</option>
                <option value='isdn2' $selected{'COMPORT'}{'isdn2'}>$Lang::tr{'isdn2'}</option>
        </select></td>
+ </tr>
 END
 ;
                }
                if ($pppsettings{'TYPE'} =~ /^(modem|serial)$/ ) {
                        print <<END
-       <td align='right'>$Lang::tr{'computer to modem rate'}</td>
-       <td><select name='DTERATE'>
+  <tr>
+   <td colspan='3' width='75%'>$Lang::tr{'computer to modem rate'}</td>
+        <td width='25%'><select name='DTERATE' style="width: 165px">
                <option value='9600' $selected{'DTERATE'}{'9600'}>9600</option>
                <option value='19200' $selected{'DTERATE'}{'19200'}>19200</option>
                <option value='38400' $selected{'DTERATE'}{'38400'}>38400</option>
@@ -594,30 +596,28 @@ END
 </tr>
 END
 ;
-               } else {
-                       print "<td colspan='2'>&nbsp;</td></tr>\n";
-               }
+               } 
                if ($pppsettings{'TYPE'} =~ /^(modem|isdn)$/ ) {
-                       print "<tr><td align='right'>$Lang::tr{'number'}</td>\n";
-                       print "<td><input type='text' name='TELEPHONE' value='$pppsettings{'TELEPHONE'}' /></td>\n";
+                       print "<tr><td colspan='3' width='75%'>$Lang::tr{'number'}</td>\n";
+                       print "<td width='25%'><input type='text' name='TELEPHONE' value='$pppsettings{'TELEPHONE'}'></td><tr>\n";
                        if ($pppsettings{'TYPE'} eq 'modem' ) {
-                               print "<td align='right'>$Lang::tr{'modem speaker on'}</td>\n";
-                               print "<td><input type='checkbox' name='SPEAKER' $checked{'SPEAKER'}{'on'} /></td></tr>\n";
-                       } else {
-                               print "<td colspan='2'>&nbsp;</td></tr>\n";
-                       }
+                               print "<tr><td colspan='3' width='75%'>$Lang::tr{'modem speaker on'}</td>\n";
+                               print "<td width='25%'><input type='checkbox' name='SPEAKER' $checked{'SPEAKER'}{'on'} /></td></tr>\n";
+                       } 
                }
        }
        if ($pppsettings{'TYPE'} eq 'modem') {
                print <<END
 <tr>
-       <td align='right'>$Lang::tr{'dialing mode'}</td>
-       <td><select name='DIALMODE'>
+       <td colspan='3' width='75%'>$Lang::tr{'dialing mode'}</td>
+       <td width='25%'><select name='DIALMODE' style="width: 165px">
                <option value='T' $selected{'DIALMODE'}{'T'}>$Lang::tr{'tone'}</option>
                <option value='P' $selected{'DIALMODE'}{'P'}>$Lang::tr{'pulse'}</option>
        </select></td>
-       <td align='right'>$Lang::tr{'send cr'}</td>
-       <td><input type='checkbox' name='SENDCR' $checked{'SENDCR'}{'on'} /></td>
+</tr>
+<tr>
+  <td colspan='3' width='75%'>$Lang::tr{'send cr'}</td>
+       <td width='50%'><input type='checkbox' name='SENDCR' $checked{'SENDCR'}{'on'} /></td>
 </tr>
 END
 ; 
@@ -625,41 +625,46 @@ END
 
 print <<END
 <tr>
-       <td align='right'>$Lang::tr{'idle timeout'}</td>
-       <td><input type='text' size='5' name='TIMEOUT' value='$pppsettings{'TIMEOUT'}' /></td>
-       <td colspan='2'>&nbsp;</td>
+       <td colspan='3' width='75%'>$Lang::tr{'idle timeout'}</td>
+       <td width='25%'><input type='text' name='TIMEOUT' value='$pppsettings{'TIMEOUT'}' /></td>
 </tr>
 END
 ;
        if ( $netsettings{'CONFIG_TYPE'} =~ /^(2|3|6|7)$/ && ( $netsettings{'RED_TYPE'} eq "DHCP" || $netsettings{'RED_TYPE'} eq "STATIC") ) {
                $pppsettings{'AUTOCONNECT'} = 'on';
-               print "<tr><td align='right'>$Lang::tr{'connect on ipfire restart'}</td>\n";
-               print "<td><input type='checkbox' disabled='disabled' name='AUTOCONNECT' value='on' $checked{'AUTOCONNECT'}{'on'} /></td>\n";
+               print "<tr><td colspan='3' width='75%'>$Lang::tr{'connect on ipfire restart'}</td>\n";
+               print "<td width='25%'><input type='checkbox' disabled='disabled' name='AUTOCONNECT' value='on' $checked{'AUTOCONNECT'}{'on'}></td>\n";
        } else {
-               print "<tr><td align='right'>$Lang::tr{'connect on ipfire restart'}</td>\n";
-               print "<td><input type='checkbox' name='AUTOCONNECT' value='on' $checked{'AUTOCONNECT'}{'on'} /></td>\n";
+               print "<tr><td colspan='3' width='75%'>$Lang::tr{'connect on ipfire restart'}</td>\n";
+               print "<td width='25%'><input type='checkbox' name='AUTOCONNECT' value='on' $checked{'AUTOCONNECT'}{'on'}></td>\n";
        }
 print <<END
-       <td align='right'>$Lang::tr{'connection debugging'}:</td>
-       <td><input type='checkbox' name='DEBUG' $checked{'DEBUG'}{'on'} /></td>
-</tr>
+ </tr>
+ <tr>
+  <td colspan='3' width='75%'>$Lang::tr{'connection debugging'}:</td>
+       <td width='25%'><input type='checkbox' name='DEBUG' $checked{'DEBUG'}{'on'} /></td>
+ </tr>
+ <tr>
+  <td colspan='4' width='100%'><br></br></td></tr>
 <tr>
-       <td colspan='5'><br /><hr /><b>$Lang::tr{'reconnection'}:</b></td>
+       <td colspan='4' width='100%' bgcolor='${Header::table1colour}'><b>$Lang::tr{'reconnection'}:</b></td>
 </tr>
 <tr>
-       <td colspan='4'>
-               <input type='radio' name='RECONNECTION' value='manual' $checked{'RECONNECTION'}{'manual'} />$Lang::tr{'manual'}</td>
+       <td colspan='4' width='100%'><input type='radio' name='RECONNECTION' value='manual' $checked{'RECONNECTION'}{'manual'}>$Lang::tr{'manual'}</td>
 </tr>
+<tr>
+       <td colspan='4' width='100%'><input type='radio' name='RECONNECTION' value='dialondemand' $checked{'RECONNECTION'}{'dialondemand'}>$Lang::tr{'dod'}</td>
+ </tr>
 END
 ;
 if ($pppsettings{'TYPE'} ne 'isdn') {
 print <<END
-<tr>
-       <td>
              <input type='radio' name='RECONNECTION' value='persistent' $checked{'RECONNECTION'}{'persistent'} />$Lang::tr{'persistent'}</td>
      <td colspan='2' align='right'>$Lang::tr{'backupprofile'}:</td>
-       <td>
-       <select name='BACKUPPROFILE'>
+ <tr>
+       <td colspan='4' width='100%'><input type='radio' name='RECONNECTION' value='persistent' $checked{'RECONNECTION'}{'persistent'}>$Lang::tr{'persistent'}</td>
</tr>
<tr>
+  <td colspan='3' width='75%'>$Lang::tr{'backupprofile'}:</td>
+       <td width='25%'><select name='BACKUPPROFILE' style="width: 165px">
 END
 ;
        for ($c = 1; $c <= $maxprofiles; $c++) {
@@ -672,34 +677,34 @@ END
 ;
 }
 print <<END
+ <tr>
+       <td colspan='3' width='75%'>$Lang::tr{'dod for dns'}</td>
+  <td width='25%'><input type='checkbox' name='DIALONDEMANDDNS' $checked{'DIALONDEMANDDNS'}{'on'} /></td>
+</tr>
 <tr>
-       <td>
-               <input type='radio' name='RECONNECTION' value='dialondemand' $checked{'RECONNECTION'}{'dialondemand'} />$Lang::tr{'dod'}</td>
-       <td colspan='2' align='right'>$Lang::tr{'dod for dns'}</td>
-       <td><input type='checkbox' name='DIALONDEMANDDNS' $checked{'DIALONDEMANDDNS'}{'on'} /></td>
-
+       <td colspan='3' width='75%'>$Lang::tr{'holdoff'}:</td>
+       <td width='25%'><input type='text' name='HOLDOFF' value='$pppsettings{'HOLDOFF'}' /></td>
 </tr>
 <tr>
-       <td align='right'>$Lang::tr{'holdoff'}:</td>
-       <td><input type='text' size='5' name='HOLDOFF' value='$pppsettings{'HOLDOFF'}' /></td>
-       <td align='right'>$Lang::tr{'maximum retries'}</td>
-       <td><input type='text' size='5' name='MAXRETRIES' value='$pppsettings{'MAXRETRIES'}' /></td>
+       <td colspan='3' width='75%'>$Lang::tr{'maximum retries'}</td>
+       <td width='25%'><input type='text' name='MAXRETRIES' value='$pppsettings{'MAXRETRIES'}' /></td>
 </tr>
 END
 ;
 
 if ($pppsettings{'TYPE'} eq 'isdn') {
        print <<END
-</table>
-<table width='100%'>
+<tr><td colspan='4' width='100%'><br></br></td></tr>
 <tr>
-       <td colspan='5'><br /><hr /><b>$Lang::tr{'isdn settings'}</b></td>
+       <td colspan='4' width='100%' bgcolor='${Header::table1colour}'><b>$Lang::tr{'isdn settings'}</b></td>
 </tr>
 <tr>
-       <td align='right'>$Lang::tr{'use ibod'}</td>
-       <td><input type='checkbox' name='USEIBOD' $checked{'USEIBOD'}{'on'} /></td>
-       <td align='right'>$Lang::tr{'use dov'}</td>
-       <td><input type='checkbox' name='USEDOV' $checked{'USEDOV'}{'on'} /></td>
+       <td colspan='3' width='75%'>$Lang::tr{'use ibod'}</td>
+       <td width='25%'><input type='checkbox' name='USEIBOD' $checked{'USEIBOD'}{'on'} /></td>
+</tr>
+<tr>
+       <td colspan='3' width='75%'>$Lang::tr{'use dov'}</td>
+       <td width='25%'><input type='checkbox' name='USEDOV' $checked{'USEDOV'}{'on'} /></td>
 </tr>
 END
 ;
@@ -708,29 +713,24 @@ END
 if ($pppsettings{'TYPE'} eq 'pptp')
 {
 print <<END
-</table>
-
-<table width='100%'>
+<tr><td colspan='4' width='100%'><br></br></td></tr>
 <tr>
-       <td colspan='5'><br /><hr /><b>$Lang::tr{'pptp settings'}</b></td>
+       <td colspan='4' width='100%' bgcolor='${Header::table1colour}'><b>$Lang::tr{'pptp settings'}</b></td>
 </tr>
 <tr>
-       <td colspan='2' align='right'>$Lang::tr{'phonebook entry'}</td>
-       <td><input type='text' name='PHONEBOOK' value='$pppsettings{'PHONEBOOK'}' /></td>
+       <td width='25%'>$Lang::tr{'phonebook entry'}</td>
+       <td colspan='2' width='50%'></td>
+       <td width='25%'><input type='text' name='PHONEBOOK' value='$pppsettings{'PHONEBOOK'}' /></td>
 </tr>
 <tr>
-       <td><input type='radio' name='METHOD' value='STATIC' $checked{'METHOD'}{'STATIC'} />$Lang::tr{'static ip'}</td>
-       <td align='right'>$Lang::tr{'router ip'}</td>
-       <td><input type='text' name='ROUTERIP' value='$pppsettings{'ROUTERIP'}' /></td>
+       <td width='25%'><input type='radio' name='METHOD' value='STATIC' $checked{'METHOD'}{'STATIC'} />$Lang::tr{'static ip'}</td>
+       <td colspan='2' width='50%'>$Lang::tr{'router ip'}</td>
+       <td width='25%'><input type='text' name='ROUTERIP' value='$pppsettings{'ROUTERIP'}' /></td>
 </tr>
 <tr>
-       <td>&nbsp;</td>
-       <td colspan='3'><hr /></td>
-</tr>
-<tr>
-       <td><input type='radio' name='METHOD' value='DHCP' $checked{'METHOD'}{'DHCP'} />$Lang::tr{'dhcp mode'}</td>
-       <td align='right'>$Lang::tr{'hostname'}:&nbsp;<img src='/blob.gif' alt='*' /></td>
-       <td><input type='text' name='DHCP_HOSTNAME' value='$pppsettings{'DHCP_HOSTNAME'}' /></td>
+       <td width='25%'><input type='radio' name='METHOD' value='DHCP' $checked{'METHOD'}{'DHCP'} />$Lang::tr{'dhcp mode'}</td>
+       <td colspan='2' width='50%'>$Lang::tr{'hostname'}:&nbsp;<img src='/blob.gif' alt='*' /></td>
+       <td width='25%'><input type='text' name='DHCP_HOSTNAME' value='$pppsettings{'DHCP_HOSTNAME'}' /></td>
 </tr>
 END
 ;
@@ -738,180 +738,59 @@ END
 if ($pppsettings{'TYPE'} eq 'pppoe')
 {
 print <<END
-</table>
-<table width='100%'>
-<tr>
-       <td colspan='5'><br /><hr /><b>$Lang::tr{'pppoe settings'}</b></td>
-</tr>
-END
-;
-}
-if ($pppsettings{'TYPE'} =~ /^(alcatelusb|alcatelusbk|amedynusbadsl|conexantusbadsl|conexantpciadsl|3cp4218usbadsl|pulsardsl|eciadsl|fritzdsl|bewanadsl|eagleusbadsl)$/)
-{
-
-print <<END
-</table>
-<table width='100%'>
-<tr>
-       <td colspan='5'><br /><hr /><b>$Lang::tr{'adsl settings'}:</b></td>
-</tr>
-<tr>
-       <td nowrap='nowrap' align='right'>$Lang::tr{'vpi number'}</td>
-       <td><input type='text' size='5' name='VPI' value='$pppsettings{'VPI'}' /></td>
-       <td align='right'>$Lang::tr{'vci number'}</td>
-       <td colspan='2'><input type='text' size='5' name='VCI' value='$pppsettings{'VCI'}' /></td>
-</tr>
-<tr>
-       <td>&nbsp;</td>
-       <td colspan='4'><hr /></td>
-</tr>
-END
-;
-}
-if ($pppsettings{'TYPE'} eq 'bewanadsl')
-{
-print <<END
+<tr><td colspan='4' width='100%'><br></br></td></tr>
 <tr>
-       <td align='right'>$Lang::tr{'modem'}:</td>
-       <td colspan='2' nowrap='nowrap'>
-               <input type='radio' name='MODEM' value='PCIST' $checked{'MODEM'}{'PCIST'} />Bewan ADSL PCI st</td>
-       <td colspan='2'><input type='radio' name='MODEM' value='USB' $checked{'MODEM'}{'USB'} />Bewan ADSL USB st</td>
+       <td colspan='4' width='100%' bgcolor='${Header::table1colour}'><b>$Lang::tr{'pppoe settings'}</b></td>
 </tr>
 <tr>
-       <td>&nbsp;</td>
-       <td colspan='4'><hr /></td>
-</tr>
-END
-;
-}
-if ($pppsettings{'TYPE'} =~ /^(3cp4218usbadsl|bewanadsl)$/)
-{
-print <<END
-<tr>
-       <td align='right'>$Lang::tr{'modulation'}:</td>
-       <td><input type='radio' name='MODULATION' value='AUTO' $checked{'MODULATION'}{'AUTO'} />$Lang::tr{'automatic'}</td>
-       <td><input type='radio' name='MODULATION' value='ANSI' $checked{'MODULATION'}{'ANSI'} />ANSI T1.483</td>
-       <td><input type='radio' name='MODULATION' value='GDMT' $checked{'MODULATION'}{'GDMT'} />G.DMT</td>
-       <td><input type='radio' name='MODULATION' value='GLITE' $checked{'MODULATION'}{'GLITE'} />G.Lite</td>
+       <td width='25%'><input type='radio' name='METHOD' value='PPPOE_PLUGIN' $checked{'METHOD'}{'PPPOE_PLUGIN'} />PPPoE plugin</td>
+       <td colspan='2' width='50%'>$Lang::tr{'service name'}&nbsp;<img src='/blob.gif' alt='*' /></td>
+       <td width='25%'><input type='text' name='SERVICENAME' value='$pppsettings{'SERVICENAME'}' /></td>
 </tr>
 <tr>
-       <td>&nbsp;</td>
-       <td colspan='4'><hr /></td>
+       <td width='25%'><input type='radio' name='METHOD' value='PPPOE' $checked{'METHOD'}{'PPPOE'} />$Lang::tr{'pppoe'}</td>
+       <td colspan='2' width='50%'>$Lang::tr{'concentrator name'}&nbsp;<img src='/blob.gif' alt='*' /></td>
+       <td width='25%'><input type='text' name='CONCENTRATORNAME' value='$pppsettings{'CONCENTRATORNAME'}' /></td>
 </tr>
 END
 ;
 }
 
-if ($pppsettings{'TYPE'} eq 'eagleusbadsl')
+if ($pppsettings{'TYPE'} eq 'fritzdsl')
 {
 print <<END
+<tr><td colspan='4' width='100%'><br></br></td></tr>
 <tr>
-       <td align='right'>$Lang::tr{'country'}:</td>
-       <td>
-       <select name='LINE'>
-       <option value='WO' $selected{'LINE'}{'WO'}>$Lang::tr{'other countries'}</option>
-       <option value='ES' $selected{'LINE'}{'ES'}>ESPANA</option>
-       <option value='ES03' $selected{'LINE'}{'ES03'}>ESPANA03</option>
-       <option value='FR' $selected{'LINE'}{'FR'}>FRANCE</option>
-       <option value='FR04' $selected{'LINE'}{'FR04'}>FRANCE04</option>
-       <option value='FR10' $selected{'LINE'}{'FR04'}>FRANCE10</option>
-       <option value='IT' $selected{'LINE'}{'IT'}>ITALIA</option>
-       </select></td>
+       <td colspan='4' width='100%' bgcolor='${Header::table1colour}'><b>$Lang::tr{'adsl settings'}:</b></td>
 </tr>
 <tr>
-       <td>&nbsp;</td>
-       <td colspan='4'><hr /></td>
-</tr>
-END
-;
-}
-if ($pppsettings{'TYPE'} eq 'eciadsl')
-{
-print <<END
-<tr>
-       <td align='right'>$Lang::tr{'modem'}:</td>
-       <td colspan='5'>
-               <select name='MODEM'>
-END
-;
-               open (MODEMS, "/etc/eciadsl/modems.db") or die 'Unable to open modems database.';
-               while (my $line = <MODEMS>) {
-                       $line =~ /^([\S\ ]+).*$/;
-                       my $modem = $1;
-                       $modem =~ s/^\s*(.*?)\s*$/$1/;
-                       print "<option value='$modem'";
-                       if ($pppsettings{'MODEM'} =~ /$modem/) { print " selected";}
-                       print ">$modem</option>\n";
-               }
-               close (MODEMS);
-
-print <<END
-               </select>
-       </td>
+       <td colspan='2' width='50%'>$Lang::tr{'vpi number'}</td>
+       <td colspan='2' width='50%'><input type='text' name='VPI' value='$pppsettings{'VPI'}' /></td>
 </tr>
 <tr>
-       <td>&nbsp;</td>
-       <td colspan='4'><hr /></td>
+       <td colspan='2' width='50%'>$Lang::tr{'vci number'}</td>
+       <td colspan='2' width='50%'><input type='text' name='VCI' value='$pppsettings{'VCI'}' /></td>
 </tr>
-END
-;
-}
-if ($pppsettings{'TYPE'} =~ /^(alcatelusb|alcatelusbk|amedynusbadsl|conexantusbadsl|conexantpciadsl|3cp4218usbadsl|pulsardsl|eciadsl|fritzdsl|bewanadsl|eagleusbadsl)$/)
-{
-print <<END
 <tr>
-       <td valign='top' align='right'>$Lang::tr{'protocol'}:</td>
-       <td nowrap='nowrap'>
-               <input type='radio' name='PROTOCOL' value='RFC2364' $checked{'PROTOCOL'}{'RFC2364'} />RFC2364 PPPoA</td>
-END
-;
-}
-if ($pppsettings{'TYPE'} eq 'alcatelusb')
-{
-       print "<td colspan=3>&nbsp;</td></tr>";
-}
-
-if ($pppsettings{'TYPE'} =~ /^(alcatelusbk|amedynusbadsl|conexantusbadsl|conexantpciadsl|3cp4218usbadsl|pulsardsl|eciadsl|bewanadsl|eagleusbadsl|fritzdsl)$/)
-{
-print <<END
-       <td align='right'>$Lang::tr{'encapsulation'}:</td>
-       <td colspan='2' width='30%'>
-               <select name='ENCAP_RFC2364'>
+       <td colspan='2' width='50%'>$Lang::tr{'protocol'}:</td>
+       <td colspan='2' width='50%'><input type='radio' name='PROTOCOL' value='RFC2364' $checked{'PROTOCOL'}{'RFC2364'} />RFC2364 PPPoA</td>
+ </tr>
+       <td colspan='2' width='50%'></td>
+       <td colspan='2' width='50%'><input type='radio' name='PROTOCOL' value='RFC1483' $checked{'PROTOCOL'}{'RFC1483'} />RFC 1483 / 2684</td>
+ </tr>
+ <tr>          
+       <td colspan='2' width='50%'>$Lang::tr{'encapsulation'}:</td>
+       <td colspan='2' width='50%'>
+               <select name='ENCAP_RFC2364' style="width: 165px">
                <option value='0' $selected{'ENCAP'}{'0'}>VCmux</option>
                <option value='1' $selected{'ENCAP'}{'1'}>LLC</option>
                </select>
        </td>
 </tr>
-END
-;
-}
-if ($pppsettings{'TYPE'} =~ /^(alcatelusb|alcatelusbk|amedynusbadsl|conexantusbadsl|conexantpciadsl|3cp4218usbadsl|pulsardsl|eciadsl|fritzdsl|bewanadsl|eagleusbadsl)$/)
-{
-print <<END
-<tr>
-       <td>&nbsp;</td>
-       <td colspan='4'><hr /></td>
-</tr>
 <tr>
-       <td>&nbsp;</td>
-       <td valign='top'>
-               <input type='radio' name='PROTOCOL' value='RFC1483' $checked{'PROTOCOL'}{'RFC1483'} />RFC 1483 / 2684</td>
-END
-;
-}
-if ($pppsettings{'TYPE'} eq 'alcatelusb')
-{
-       print "<td colspan='3'>&nbsp;</td></tr>";
-}
-
-if ($pppsettings{'TYPE'} =~ /^(alcatelusbk|amedynusbadsl|conexantusbadsl|conexantpciadsl|3cp4218usbadsl|pulsardsl|eciadsl|bewanadsl|eagleusbadsl|fritzdsl)$/)
-{
-       if ($pppsettings{'TYPE'} ne 'fritzdsl')
-       {
-print <<END
-       <td align='right'>$Lang::tr{'encapsulation'}:</td>
-       <td colspan='2'>
-               <select name='ENCAP_RFC1483'>
+       <td colspan='2' width='50%'>$Lang::tr{'encapsulation'}:</td>
+       <td colspan='2' width='50%'>
+               <select name='ENCAP_RFC1483' style="width: 165px">
                <option value='0' $selected{'ENCAP'}{'0'}>BRIDGED_ETH_LLC</option>
                <option value='1' $selected{'ENCAP'}{'1'}>BRIDGED_ETH_VC</option>
                <option value='2' $selected{'ENCAP'}{'2'}>ROUTED_IP_LLC</option>
@@ -919,138 +798,29 @@ print <<END
                </select>
        </td>
 </tr>
-<tr>
-       <td colspan='2'>&nbsp;</td>
-       <td colspan='3'><hr /></td>
-</tr>
-END
-;
-       } else {
-print <<END
-       <td colspan='4'>PPPoE</td>
-</tr>
-END
-;
-       }
-}
-if ($pppsettings{'TYPE'} =~ /^(pppoe|alcatelusb|alcatelusbk|amedynusbadsl|conexantusbadsl|conexantpciadsl|3cp4218usbadsl|pulsardsl|eciadsl|bewanadsl|eagleusbadsl)$/)
-{
-print <<END
-<tr>
-       <td>&nbsp;</td>
-       <td>&nbsp;</td>
-       <td><input type='radio' name='METHOD' value='PPPOE_PLUGIN' $checked{'METHOD'}{'PPPOE_PLUGIN'} />PPPoE plugin</td>
-       <td align='right'>$Lang::tr{'service name'}&nbsp;<img src='/blob.gif' alt='*' /></td>
-       <td><input type='text' name='SERVICENAME' value='$pppsettings{'SERVICENAME'}' /></td>
-</tr>
-<tr>
-       <td>&nbsp;</td>
-       <td>&nbsp;</td>
-       <td><input type='radio' name='METHOD' value='PPPOE' $checked{'METHOD'}{'PPPOE'} />$Lang::tr{'pppoe'}</td>
-       <td align='right'>$Lang::tr{'concentrator name'}&nbsp;<img src='/blob.gif' alt='*' /></td>
-       <td><input type='text' name='CONCENTRATORNAME' value='$pppsettings{'CONCENTRATORNAME'}' /></td>
-</tr>
-
-END
-;
-}
-if ($pppsettings{'TYPE'} =~ /^(alcatelusbk|amedynusbadsl|conexantusbadsl|conexantpciadsl|3cp4218usbadsl|pulsardsl|eciadsl|bewanadsl|eagleusbadsl)$/)
-{
-print <<END
-<tr>
-       <td colspan='2'>&nbsp;</td>
-       <td colspan='3'><hr /></td>
-</tr>
-<tr>
-       <td>&nbsp;</td>
-       <td>&nbsp;</td>
-       <td rowspan='4'><input type='radio' name='METHOD' value='STATIC' $checked{'METHOD'}{'STATIC'} />$Lang::tr{'static ip'}</td>
-       <td align='right'>$Lang::tr{'static ip'}:</td>
-       <td><input type='text' size='16' name='IP' value='$pppsettings{'IP'}' /></td>
-</tr>
-<tr>
-       <td>&nbsp;</td>
-       <td>&nbsp;</td>
-       <td align='right'>$Lang::tr{'gateway ip'}:</td>
-       <td><input type='text' size='16' name='GATEWAY' value='$pppsettings{'GATEWAY'}' /></td>
-</tr>
-<tr>
-       <td>&nbsp;</td>
-       <td>&nbsp;</td>
-       <td align='right'>$Lang::tr{'netmask'}:</td>
-       <td><input type='text' size='16' name='NETMASK' value='$pppsettings{'NETMASK'}' /></td>
-</tr>
-<tr>
-       <td>&nbsp;</td>
-       <td>&nbsp;</td>
-       <td align='right' nowrap='nowrap'>$Lang::tr{'broadcast'}:&nbsp;<img src='/blob.gif' alt='*' /></td>
-       <td><input type='text' size='16' name='BROADCAST' value='$pppsettings{'BROADCAST'}' /></td>
-</tr>
-END
-;
-       if ($pppsettings{'TYPE'} =~ /^(eciadsl|eagleusbadsl)$/)
-       {
-print <<END
-<tr>
-       <td colspan='2'>&nbsp;</td>
-       <td colspan='3'><hr /></td>
-</tr>
-<tr>
-       <td>&nbsp;</td>
-       <td>&nbsp;</td>
-       <td><input type='radio' name='METHOD' value='DHCP' $checked{'METHOD'}{'DHCP'} />$Lang::tr{'dhcp mode'}</td>
-       <td align='right'>$Lang::tr{'hostname'}:&nbsp;<img src='/blob.gif' alt='*' /></td>
-       <td><input type='text' name='DHCP_HOSTNAME' value='$pppsettings{'DHCP_HOSTNAME'}' /></td>
-</tr>
 END
 ;
-       }
-}
-if ($pppsettings{'TYPE'} =~ /^(alcatelusb|alcatelusbk|eciadsl|fritzdsl)$/) {
-       print "<tr><td>&nbsp;</td><td colspan='4'><hr /></td></tr>";
-}
-if ($pppsettings{'TYPE'} =~ /^(alcatelusb|alcatelusbk)$/) {
-       my $speedtouch = &Header::speedtouchversion;
-       if (($speedtouch >= 0) && ($speedtouch <=4)) {
-               my $modem;
-               if ($speedtouch ==4) { $modem='v4_b'; } else { $modem='v0123'; }
-               print "<tr><td align='right'>$Lang::tr{'firmware'}:</td>";
-               if (-e "${General::swroot}/alcatelusb/firmware.$modem.bin") {
-                       print "<td>$Lang::tr{'present'}</td><td colspan='3'>&nbsp;</td></tr>\n";
-               } else {
-                       print "<td>$Lang::tr{'not present'}</td><td colspan='3'>&nbsp;</td></tr>\n";
-               }
-       } else {
-               print "<tr><td colspan='5'>$Lang::tr{'unknown'} Rev $speedtouch</td></tr>";
-       }
-} elsif ($pppsettings{'TYPE'} eq 'eciadsl') {
-       print "<tr><td align='right'>$Lang::tr{'driver'}:</td>";
-       if (-e "${General::swroot}/eciadsl/synch.bin") {
-               print "<td>$Lang::tr{'present'}</td><td colspan='3'>&nbsp;</td></tr>\n";
-       } else {
-               print "<td>$Lang::tr{'not present'}</td><td colspan='3'>&nbsp;</td></tr>\n"; }
-} elsif ($pppsettings{'TYPE'} eq 'fritzdsl') {
-       print "<tr><td align='right'>$Lang::tr{'driver'}:</td>";
+       print "<tr><td colspan='2' width='50%'>$Lang::tr{'driver'}:</td>";
        if (-e "/lib/modules/$kernel/misc/fcdslusb.o.gz") {
-               print "<td>$Lang::tr{'present'}</td><td colspan='3'>&nbsp;</td></tr>\n";
+               print "<td colspan='2' width='50%'>$Lang::tr{'present'}</td></tr>";
        } else {
-               print "<td>$Lang::tr{'not present'}</td><td colspan='3'>&nbsp;</td></tr>\n"; }
+               print "<td colspan='2' width='50%'>$Lang::tr{'not present'}</td></tr>"; }
 }
+
 print <<END
-</table>
-<table width='100%'>
+<tr><td colspan='4' width='100%'><br></br></td></tr>
 <tr>
-       <td colspan='5'><br /><hr /><b>$Lang::tr{'authentication'}</b></td>
+       <td bgcolor='${Header::table1colour}' colspan='4' width='100%'><b>$Lang::tr{'authentication'}</b></td>
 </tr>
 <tr>
-       <td align='right'>$Lang::tr{'username'}</td>
-       <td><input type='text' name='USERNAME' value='$pppsettings{'USERNAME'}' /></td>
-       <td align='right'>$Lang::tr{'password'}</td>
-       <td><input type='password' name='PASSWORD' value='$pppsettings{'PASSWORD'}' /></td>
+       <td width='25%'>$Lang::tr{'username'}</td>
+       <td width='25%'><input type='text' name='USERNAME' value='$pppsettings{'USERNAME'}' /></td>
+       <td width='25%'>$Lang::tr{'password'}</td>
+       <td width='25%'><input type='password' name='PASSWORD' value='$pppsettings{'PASSWORD'}' /></td>
 </tr>
 <tr>
-       <td align='right'>$Lang::tr{'method'}</td>
-       <td><select name='AUTH'>
+       <td width='25%'>$Lang::tr{'method'}</td>
+       <td width='25%'><select name='AUTH' style="width: 165px">
                <option value='pap-or-chap' $selected{'AUTH'}{'pap-or-chap'}>$Lang::tr{'pap or chap'}</option>
                <option value='pap' $selected{'AUTH'}{'pap'}>PAP</option>
                <option value='chap' $selected{'AUTH'}{'chap'}>CHAP</option>
@@ -1066,39 +836,37 @@ END
 }
 print <<END
        </select></td>
-       <td align='right'>$Lang::tr{'script name'}&nbsp;<img src='/blob.gif' alt='*' /></td>
-       <td nowrap='nowrap'><input type='text' name='LOGINSCRIPT' value='$pppsettings{'LOGINSCRIPT'}' /></td>
+       <td width='25%'>$Lang::tr{'script name'}&nbsp;<img src='/blob.gif' alt='*' /></td>
+       <td width='25%'><input type='text' name='LOGINSCRIPT' value='$pppsettings{'LOGINSCRIPT'}' /></td>
 </tr>
-</table>
-<table width='100%'>
+<tr><td colspan='4' width='100%'><br></br></td></tr>
 <tr>
-       <td colspan='5'><br /><hr /><b>DNS:</b></td>
+       <td bgcolor='${Header::table1colour}' colspan='4' width='100%'><b>DNS:</b></td>
 </tr>
 <tr>
-       <td colspan='5'><input type='radio' name='DNS' value='Automatic' $checked{'DNS'}{'Automatic'} />$Lang::tr{'automatic'}</td>
+       <td colspan='4' width='100%'><input type='radio' name='DNS' value='Automatic' $checked{'DNS'}{'Automatic'} />$Lang::tr{'automatic'}</td>
 </tr>
 <tr>
-       <td><input type='radio' name='DNS' value='Manual' $checked{'DNS'}{'Manual'} />$Lang::tr{'manual'}</td>
-       <td align='right'>$Lang::tr{'primary dns'}</td>
-       <td><input type='text' size='16' name='DNS1' value='$pppsettings{'DNS1'}' /></td>
-       <td align='right'>$Lang::tr{'secondary dns'}</td>
-       <td><input type='text' size='16' name='DNS2' value='$pppsettings{'DNS2'}' /></td>
+       <td colspan='4' width='100%'><input type='radio' name='DNS' value='Manual' $checked{'DNS'}{'Manual'} />$Lang::tr{'manual'}</td>
 </tr>
 <tr>
-       <td colspan='5'><br /><hr /></td>
+       <td width='25%'>$Lang::tr{'primary dns'}</td>
+       <td width='25%'><input type='text' name='DNS1' value='$pppsettings{'DNS1'}'></td>
+       <td width='25%'>$Lang::tr{'secondary dns'}</td>
+       <td width='25%'><input type='text' name='DNS2' value='$pppsettings{'DNS2'}'></td>
 </tr>
+<tr><td colspan='4' width='100%'><br></br><hr></hr><br></br></td></tr>
 <tr>
-       <td>&nbsp;</td>
-       <td align='right'>$Lang::tr{'profile name'}</td>
-       <td><input type='text' name='PROFILENAME' value='$pppsettings{'PROFILENAME'}' /></td>
-       <td><input type='submit' name='ACTION' value='$Lang::tr{'save'}' /></td>
+       <td width='25%'>$Lang::tr{'profile name'}</td>
+       <td width='25%'><input type='text' name='PROFILENAME' value='$pppsettings{'PROFILENAME'}'>
+       <td colspan='2' width='50%'></td>
 </tr>
 <tr>
-       <td colspan='5'><br /><hr /></td>
+  <td align='center' colspan='4' width='100%'><input type='submit' name='ACTION' value='$Lang::tr{'save'}'></td>
 </tr>
 <tr>
-       <td align='right'>$Lang::tr{'legend'}:</td>
-       <td><img src='/blob.gif' alt='*' />&nbsp;$Lang::tr{'this field may be blank'}</td>
+       <td colspan='2' width='50%'>$Lang::tr{'legend'}:</td>
+       <td colspan='2' width='50%'><img src='/blob.gif' alt='*' />&nbsp;$Lang::tr{'this field may be blank'}</td>
 </tr>
 </table>
 END
diff --git a/lfs/GD-Graph b/lfs/GD-Graph
new file mode 100644 (file)
index 0000000..f32a1e4
--- /dev/null
@@ -0,0 +1,79 @@
+###############################################################################
+# This file is part of the IPCop Firewall.                                    #
+#                                                                             #
+# IPCop is free software; you can redistribute it and/or modify               #
+# it under the terms of the GNU General Public License as published by        #
+# the Free Software Foundation; either version 2 of the License, or           #
+# (at your option) any later version.                                         #
+#                                                                             #
+# IPCop is distributed in the hope that it will be useful,                    #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of              #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               #
+# GNU General Public License for more details.                                #
+#                                                                             #
+# You should have received a copy of the GNU General Public License           #
+# along with IPCop; if not, write to the Free Software                        #
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA    #
+#                                                                             #
+# Makefiles are based on LFSMake, which is                                    #
+# Copyright (C) 2002 Rod Roard <rod@sunsetsystems.com>                        #
+#                                                                             #
+###############################################################################
+
+###############################################################################
+# Definitions
+###############################################################################
+
+include Config
+
+VER        = 1.4308
+
+THISAPP    = GDGraph-$(VER)
+DL_FILE    = $(THISAPP).tar.gz
+DL_FROM    = $(URL_IPFIRE)
+DIR_APP    = $(DIR_SRC)/$(THISAPP)
+TARGET     = $(DIR_INFO)/$(THISAPP)
+
+###############################################################################
+# Top-level Rules
+###############################################################################
+
+objects = $(DL_FILE)
+
+$(DL_FILE) = $(DL_FROM)/$(DL_FILE)
+
+$(DL_FILE)_MD5 = fcdd34d5e09ae917b5d264887734b3b1
+
+install : $(TARGET)
+
+check : $(patsubst %,$(DIR_CHK)/%,$(objects))
+
+download :$(patsubst %,$(DIR_DL)/%,$(objects))
+
+md5 : $(subst %,%_MD5,$(objects))
+
+###############################################################################
+# Downloading, checking, md5sum
+###############################################################################
+
+$(patsubst %,$(DIR_CHK)/%,$(objects)) :
+       @$(CHECK)
+
+$(patsubst %,$(DIR_DL)/%,$(objects)) :
+       @$(LOAD)
+
+$(subst %,%_MD5,$(objects)) :
+       @$(MD5)
+
+###############################################################################
+# Installation Details
+###############################################################################
+
+$(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
+       @$(PREBUILD)
+       @rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar zxf $(DIR_DL)/$(DL_FILE)
+       cd $(DIR_APP) && perl Makefile.PL
+       cd $(DIR_APP) && make $(MAKETUNING)
+       cd $(DIR_APP) && make install
+       @rm -rf $(DIR_APP)
+       @$(POSTBUILD)
index bb4303bed6547d64165b53c83a05a074abc71e94..8c2bd6851872294144b888eb2371673635a9d408 100644 (file)
@@ -73,9 +73,9 @@ $(TARGET) :
        depmod -a -F /boot/System.map-$(KVER)-ipfire-smp $(KVER)-ipfire-smp
 
        cd / && tar -cvf /tmp/drivers.tar \
-               --exclude=lib/modules/$(KVER)-ipfire/kernel/{arch,fs} \
-               --exclude=lib/modules/$(KVER)-ipfire/kernel/drivers/{acpi,atm,bluetooth,block,char,cdrom,hwmon,ide} \
-               --exclude=lib/modules/$(KVER)-ipfire/kernel/drivers/{ieee1394,isdn,mmc,scsi,md,video} \
+               --exclude=lib/modules/$(KVER)-ipfire/kernel/{arch,crypto} \
+               --exclude=lib/modules/$(KVER)-ipfire/kernel/drivers/{acpi,atm,bluetooth,block,char,cdrom,connector,cpufreq,hwmon,ide} \
+               --exclude=lib/modules/$(KVER)-ipfire/kernel/drivers/{ieee1394,isdn,mmc,md,parport,video} \
                --exclude=lib/modules/$(KVER)-ipfire/kernel/drivers/net/{wan,ppp*,slip*,slhc*,tun*,wireless} \
                --exclude=lib/modules/$(KVER)-ipfire/kernel/drivers/usb/{atm,input,storage,host} \
                --exclude=lib/modules/$(KVER)-ipfire/kernel/drivers/usb/{3cp4218.ko,acm.ko,amedyn.ko,cxacru.ko} \
@@ -87,10 +87,6 @@ $(TARGET) :
        cd /install/initrd/ && tar -xvf /tmp/drivers.tar && rm -f /tmp/drivers.tar
 
        # Extra modules
-       -mkdir -p /install/initrd/lib/modules/$(KVER)-ipfire/kernel/drivers/scsi
-       cp -af /lib/modules/$(KVER)-ipfire/kernel/drivers/scsi/*.ko \
-               /install/initrd/lib/modules/$(KVER)-ipfire/kernel/drivers/scsi/
-
        -mkdir -p /install/initrd/lib/modules/$(KVER)-ipfire/kernel/drivers/usb/storage
        cp -f /lib/modules/$(KVER)-ipfire/kernel/drivers/usb/storage/*.ko \
                /install/initrd/lib/modules/$(KVER)-ipfire/kernel/drivers/usb/storage/
@@ -107,10 +103,6 @@ $(TARGET) :
        cp -f /lib/modules/$(KVER)-ipfire/kernel/drivers/usb/core/*.ko \
                /install/initrd/lib/modules/$(KVER)-ipfire/kernel/drivers/usb/core
 
-       # File system
-       -mkdir -p /install/initrd/lib/modules/$(KVER)-ipfire/kernel/fs
-       cp -rf /lib/modules/$(KVER)-ipfire/kernel/fs/* /install/initrd/lib/modules/$(KVER)-ipfire/kernel/fs
-
        cp -f /lib/modules/$(KVER)-ipfire/modules.* /install/initrd/lib/modules/$(KVER)-ipfire
 
        cp /opt/$(MACHINE)-uClibc/lib/libgcc_s.so.1 /install/initrd/lib/
diff --git a/make.sh b/make.sh
index 25b338966aafe7ae10d29b556515a16243bf6c85..9a2aaf878a0c4aba28929866f50787f89ac9a86f 100644 (file)
--- a/make.sh
+++ b/make.sh
@@ -393,6 +393,7 @@ buildipfire() {
   ipfiremake ez-ipupdate
   ipfiremake fcron
   ipfiremake GD
+  ipfiremake GD-Graph
   ipfiremake gnupg
   ipfiremake hdparm
   ipfiremake ibod
index e5e98922333bdea35099f28f418a65f3eb7dafee..9bd629dc10b506377e77f13b2c44cec3dde5db78 100644 (file)
@@ -128,7 +128,6 @@ int main(int argc, char *argv[])
                }
        }
 
-       // make some beeps before wiping the system :)
        if (unattended) {
            runcommandwithstatus("/bin/sleep 10", "WARNING: Unattended installation will start in 10 seconds...");
        }
@@ -165,8 +164,7 @@ int main(int argc, char *argv[])
                rc = newtWinMenu(ctr[TR_SELECT_INSTALLATION_MEDIA], message,
                        50, 5, 5, 6, installtypes, &installtype, ctr[TR_OK],
                        ctr[TR_CANCEL], NULL);
-       }
-       else {
+       } else {
            rc = 1;
            installtype = CDROM_INSTALL;
        }
@@ -179,7 +177,6 @@ int main(int argc, char *argv[])
 
        /* CDROM INSTALL */
        if (installtype == CDROM_INSTALL) {
-
                switch (mysystem("/bin/mountsource.sh")) {
                    case 0:
                        installtype = CDROM_INSTALL;
@@ -215,7 +212,7 @@ int main(int argc, char *argv[])
                        goto EXIT;
                }
 
-               /* Check for ipcop-<VERSION>.tbz2 */
+               /* Check for ipfire-<VERSION>.tbz2 */
                if (checktarball(SNAME "-" VERSION ".tbz2", ctr[TR_ENTER_URL])) {
                        errorbox(ctr[TR_NO_IPCOP_TARBALL_FOUND]);
                        goto EXIT;
@@ -527,36 +524,35 @@ int main(int argc, char *argv[])
        mysystem("/bin/mount -t proc none /harddisk/proc");
        mysystem("/bin/mount --bind /dev /harddisk/dev");
 
+       /* Build cache lang file */
+       snprintf(commandstring, STRING_SIZE, "/sbin/chroot /harddisk /usr/bin/perl -e \"require '" CONFIG_ROOT "/lang.pl'; &Lang::BuildCacheLang\"");
+       if (runcommandwithstatus(commandstring, ctr[TR_INSTALLING_LANG_CACHE]))
+       {
+               errorbox(ctr[TR_UNABLE_TO_INSTALL_LANG_CACHE]);
+               goto EXIT;
+       }
+
+       /* Update /etc/fstab */
+       replace("/harddisk/etc/fstab", "DEVICE", hdparams.devnode);
 
-       /* if we detected SCSI then fixup */
-       /* doesn't really work cause it sometimes creates a ramdisk on ide systems */
-/*     mysystem("/bin/probecntrl.sh");
-       if ((handle = fopen("/cntrldriver", "r")))
+       /* if we detected SCSI/USB then fixup */
+       mysystem("/bin/probecntrl.sh");
+       if ((handle = fopen("/tmp/cntrldriver", "r")))
        {
                char *driver;
-                       fgets(line, STRING_SIZE-1, handle);
-                       fclose(handle);
+               fgets(line, STRING_SIZE-1, handle);
+               fclose(handle);
                line[strlen(line) - 1] = 0;
                driver = strtok(line, ".");
-               fprintf(flog, "Detected SCSI driver %s\n",driver);
                if (strlen(driver) > 1) {
                        fprintf(flog, "Fixing up ipfirerd.img\n");
-                       mysystem("/sbin/chroot /harddisk /sbin/modprobe loop");
                        mkdir("/harddisk/initrd", S_IRWXU|S_IRWXG|S_IRWXO);
-                       snprintf(commandstring, STRING_SIZE, "/sbin/chroot /harddisk /sbin/mkinitrd --with=scsi_mod --with=%s --with=sd_mod --with=sr_mod --with=libata /boot/ipfirerd.img %s", driver, KERNEL_VERSION);
+                       snprintf(commandstring, STRING_SIZE, "/sbin/chroot /harddisk /sbin/mkinitrd --with=scsi_mod %s --with=sd_mod --with=sr_mod /boot/ipfirerd.img %s-ipfire", driver, KERNEL_VERSION);
                        runcommandwithstatus(commandstring, ctr[TR_BUILDING_INITRD]);
-                       snprintf(commandstring, STRING_SIZE, "/sbin/chroot /harddisk /sbin/mkinitrd --with=scsi_mod --with=%s --with=sd_mod --with=sr_mod --with=libata /boot/ipfirerd-smp.img %s-smp", driver, KERNEL_VERSION);
+                       snprintf(commandstring, STRING_SIZE, "/sbin/chroot /harddisk /sbin/mkinitrd --with=scsi_mod %s --with=sd_mod --with=sr_mod /boot/ipfirerd-smp.img %s-ipfire-smp", driver, KERNEL_VERSION);
                        runcommandwithstatus(commandstring, ctr[TR_BUILDING_INITRD]);
                        mysystem("/sbin/chroot /harddisk /bin/mv /boot/grub/scsigrub.conf /boot/grub/grub.conf");
                }
-       } */
-
-       /* Build cache lang file */
-       snprintf(commandstring, STRING_SIZE, "/sbin/chroot /harddisk /usr/bin/perl -e \"require '" CONFIG_ROOT "/lang.pl'; &Lang::BuildCacheLang\"");
-       if (runcommandwithstatus(commandstring, ctr[TR_INSTALLING_LANG_CACHE]))
-       {
-               errorbox(ctr[TR_UNABLE_TO_INSTALL_LANG_CACHE]);
-               goto EXIT;
        }
 
        if (raid_disk)
@@ -576,9 +572,6 @@ int main(int argc, char *argv[])
                goto EXIT;
        }
 
-       /* Update /etc/fstab */
-       replace("/harddisk/etc/fstab", "DEVICE", hdparams.devnode);
-
        /* Install bootsplash */
        mysystem("/bin/installbootsplash.sh");
 
index 6515fada4e43fe982497869d688ac6a66bf4a595..5c58a39102e9400f1421b80c96a36757e22204b4 100644 (file)
@@ -1,13 +1,19 @@
 #!/bin/sh
 
-echo "Probing for SCSI controllers"
-MODULE=`/bin/kudzu -qps  -t 30 -c SCSI | grep driver | cut -d ' ' -f 2 | sort | uniq`
+echo "Probing for storage controllers"
+for MODULE in $(hwinfo --usb --usb-ctrl --storage-ctrl | grep modprobe | awk '{ print $5 }' | tr -d \" | sort | uniq); do
+    if [ "${MODULE}" = "piix" ]; then
+        continue
+    fi
+    if grep -Eqe "^${MODULE} " /proc/modules; then
+        MODULES="${MODULES} --with=${MODULE}"
+        echo "Found: ${MODULE}"
+    fi
+done
 
-if [ "$MODULE" ]; then
-       echo $MODULE > /tmp/cntrldriver
-       echo "Your controller is: $MODULE"
+if [ -z "${MODULES}" ]; then
+       exit 1
+else
+       echo "${MODULES}" > /tmp/cntrldriver
        exit 0
 fi
-
-echo "No SCSI controller found"
-exit 1
index d7ff113a9fd320c55f0419e774d2443b70768564..0606b3d93cec0282c171b5cb194f5b0ab21fdf3e 100644 (file)
@@ -15,7 +15,7 @@
  * along with IPFire; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  *
- * Copyright 2002: Mark Wormgoor <mark@wormgoor.com>
+ * Copyright 2007: Michael Tremer for www.ipfire.org
  * 
  */
 
index 826ab1bb973f094655997c5bb9997aeeec2125a8..19b7bfb67548b6ee953eb22abab1f9c53567a9cc 100644 (file)
@@ -29,6 +29,7 @@ int initialize_usb() {
     mysystem("/sbin/modprobe sd_mod");
     mysystem("/sbin/modprobe sr_mod");
     mysystem("/sbin/modprobe usb-storage");
+    mysystem("/sbin/modprobe vfat");
 
     if (ehcihcd) {
        mysystem("/sbin/rmmod ehci-hcd");
@@ -51,7 +52,7 @@ int initialize_usb() {
        usbuhci = 1;
 
     mysystem("/sbin/modprobe usbhid");
-    mysystem("udevstart");
+    mysystem("/sbin/udevstart");
     return 0;
 }
 
index 5cb6979a1d11c442f04b853154711a977c7773f3..602fe520f3d0f6b92b2abfd15bfd3eb95398045b 100644 (file)
@@ -1,23 +1,18 @@
-CFLAGS=-Wall -DVERSION=\"$(VERSION)\" -g
+CFLAGS=-Wall -Werror -DVERSION=\"$(VERSION)\" -g  -D_FORTIFY_SOURCE=2
 VERSION=$(shell awk -F= '/^VERSION=/ { print $$2 }' mkinitrd)
 
 ARCH := $(patsubst i%86,i386,$(shell uname -m))
 ARCH := $(patsubst sparc%,sparc,$(ARCH))
 
-#ifeq (i386, $(ARCH))
-#CC:=diet $(CC)
-#CFLAGS += -DUSE_DIET=1
-#else
 STATIC=-static
-#endif
 
 mandir=usr/share/man
 
-nash: nash.o mount_by_label.o
-       $(CC) $(STATIC) -g $(LDFLAGS) -o $@ nash.o mount_by_label.o
+nash: nash.o mount_by_label.o name_to_dev_t.o
+       $(CC) $(STATIC) -g $(LDFLAGS) -o $@ $^
 
 clean:
-       rm -f nash $(MINILIBC) nash.o mount_by_label.o
+       rm -f nash $(MINILIBC) *.o
 
 install:
        mkdir -p $(BUILDROOT)/sbin
index e584220ac36f58d192254a13a0ad3fdac13be7f3..c84d4218d4f72b9bf40c12665778cd6048c3198c 100644 (file)
-/* Including <linux/fs.h> became more and more painful.\r
-   Below a very abbreviated version of some declarations,\r
-   only designed to be able to check a magic number\r
-   in case no filesystem type was given. */\r
-\r
-#ifndef BLKGETSIZE\r
-#ifndef _IO\r
-/* pre-1.3.45 */\r
-#define BLKGETSIZE 0x1260                 /* return device size */\r
-#else\r
-/* same on i386, m68k, arm; different on alpha, mips, sparc, ppc */\r
-#define BLKGETSIZE _IO(0x12,96)\r
-#endif\r
-#endif\r
-\r
-#define MINIX_SUPER_MAGIC   0x137F         /* original minix fs */\r
-#define MINIX_SUPER_MAGIC2  0x138F         /* minix fs, 30 char names */\r
-struct minix_super_block {\r
-       unsigned char   s_dummy[16];\r
-       unsigned char   s_magic[2];\r
-};\r
-#define minixmagic(s)  ((unsigned int) s.s_magic[0] + (((unsigned int) s.s_magic[1]) << 8))\r
-\r
-#define ISODCL(from, to) (to - from + 1)\r
-#define ISO_STANDARD_ID "CD001"\r
-struct iso_volume_descriptor {\r
-       char type[ISODCL(1,1)]; /* 711 */\r
-       char id[ISODCL(2,6)];\r
-       char version[ISODCL(7,7)];\r
-       char data[ISODCL(8,2048)];\r
-};\r
-\r
-#define HS_STANDARD_ID "CDROM"\r
-struct  hs_volume_descriptor {\r
-       char foo[ISODCL (  1,   8)]; /* 733 */\r
-       char type[ISODCL (  9,   9)]; /* 711 */\r
-       char id[ISODCL ( 10,  14)];\r
-       char version[ISODCL ( 15,  15)]; /* 711 */\r
-       char data[ISODCL(16,2048)];\r
-};\r
-\r
-#define EXT_SUPER_MAGIC 0x137D\r
-struct ext_super_block {\r
-       unsigned char   s_dummy[56];\r
-       unsigned char   s_magic[2];\r
-};\r
-#define extmagic(s)    ((unsigned int) s.s_magic[0] + (((unsigned int) s.s_magic[1]) << 8))\r
-\r
-#define EXT2_PRE_02B_MAGIC  0xEF51\r
-#define EXT2_SUPER_MAGIC    0xEF53\r
-#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x0004\r
-struct ext2_super_block {\r
-       unsigned char   s_dummy1[56];\r
-       unsigned char   s_magic[2];\r
-       unsigned char   s_dummy2[34];\r
-       unsigned char   s_feature_compat[4];\r
-       unsigned char   s_feature_incompat[4];\r
-       unsigned char   s_feature_ro_compat[4];\r
-       unsigned char   s_uuid[16];\r
-       unsigned char   s_volume_name[16];\r
-       unsigned char   s_dummy3[88];\r
-       unsigned char   s_journal_inum[4];      /* ext3 only */\r
-};\r
-#define ext2magic(s)   ((unsigned int) s.s_magic[0] + (((unsigned int) s.s_magic[1]) << 8))\r
-\r
-struct reiserfs_super_block\r
-{\r
-       unsigned char           s_block_count[4];\r
-       unsigned char           s_free_blocks[4];\r
-       unsigned char           s_root_block[4];\r
-       unsigned char           s_journal_block[4];\r
-       unsigned char           s_journal_dev[4];\r
-       unsigned char           s_orig_journal_size[4];\r
-       unsigned char           s_journal_trans_max[4];\r
-       unsigned char           s_journal_block_count[4];\r
-       unsigned char           s_journal_max_batch[4];\r
-       unsigned char           s_journal_max_commit_age[4];\r
-       unsigned char           s_journal_max_trans_age[4];\r
-       unsigned char           s_blocksize[2];\r
-       unsigned char           s_oid_maxsize[2];\r
-       unsigned char           s_oid_cursize[2];\r
-       unsigned char           s_state[2];\r
-       unsigned char           s_magic[12];\r
-};\r
-#define REISERFS_SUPER_MAGIC_STRING "ReIsErFs"\r
-#define REISER2FS_SUPER_MAGIC_STRING "ReIsEr2Fs"\r
-#define REISERFS_DISK_OFFSET_IN_BYTES (64 * 1024)\r
-/* the spot for the super in versions 3.5 - 3.5.10 (inclusive) */\r
-#define REISERFS_OLD_DISK_OFFSET_IN_BYTES (8 * 1024)\r
-\r
-#define _XIAFS_SUPER_MAGIC 0x012FD16D\r
-struct xiafs_super_block {\r
-    unsigned char     s_boot_segment[512];     /*  1st sector reserved for boot */\r
-    unsigned char     s_dummy[60];\r
-    unsigned char     s_magic[4];\r
-};\r
-#define xiafsmagic(s)  ((unsigned int) s.s_magic[0] + (((unsigned int) s.s_magic[1]) << 8) + \\r
-                       (((unsigned int) s.s_magic[2]) << 16) + \\r
-                       (((unsigned int) s.s_magic[3]) << 24))\r
-\r
-/* From jj@sunsite.ms.mff.cuni.cz Mon Mar 23 15:19:05 1998 */\r
-#define UFS_SUPER_MAGIC 0x00011954\r
-struct ufs_super_block {\r
-    unsigned char     s_dummy[0x55c];\r
-    unsigned char     s_magic[4];\r
-};\r
-#define ufsmagic(s)    ((unsigned int) s.s_magic[0] + (((unsigned int) s.s_magic[1]) << 8) + \\r
-                        (((unsigned int) s.s_magic[2]) << 16) + \\r
-                        (((unsigned int) s.s_magic[3]) << 24))\r
-\r
-/* From Richard.Russon@ait.co.uk Wed Feb 24 08:05:27 1999 */\r
-#define NTFS_SUPER_MAGIC "NTFS"\r
-struct ntfs_super_block {\r
-    unsigned char    s_dummy[3];\r
-    unsigned char    s_magic[4];\r
-};\r
-\r
-/* From inspection of a few FAT filesystems - aeb */\r
-/* Unfortunately I find almost the same thing on an extended partition;\r
-   it looks like a primary has some directory entries where the extended\r
-   has a partition table: IO.SYS, MSDOS.SYS, WINBOOT.SYS */\r
-struct fat_super_block {\r
-    unsigned char    s_dummy[3];\r
-    unsigned char    s_os[8];          /* "MSDOS5.0" or "MSWIN4.0" or "MSWIN4.1" */\r
-                               /* mtools-3.9.4 writes "MTOOL394" */\r
-    unsigned char    s_dummy2[32];\r
-    unsigned char    s_label[11];      /* for DOS? */\r
-    unsigned char    s_fs[8];          /* "FAT12   " or "FAT16   " or all zero   */\r
-                                /* OS/2 BM has "FAT     " here. */\r
-    unsigned char    s_dummy3[9];\r
-    unsigned char    s_label2[11];     /* for Windows? */\r
-    unsigned char    s_fs2[8];         /* garbage or "FAT32   " */\r
-};\r
-\r
-#define XFS_SUPER_MAGIC "XFSB"\r
-struct xfs_super_block {\r
-    unsigned char    s_magic[4];\r
-    unsigned char    s_dummy[28];\r
-    unsigned char    s_uuid[16];\r
-    unsigned char    s_dummy2[60];\r
-    unsigned char    s_fname[12];\r
-};\r
-\r
-#define CRAMFS_SUPER_MAGIC 0x28cd3d45\r
-struct cramfs_super_block {\r
-       unsigned char    s_magic[4];\r
-       unsigned char    s_dummy[12];\r
-       unsigned char    s_id[16];\r
-};\r
-#define cramfsmagic(s) ((unsigned int) s.s_magic[0] + (((unsigned int) s.s_magic[1]) << 8) + \\r
-                        (((unsigned int) s.s_magic[2]) << 16) + \\r
-                        (((unsigned int) s.s_magic[3]) << 24))\r
-\r
-#define HFS_SUPER_MAGIC 0x4244\r
-struct hfs_super_block {\r
-       unsigned char    s_magic[2];\r
-       unsigned char    s_dummy[18];\r
-       unsigned char    s_blksize[4];\r
-};\r
-#define hfsmagic(s)    ((unsigned int) s.s_magic[0] + (((unsigned int) s.s_magic[1]) << 8))\r
-#define hfsblksize(s)  ((unsigned int) s.s_blksize[0] + \\r
-                        (((unsigned int) s.s_blksize[1]) << 8) + \\r
-                        (((unsigned int) s.s_blksize[2]) << 16) + \\r
-                        (((unsigned int) s.s_blksize[3]) << 24))\r
-\r
-#define HPFS_SUPER_MAGIC 0xf995e849\r
-struct hpfs_super_block {\r
-       unsigned char    s_magic[4];\r
-       unsigned char    s_magic2[4];\r
-};\r
-#define hpfsmagic(s)   ((unsigned int) s.s_magic[0] + (((unsigned int) s.s_magic[1]) << 8) + \\r
-                        (((unsigned int) s.s_magic[2]) << 16) + \\r
-                        (((unsigned int) s.s_magic[3]) << 24))\r
-\r
-struct adfs_super_block {\r
-       unsigned char    s_dummy[448];\r
-       unsigned char    s_blksize[1];\r
-       unsigned char    s_dummy2[62];\r
-       unsigned char    s_checksum[1];\r
-};\r
-#define adfsblksize(s) ((unsigned int) s.s_blksize[0])\r
+/* Including <linux/fs.h> became more and more painful.
+   Below a very abbreviated version of some declarations,
+   only designed to be able to check a magic number
+   in case no filesystem type was given. */
+
+#ifndef BLKGETSIZE
+#ifndef _IO
+/* pre-1.3.45 */
+#define BLKGETSIZE 0x1260                 /* return device size */
+#else
+/* same on i386, m68k, arm; different on alpha, mips, sparc, ppc */
+#define BLKGETSIZE _IO(0x12,96)
+#endif
+#endif
+
+#define MINIX_SUPER_MAGIC   0x137F         /* original minix fs */
+#define MINIX_SUPER_MAGIC2  0x138F         /* minix fs, 30 char names */
+struct minix_super_block {
+       unsigned char   s_dummy[16];
+       unsigned char   s_magic[2];
+};
+#define minixmagic(s)  ((unsigned int) s.s_magic[0] + (((unsigned int) s.s_magic[1]) << 8))
+
+#define ISODCL(from, to) (to - from + 1)
+#define ISO_STANDARD_ID "CD001"
+struct iso_volume_descriptor {
+       char type[ISODCL(1,1)]; /* 711 */
+       char id[ISODCL(2,6)];
+       char version[ISODCL(7,7)];
+       char data[ISODCL(8,2048)];
+};
+
+#define HS_STANDARD_ID "CDROM"
+struct  hs_volume_descriptor {
+       char foo[ISODCL (  1,   8)]; /* 733 */
+       char type[ISODCL (  9,   9)]; /* 711 */
+       char id[ISODCL ( 10,  14)];
+       char version[ISODCL ( 15,  15)]; /* 711 */
+       char data[ISODCL(16,2048)];
+};
+
+#define EXT_SUPER_MAGIC 0x137D
+struct ext_super_block {
+       unsigned char   s_dummy[56];
+       unsigned char   s_magic[2];
+};
+#define extmagic(s)    ((unsigned int) s.s_magic[0] + (((unsigned int) s.s_magic[1]) << 8))
+
+#define EXT2_PRE_02B_MAGIC  0xEF51
+#define EXT2_SUPER_MAGIC    0xEF53
+#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x0004
+struct ext2_super_block {
+       unsigned char   s_dummy1[56];
+       unsigned char   s_magic[2];
+       unsigned char   s_dummy2[34];
+       unsigned char   s_feature_compat[4];
+       unsigned char   s_feature_incompat[4];
+       unsigned char   s_feature_ro_compat[4];
+       unsigned char   s_uuid[16];
+       unsigned char   s_volume_name[16];
+       unsigned char   s_dummy3[88];
+       unsigned char   s_journal_inum[4];      /* ext3 only */
+};
+#define ext2magic(s)   ((unsigned int) s.s_magic[0] + (((unsigned int) s.s_magic[1]) << 8))
+
+struct reiserfs_super_block
+{
+       unsigned char           s_block_count[4];
+       unsigned char           s_free_blocks[4];
+       unsigned char           s_root_block[4];
+       unsigned char           s_journal_block[4];
+       unsigned char           s_journal_dev[4];
+       unsigned char           s_orig_journal_size[4];
+       unsigned char           s_journal_trans_max[4];
+       unsigned char           s_journal_block_count[4];
+       unsigned char           s_journal_max_batch[4];
+       unsigned char           s_journal_max_commit_age[4];
+       unsigned char           s_journal_max_trans_age[4];
+       unsigned char           s_blocksize[2];
+       unsigned char           s_oid_maxsize[2];
+       unsigned char           s_oid_cursize[2];
+       unsigned char           s_state[2];
+       unsigned char           s_magic[12];
+};
+#define REISERFS_SUPER_MAGIC_STRING "ReIsErFs"
+#define REISER2FS_SUPER_MAGIC_STRING "ReIsEr2Fs"
+#define REISERFS_DISK_OFFSET_IN_BYTES (64 * 1024)
+/* the spot for the super in versions 3.5 - 3.5.10 (inclusive) */
+#define REISERFS_OLD_DISK_OFFSET_IN_BYTES (8 * 1024)
+
+#define _XIAFS_SUPER_MAGIC 0x012FD16D
+struct xiafs_super_block {
+    unsigned char     s_boot_segment[512];     /*  1st sector reserved for boot */
+    unsigned char     s_dummy[60];
+    unsigned char     s_magic[4];
+};
+#define xiafsmagic(s)  ((unsigned int) s.s_magic[0] + (((unsigned int) s.s_magic[1]) << 8) + \
+                       (((unsigned int) s.s_magic[2]) << 16) + \
+                       (((unsigned int) s.s_magic[3]) << 24))
+
+/* From jj@sunsite.ms.mff.cuni.cz Mon Mar 23 15:19:05 1998 */
+#define UFS_SUPER_MAGIC 0x00011954
+struct ufs_super_block {
+    unsigned char     s_dummy[0x55c];
+    unsigned char     s_magic[4];
+};
+#define ufsmagic(s)    ((unsigned int) s.s_magic[0] + (((unsigned int) s.s_magic[1]) << 8) + \
+                        (((unsigned int) s.s_magic[2]) << 16) + \
+                        (((unsigned int) s.s_magic[3]) << 24))
+
+/* From Richard.Russon@ait.co.uk Wed Feb 24 08:05:27 1999 */
+#define NTFS_SUPER_MAGIC "NTFS"
+struct ntfs_super_block {
+    unsigned char    s_dummy[3];
+    unsigned char    s_magic[4];
+};
+
+/* From inspection of a few FAT filesystems - aeb */
+/* Unfortunately I find almost the same thing on an extended partition;
+   it looks like a primary has some directory entries where the extended
+   has a partition table: IO.SYS, MSDOS.SYS, WINBOOT.SYS */
+struct fat_super_block {
+    unsigned char    s_dummy[3];
+    unsigned char    s_os[8];          /* "MSDOS5.0" or "MSWIN4.0" or "MSWIN4.1" */
+                               /* mtools-3.9.4 writes "MTOOL394" */
+    unsigned char    s_dummy2[32];
+    unsigned char    s_label[11];      /* for DOS? */
+    unsigned char    s_fs[8];          /* "FAT12   " or "FAT16   " or all zero   */
+                                /* OS/2 BM has "FAT     " here. */
+    unsigned char    s_dummy3[9];
+    unsigned char    s_label2[11];     /* for Windows? */
+    unsigned char    s_fs2[8];         /* garbage or "FAT32   " */
+};
+
+#define XFS_SUPER_MAGIC "XFSB"
+struct xfs_super_block {
+    unsigned char    s_magic[4];
+    unsigned char    s_dummy[28];
+    unsigned char    s_uuid[16];
+    unsigned char    s_dummy2[60];
+    unsigned char    s_fname[12];
+};
+
+#define CRAMFS_SUPER_MAGIC 0x28cd3d45
+struct cramfs_super_block {
+       unsigned char    s_magic[4];
+       unsigned char    s_dummy[12];
+       unsigned char    s_id[16];
+};
+#define cramfsmagic(s) ((unsigned int) s.s_magic[0] + (((unsigned int) s.s_magic[1]) << 8) + \
+                        (((unsigned int) s.s_magic[2]) << 16) + \
+                        (((unsigned int) s.s_magic[3]) << 24))
+
+#define HFS_SUPER_MAGIC 0x4244
+struct hfs_super_block {
+       unsigned char    s_magic[2];
+       unsigned char    s_dummy[18];
+       unsigned char    s_blksize[4];
+};
+#define hfsmagic(s)    ((unsigned int) s.s_magic[0] + (((unsigned int) s.s_magic[1]) << 8))
+#define hfsblksize(s)  ((unsigned int) s.s_blksize[0] + \
+                        (((unsigned int) s.s_blksize[1]) << 8) + \
+                        (((unsigned int) s.s_blksize[2]) << 16) + \
+                        (((unsigned int) s.s_blksize[3]) << 24))
+
+#define HPFS_SUPER_MAGIC 0xf995e849
+struct hpfs_super_block {
+       unsigned char    s_magic[4];
+       unsigned char    s_magic2[4];
+};
+#define hpfsmagic(s)   ((unsigned int) s.s_magic[0] + (((unsigned int) s.s_magic[1]) << 8) + \
+                        (((unsigned int) s.s_magic[2]) << 16) + \
+                        (((unsigned int) s.s_magic[3]) << 24))
+
+struct adfs_super_block {
+       unsigned char    s_dummy[448];
+       unsigned char    s_blksize[1];
+       unsigned char    s_dummy2[62];
+       unsigned char    s_checksum[1];
+};
+#define adfsblksize(s) ((unsigned int) s.s_blksize[0])
index 2a36352de167db0c6ac06d76e15071d4cc73c989..cbd99feb917a1300e6129b356e9eeb6a74db5602 100644 (file)
@@ -1,7 +1,9 @@
-#!/bin/bash
+#!/bin/bash --norc
 
 # mkinitrd
 #
+# Copyright 2005 Red Hat, Inc.
+#
 # Written by Erik Troan <ewt@redhat.com>
 #
 # Contributors:
 #       Preston Brown <pbrown@redhat.com>
 #      Bill Nottingham <notting@redhat.com>
 #       Guillaume Cottenceau <gc@mandrakesoft.com>
+#      Peter Jones <pjones@redhat.com>
 
+umask 0022
 
 PATH=/sbin:/usr/sbin:/bin:/usr/bin:$PATH
 export PATH
 
-VERSION=3.5.14
+VERSION=4.2.11
 
 compress=1
+allowmissing=""
 target=""
 kernel=""
 force=""
@@ -36,18 +41,28 @@ MODULES=""
 img_vers=""
 builtins=""
 pivot=1
+squashfs=1
+initramfs=""
 modulefile=/etc/modules.conf
 rc=0
 
-IMAGESIZE=5120
+IMAGESIZE=8000
 PRESCSIMODS="scsi_mod sd_mod unknown"
 fstab="/etc/fstab"
 
+if [ -f /etc/udev/udev.conf ]; then
+    USE_UDEV="yes"
+    UDEV_TMPFS="yes"
+    UDEV_KEEP_DEV="yes"
+    . /etc/udev/udev.conf
+    [ -x /sbin/udev.static ] || USE_UDEV=
+fi
+
 usage () {
     echo "usage: `basename $0` [--version] [-v] [-f] [--preload <module>]" >&2
     echo "       [--omit-scsi-modules] [--omit-raid-modules] [--omit-lvm-modules]" >&2
     echo "       [--with=<module>] [--image-version] [--fstab=<fstab>] [--nocompress]" >&2
-    echo "       [--builtin=<module>] [--nopivot] <initrd-image> <kernel-version>" >&2
+    echo "       [--builtin=<module>] [--nopivot] [--nosquashfs] <initrd-image> <kernel-version>" >&2
     echo "" >&2
     echo "       (ex: `basename $0` /boot/initrd-2.2.5-15.img 2.2.5-15)" >&2
     exit 1
@@ -61,11 +76,11 @@ moduledep() {
 
     [ -n "$verbose" ] && echo -n "Looking for deps of module $1"
     deps=$(gawk 'BEGIN { searched=ARGV[2]; ARGV[2]=""; rc=1 } \
-                function modname(filename) { match(filename, /\/([^\/]+)\.k?o/, ret); return ret[1] } \
+                function modname(filename) { match(filename, /\/([^\/]+)\.k?o:?$/, ret); return ret[1] } \
                 function show() { if (orig == searched) { print dep; orig=""; rc=0; exit } } \
                 /^\/lib/ { show(); \
-                           orig=modname($1); \
-                           if ($2) { dep=modname($2) } else { dep="" } } \
+                           orig=modname($1); dep=""; \
+                           if ($2) { for (i = 2; i <= NF; i++) { dep=sprintf("%s %s", dep, modname($i)); } } } \
                 /^     / { dep=sprintf("%s %s", dep, modname($1));  } \
                 END      { show(); exit(rc) }' /lib/modules/$kernel/modules.dep $1)
     [ -n "$verbose" ] && echo -e "\t$deps"
@@ -90,7 +105,7 @@ findmodule() {
        modName=$(echo $modName | cut -b2-)
     fi
 
-    if echo $builtins | grep -E -q '(^| )'$modName'( |$)' ; then
+    if echo $builtins | egrep -q '(^| )'$modName'( |$)' ; then
        [ -n "$verbose" ] && echo "module $modName assumed to be built in"
        set +x
        return
@@ -99,7 +114,7 @@ findmodule() {
     # special cases
     if [ "$modName" = "i2o_block" ]; then
        findmodule i2o_core
-       findmodule i2o_pci
+       findmodule -i2o_pci
        modName="i2o_block"
     elif [ "$modName" = "ppa" ]; then
        findmodule parport
@@ -143,6 +158,11 @@ findmodule() {
                return;
            fi
        done;
+
+       if [ -n "$allowmissing" ]; then
+           echo "WARNING: No module $modName found for kernel $kernel, continuing anyway" >&2
+           return
+       fi
     
        echo "No module $modName found for kernel $kernel, aborting." >&2
        exit 1
@@ -216,6 +236,10 @@ while [ $# -gt 0 ]; do
            pivot=""
            ;;
 
+       --nosquashfs)
+           squashfs=""
+           ;;
+
        --ifneeded)
            # legacy
            ;;
@@ -245,6 +269,12 @@ while [ $# -gt 0 ]; do
        --image-version)
            img_vers=yes
            ;;
+       --noudev)
+           USE_UDEV=
+           ;;
+       --allow-missing)
+           allowmissing=yes
+           ;;
        *)
            if [ -z "$target" ]; then
                target=$1
@@ -282,6 +312,21 @@ if [ $UID != 0 ]; then
     exit 1
 fi
 
+kernelmajor=`echo $kernel | cut -d . -f 1,2`
+
+#if [ "$kernelmajor" == "2.4" ]; then
+    if [ -n "$verbose" ]; then echo "Creating old-style initrd"; fi
+    USE_UDEV=
+#else
+#    if [ -n "$verbose" ]; then echo "Creating initramfs"; fi
+#    modulefile=/etc/modprobe.conf
+#    initramfs=1
+#    pivot=""
+#fi
+
+# if we're not using udev, don't set any of the other bits
+[ -z "$USE_UDEV" ] && UDEV_TMPFS= && UDEV_KEEP_DEV=
+
 # find a temporary directory which doesn't use tmpfs
 TMPDIR=""
 for t in /tmp /var/tmp /root ${PWD}; do
@@ -319,7 +364,7 @@ if [ -n "$withusb" ]; then
           if [ `which kudzu 2>/dev/null` ]; then
            host=$(kudzu --probe -b scsi |
              gawk '/^device: '${dev}'/,/^host:/ { if (/^host/) { print $2; exit; } }')
-           if [ -d /proc/scsi/usb-storage-${host} ]; then
+           if [ -d /proc/scsi/usb-storage-${host} -o -f /proc/scsi/usb-storage/${host} ]; then
                needusb=1
            fi
           fi
@@ -328,7 +373,7 @@ if [ -n "$withusb" ]; then
 fi
 
 if [ -n "$needusb" ]; then
-    drivers=$(gawk '/^alias usb-controller[0-9]* / { print $3}' < /etc/modules.conf)
+    drivers=$(gawk '/^alias[[:space:]]+usb-controller[0-9]* / { print $3}' < $modulefile)
     if [ -n "$drivers" ]; then
        for driver in $drivers; do
            findmodule $driver
@@ -345,7 +390,7 @@ if [ -z "$noscsi" ]; then
     fi
 
     if [ -f $modulefile ]; then
-       scsimodules=`grep "alias[[:space:]]scsi_hostadapter" $modulefile | grep -v '^[  ]*#' | LC_ALL=C sort -u | gawk '{ print $3 }'`
+       scsimodules=`grep "alias[[:space:]]\+scsi_hostadapter" $modulefile | grep -v '^[        ]*#' | LC_ALL=C sort -u | gawk '{ print $3 }'`
 
        if [ -n "$scsimodules" ]; then
            for n in $PRESCSIMODS; do
@@ -371,9 +416,20 @@ fi
 if [ -z "$nolvm" ]; then
     if [ -f /proc/lvm/global  ]; then
         if  grep -q '^VG:' /proc/lvm/global ; then
-           findmodule -lvm-mod
+           if [ "$kernelmajor" == "2.4" ]; then
+               findmodule -lvm-mod
+           else
+               findmodule -dm-mod
+           fi
         fi
     fi
+
+    if [ -x /sbin/dmsetup -a -e /dev/mapper/control ]; then
+       dmout=$(/sbin/dmsetup ls 2>/dev/null)
+       if [ "$dmout" != "No devices found" -a "$dmout" != "" ]; then
+           findmodule -dm-mod
+       fi
+    fi
 fi
 
 # If we have dasd devices, include the necessary modules (S/390)
@@ -395,7 +451,11 @@ if [ -z "$noraid" -a -f /proc/mdstat ]; then
            findmodule linear
            startraid=1
            ;;
-       raid[0145])
+       multipath)
+           findmodule multipath
+           startraid=1
+           ;;
+       raid[01456])
            findmodule $level
            startraid=1
            ;;
@@ -415,9 +475,9 @@ fi
 rootdev=$(gawk '/^[ \t]*[^#]/ { if ($2 == "/") { print $1; }}' $fstab)
 if echo $rootdev | cut -d/ -f3 | grep -q loop ; then
     key="^# $(echo $rootdev | cut -d/ -f3 | tr '[a-z]' '[A-Z]'):"
-    if ! grep "$key" $fstab > /dev/null; then
-       echo "The root filesystem is on a $rootdev, but there is no magic entry in $fstab" 1>&2
-       echo "for this device. Consult the mkinitrd man page for more information" 2>&2
+    if ! grep "$key" $fstab >> /dev/null; then
+       echo "The root filesystem is on a $rootdev, but there is no magic entry in $fstab" >&2
+       echo "for this device. Consult the mkinitrd man page for more information" >&2
        exit 1
     fi
 
@@ -433,19 +493,31 @@ if echo $rootdev | cut -d/ -f3 | grep -q loop ; then
     basicmodules="$basicmodules -${loopFs}"
 # check if the root fs is on a logical volume
 elif ! echo $rootdev | cut -c1-6 |grep -q "LABEL=" ; then
+    root_vg=$(echo $rootdev | cut -d/ -f3)
     rootdev=$(echo "readlink $rootdev" | /sbin/nash --quiet)
     major=`ls -l $rootdev | sed -e "s/.* \\([0-9]\+\\), *[0-9]\+.*/\\1/"`
     [ "$major" != "58" ] || root_lvm=1
+    if echo $rootdev |grep -q /dev/mapper 2>/dev/null ; then root_lvm=1 ; fi
 fi
 
 rootfs=$(gawk '{ if ($1 !~ /^[ \t]*#/ && $2 == "/") { print $3; }}' $fstab)
-rootopts=$(gawk '{ if ($1 !~ /^[ \t]*#/ && $2 == "/") { print $4; }}' $fstab)
+rootopts=$(gawk '{ if ($1 !~ /^[ \t]*#/ && $2 == "/") { print $4; }}' $fstab \
+    | sed -e 's/\(^rw,\|rw,$\)//' -e 's/,rw,/,/' -e 's/^rw$/ro/')
 
 # in case the root filesystem is modular
 findmodule -${rootfs}
 
 if [ -n "$root_lvm" ]; then
-    findmodule -lvm-mod
+    if [ "$kernelmajor" == "2.4" ]; then    
+       findmodule -lvm-mod
+    else
+       findmodule -dm-mod
+       # DM requires all of these to be there in case someone used the
+       # feature.  broken.  (#132001)
+       findmodule -dm-mirror
+       findmodule -dm-zero
+       findmodule -dm-snapshot
+    fi
 fi
 
 for n in $basicmodules; do 
@@ -459,60 +531,82 @@ fi
 
 MNTIMAGE=`mktemp -d ${TMPDIR}/initrd.XXXXXX`
 IMAGE=`mktemp ${TMPDIR}/initrd.img.XXXXXX`
-MNTPOINT=`mktemp -d ${TMPDIR}/initrd.mnt.XXXXXX`
-RCFILE=$MNTIMAGE/linuxrc
+if [ -z "$initramfs" ]; then
+    MNTPOINT=`mktemp -d ${TMPDIR}/initrd.mnt.XXXXXX`
+    RCFILE=$MNTIMAGE/linuxrc
+else
+    RCFILE=$MNTIMAGE/init
+fi
 
-if [ -z "$MNTIMAGE" -o -z "$IMAGE" -o -z "$MNTPOINT" ]; then
+if [ -z "$MNTIMAGE" -o -z "$IMAGE" ]; then
     echo "Error creating temporaries.  Try again" >&2
     exit 1
 fi
 
-dd if=/dev/zero of=$IMAGE bs=1k count=$IMAGESIZE 2> /dev/null || exit 1
+if [ -z "$initramfs" ]; then
+  dd if=/dev/zero of=$IMAGE bs=1k count=$IMAGESIZE 2> /dev/null || exit 1
 
-LODEV=$(echo findlodev | /sbin/nash --quiet)
+  LODEV=$(echo findlodev | /sbin/nash --quiet)
 
-if [ -z "$LODEV" ]; then
+  if [ -z "$LODEV" ]; then
     rm -rf $MNTIMAGE $MNTPOINT $IMAGE
     echo "All of your loopback devices are in use." >&2
     exit 1
-fi
+  fi
 
-losetup ${LODEV} $IMAGE || exit 1
+  losetup ${LODEV} $IMAGE || exit 1
 
-# We have to "echo y |" so that it doesn't complain about $IMAGE not
-# being a block device
-echo y | mke2fs $LODEV $IMAGESIZE >/dev/null 2>/dev/null
-tune2fs -i0 $LODEV >/dev/null
+  # We have to "echo y |" so that it doesn't complain about $IMAGE not
+  # being a block device
+  echo y | mkfs.minix -i 100 $LODEV $IMAGESIZE >/dev/null 2>/dev/null
 
-if [ -n "$verbose" ]; then
-    echo "Using loopback device $LODEV"
-fi
+  if [ -n "$verbose" ]; then
+      echo "Using loopback device $LODEV"
+  fi
 
-mkdir -p $MNTPOINT
-mount -t ext2 $LODEV $MNTPOINT || {
+  mkdir -p $MNTPOINT
+  mount -t minix $LODEV $MNTPOINT || {
        echo "Can't get a loopback device"
        exit 1
-}
+  }
+
+  # We don't need this directory, so let's save space
+  rmdir $MNTPOINT/lost+found >/dev/null 2>&1
+fi
 
 mkdir -p $MNTIMAGE
 mkdir -p $MNTIMAGE/lib
 mkdir -p $MNTIMAGE/bin
 mkdir -p $MNTIMAGE/etc
 mkdir -p $MNTIMAGE/dev
+mkdir -p $MNTIMAGE/hd
 mkdir -p $MNTIMAGE/loopfs
 mkdir -p $MNTIMAGE/proc
+mkdir -p $MNTIMAGE/sys
 mkdir -p $MNTIMAGE/sysroot
 ln -s bin $MNTIMAGE/sbin
 
-# We don't need this directory, so let's save space
-rm -rf $MNTPOINT/lost+found
-
 inst /sbin/nash "$MNTIMAGE/bin/nash"
 inst /sbin/insmod.static "$MNTIMAGE/bin/insmod"
+inst /bin/tar.static "$MNTIMAGE/bin/tar"
+inst /usr/bin/lzmadec "$MNTIMAGE/bin/lzmadec"
+inst /sbin/fsck.minix.static "$MNTIMAGE/bin/fsck.minix"
 ln -s /sbin/nash $MNTIMAGE/sbin/modprobe
 
+if [ -n "$USE_UDEV" ]; then
+    inst /sbin/udev.static $MNTIMAGE/sbin/udev
+    inst /sbin/udevstart.static $MNTIMAGE/sbin/udevstart
+    mkdir -p $MNTIMAGE/etc/udev
+    inst /etc/udev/udev.conf $MNTIMAGE/etc/udev/udev.conf
+    ln -s /sbin/nash $MNTIMAGE/sbin/hotplug
+fi
+
 for MODULE in $MODULES; do
-    cp $verbose -a /lib/modules/$kernel/$MODULE $MNTIMAGE/lib
+    if [ -x /usr/bin/strip ]; then
+       /usr/bin/strip -g $verbose /lib/modules/$kernel/$MODULE -o $MNTIMAGE/lib/$(basename $MODULE)
+    else
+       cp $verbose -a /lib/modules/$kernel/$MODULE $MNTIMAGE/lib
+    fi
 done
 
 # mknod'ing the devices instead of copying them works both with and
@@ -526,7 +620,7 @@ for i in 1 2 3 4; do
 done
 
 # FIXME -- this won't work if you're using devfs
-if [ -n "$root_lvm" ]; then
+if [ -n "$root_lvm" -a "$kernelmajor" == "2.4" ]; then
     pvs=$(/sbin/pvscan | grep " PV " | gawk {'print $5;'} |sed 's/"//g')
     for pv in $pvs; do
        cp $verbose --parents -a $pv $MNTIMAGE/
@@ -539,9 +633,44 @@ if [ -n "$root_lvm" ]; then
     mknod $MNTIMAGE/dev/lvm b 109 0
 fi
 
-echo "#!/bin/nash" > $RCFILE
+if [ -n "$root_lvm" -a "$kernelmajor" == "2.6" ]; then
+    inst /sbin/lvm.static "$MNTIMAGE/bin/lvm"
+    if [ -f /etc/lvm/lvm.conf ]; then
+       cp $verbose --parents /etc/lvm/lvm.conf $MNTIMAGE/
+    fi
+fi
+
+echo "#!/bin/nash" >| $RCFILE
 echo "" >> $RCFILE
 
+echo "mount -t proc /proc /proc" >> $RCFILE
+echo "setquiet" >> $RCFILE
+echo "echo Mounted /proc filesystem" >> $RCFILE
+
+if [ "$kernelmajor" != "2.4" ]; then
+    echo "echo Mounting sysfs" >> $RCFILE
+    echo "mount -t sysfs /sys /sys" >> $RCFILE
+fi
+
+if [ -n "$USE_UDEV" ]; then
+    if [ -n "$UDEV_TMPFS" ]; then
+       cat >> $RCFILE <<EOF
+echo Creating /dev
+mount -o mode=0755 -t tmpfs /dev /dev
+mknod /dev/console c 5 1
+mknod /dev/null c 1 3
+mknod /dev/zero c 1 5
+mkdir /dev/pts
+mkdir /dev/shm
+EOF
+    fi
+    cat >> $RCFILE <<EOF
+echo Starting udev
+/sbin/udevstart
+echo -n "/sbin/hotplug" > /proc/sys/kernel/hotplug
+EOF
+fi
+
 for MODULE in $MODULES; do
     text=""
     module=`echo $MODULE | sed "s|.*/||" | sed "s/.k\?o$//"`
@@ -561,12 +690,26 @@ for MODULE in $MODULES; do
     # Hack - we need a delay after loading usb-storage to give things
     #        time to settle down before we start looking a block devices
     if [ "$module" = "usb-storage" ]; then
-       echo "sleep 5" >> $RCFILE
+       echo "sleep 8" >> $RCFILE
+    fi
+    if [ "$module" = "zfcp" -a -f /etc/zfcp.conf ]; then
+        echo "sleep 2" >> $RCFILE
+        cat /etc/zfcp.conf | grep -v "^#" | tr "A-Z" "a-z" | while read DEVICE SCSIID WWPN SCSILUN FCPLUN; do
+            echo "echo -n $WWPN > /sys/bus/ccw/drivers/zfcp/${DEVICE/0x/}/port_add" >>$RCFILE
+            echo "echo -n $FCPLUN > /sys/bus/ccw/drivers/zfcp/${DEVICE/0x/}/$WWPN/unit_add" >>$RCFILE
+            echo "echo -n 1 > /sys/bus/ccw/drivers/zfcp/${DEVICE/0x/}/online" >>$RCFILE
+        done
     fi
 done
 
-echo "echo Mounting /proc filesystem" >> $RCFILE
-echo "mount -t proc /proc /proc" >> $RCFILE
+# HACK: module loading + device creation isn't necessarily synchronous...
+# this will make sure that we have all of our devices before trying
+# things like RAID or LVM
+if [ -n "$USE_UDEV" ]; then
+  echo "/sbin/udevstart" >> $RCFILE
+fi
+
+echo "sleep 2" >> $RCFILE
 
 if [ -n "$startraid" ]; then
     for dev in $raiddevices; do
@@ -575,8 +718,12 @@ if [ -n "$startraid" ]; then
     done
 fi
 
-echo "echo Creating block devices" >> $RCFILE
-echo "mkdevices /dev" >> $RCFILE
+if [ -z "$USE_UDEV" ]; then
+    echo "echo Creating block devices" >> $RCFILE
+    echo "mkdevices /dev" >> $RCFILE
+fi
+
+echo "mknod /dev/loop0 b 7 0" >> $RCFILE
 
 if [ -n "$loopDev" ]; then
     mkdir /initrd
@@ -587,40 +734,91 @@ if [ -n "$loopDev" ]; then
     echo "echo Setting up loopback device $rootdev" >> $RCFILE
     echo "losetup $rootdev /loopfs$loopFile" >> $RCFILE
 elif [ -n "$root_lvm" ]; then
+  if [ "$kernelmajor" == "2.4" ]; then
     echo "echo Scanning logical volumes" >> $RCFILE
     echo "vgscan" >> $RCFILE
     echo "echo Activating logical volumes" >> $RCFILE
     echo "vgchange -ay" >> $RCFILE
-else
-    echo "echo Creating root device" >> $RCFILE
-    echo "mkrootdev /dev/root" >> $RCFILE
-    rootdev=/dev/root
+  else
+    echo "echo Making device-mapper control node" >> $RCFILE
+    echo "mkdmnod" >> $RCFILE
+    echo "echo Scanning logical volumes" >> $RCFILE
+    echo "lvm vgscan --ignorelockingfailure" >> $RCFILE
+    echo "echo Activating logical volumes" >> $RCFILE
+    echo "lvm vgchange -ay --ignorelockingfailure $root_vg" >> $RCFILE
+  fi
 fi
 
-if [ -n "$pivot" ]; then
+echo "echo Creating root device" >> $RCFILE
+echo "mkrootdev /dev/root" >> $RCFILE
+rootdev=/dev/root
+
+if [ -n "$initramfs" ]; then
+  echo "echo Mounting root filesystem" >> $RCFILE
+  if [ -n "$squashfs" ]; then
+    echo "mount -o $rootopts --ro -t $rootfs $rootdev /sysroot" >> $RCFILE
+  else
+    echo "fsck.minix $rootdev" >> $RCFILE
+    echo "mount -o $rootopts -t minix $rootdev /hd" >> $RCFILE
+    echo "losetup /dev/loop0 /hd/ipcop-1.5.0a1.squashfs" >> $RCFILE
+    echo "mount --ro -t squashfs /dev/loop0 /sysroot" >> $RCFILE
+    echo "mount -t tmpfs none /sysroot/var" >> $RCFILE
+    echo "echo Unpacking IPCop configuration.. Please wait.." >> $RCFILE
+    echo "tar -C /sysroot -xjf /hd/ipcop.tbz2" >> $RCFILE
+  fi
+
+  echo "echo Switching to new root" >> $RCFILE
+  if [ -n "$UDEV_KEEP_DEV" ]; then
+    echo "switchroot --movedev /sysroot" >> $RCFILE
+  else
+    echo "switchroot /sysroot" >> $RCFILE
+  fi
+else 
+  if [ "$kernelmajor" != "2.4" ]; then
+    echo "umount /sys" >> $RCFILE
+  fi
+
+  if [ -n "$pivot" ]; then
     echo "echo 0x0100 > /proc/sys/kernel/real-root-dev" >> $RCFILE
 
     echo "echo Mounting root filesystem" >> $RCFILE
-    echo "mount -o $rootopts --ro -t $rootfs $rootdev /sysroot" >> $RCFILE
+    if [ -n "$squashfs" ]; then
+       echo "mount -o $rootopts --ro -t $rootfs $rootdev /sysroot" >> $RCFILE
+    else
+       echo "fsck.minix $rootdev" >> $RCFILE
+       echo "mount -o $rootopts -t minix $rootdev /hd" >> $RCFILE
+       echo "losetup /dev/loop0 /hd/ipcop-1.5.0a1.squashfs" >> $RCFILE
+        echo "mount --ro -t squashfs /dev/loop0 /sysroot" >> $RCFILE
+       echo "mount -t tmpfs none /sysroot/var" >> $RCFILE
+       echo "echo Unpacking IPCop configuration.. Please wait.." >> $RCFILE
+       echo "tar -C /sysroot -xjf /hd/ipcop.tbz2" >> $RCFILE
+    fi
 
     echo "pivot_root /sysroot /sysroot/initrd" >> $RCFILE
     echo "umount /initrd/proc" >> $RCFILE
-else
+  else
     echo "umount /proc" >> $RCFILE
-fi
+  fi
 
+  [ -n "$UDEV_TMPFS" ] && echo "umount /initrd/dev" >> $RCFILE
+fi
 chmod +x $RCFILE
 
-(cd $MNTIMAGE; tar cf - .) | (cd $MNTPOINT; tar xf -) || exit 1
+if [ -z "$initramfs" ]; then
+  (cd $MNTIMAGE; tar cf - .) | (cd $MNTPOINT; tar xf -) || exit 1
 
-umount $MNTPOINT
-losetup -d $LODEV
+  umount $MNTPOINT
+  losetup -d $LODEV
+else
+  (cd $MNTIMAGE; find . | cpio --quiet -c -o) >| $IMAGE || exit 1
+fi
 
 if [ -n "$compress" ]; then
-    gzip -9 < $IMAGE > $target || rc=1
+    gzip -9 < $IMAGE >| $target || rc=1
 else
     cp -a $IMAGE $target || rc=1
 fi
-rm -rf $MNTIMAGE $MNTPOINT $IMAGE
+rm -rf $MNTIMAGE $IMAGE
+if [ -n "$MNTPOINT" ]; then rm -rf $MNTPOINT ; fi
 
 exit $rc
index 75ff9be4df611ee4983e109a84c07f89cdd03358..cf3c1f591eb00e12e5db57424b155681e9bc1b70 100644 (file)
-/*\r
- * taken from util-linux 2.11g and hacked into nash\r
- *\r
- * mount_by_label.c - aeb\r
- *\r
- * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>\r
- * - added Native Language Support\r
- * 2000-01-20 James Antill <james@and.org>\r
- * - Added error message if /proc/partitions cannot be opened\r
- * 2000-05-09 Erik Troan <ewt@redhat.com>\r
- * - Added cache for UUID and disk labels\r
- * 2000-11-07 Nathan Scott <nathans@sgi.com>\r
- * - Added XFS support\r
- */\r
-\r
-#include <errno.h>\r
-#include <stdio.h>\r
-#include <string.h>\r
-#include <ctype.h>\r
-#include <fcntl.h>\r
-#include <stdlib.h>\r
-#include <unistd.h>\r
-#include <sys/stat.h>\r
-#include "linux_fs.h"\r
-#include "mount_by_label.h"\r
-\r
-#define PROC_PARTITIONS "/proc/partitions"\r
-#define DEVLABELDIR    "/dev"\r
-\r
-#define _(str) (str)\r
-\r
-static struct uuidCache_s {\r
-       struct uuidCache_s *next;\r
-       char uuid[16];\r
-       char *device;\r
-       char *label;\r
-       int major, minor;\r
-} *uuidCache = NULL;\r
-\r
-/* for now, only ext2, ext3 and xfs are supported */\r
-static int\r
-get_label_uuid(const char *device, char **label, char *uuid) {\r
-\r
-       /* start with ext2/3 and xfs tests, taken from mount_guess_fstype */\r
-       /* should merge these later */\r
-       int fd;\r
-       int rv = 1;\r
-       size_t namesize;\r
-       struct ext2_super_block e2sb;\r
-       struct xfs_super_block xfsb;\r
-\r
-       fd = open(device, O_RDONLY);\r
-       if (fd < 0)\r
-               return rv;\r
-\r
-       if (lseek(fd, 1024, SEEK_SET) == 1024\r
-           && read(fd, (char *) &e2sb, sizeof(e2sb)) == sizeof(e2sb)\r
-           && (ext2magic(e2sb) == EXT2_SUPER_MAGIC)) {\r
-               memcpy(uuid, e2sb.s_uuid, sizeof(e2sb.s_uuid));\r
-               namesize = sizeof(e2sb.s_volume_name);\r
-               if ((*label = calloc(namesize + 1, 1)) != NULL)\r
-                       memcpy(*label, e2sb.s_volume_name, namesize);\r
-               rv = 0;\r
-       }\r
-       else if (lseek(fd, 0, SEEK_SET) == 0\r
-           && read(fd, (char *) &xfsb, sizeof(xfsb)) == sizeof(xfsb)\r
-           && (strncmp(xfsb.s_magic, XFS_SUPER_MAGIC, 4) == 0)) {\r
-               memcpy(uuid, xfsb.s_uuid, sizeof(xfsb.s_uuid));\r
-               namesize = sizeof(xfsb.s_fname);\r
-               if ((*label = calloc(namesize + 1, 1)) != NULL)\r
-                       memcpy(*label, xfsb.s_fname, namesize);\r
-               rv = 0;\r
-       }\r
-\r
-       close(fd);\r
-       return rv;\r
-}\r
-\r
-static void\r
-uuidcache_addentry(char * device, int major, int minor, char *label, char *uuid) {\r
-       struct uuidCache_s *last;\r
-    \r
-       if (!uuidCache) {\r
-               last = uuidCache = malloc(sizeof(*uuidCache));\r
-       } else {\r
-               for (last = uuidCache; last->next; last = last->next) ;\r
-               last->next = malloc(sizeof(*uuidCache));\r
-               last = last->next;\r
-       }\r
-       last->next = NULL;\r
-       last->label = label;\r
-       last->device = device;\r
-       last->major = major;\r
-       last->minor = minor;\r
-       memcpy(last->uuid, uuid, sizeof(last->uuid));\r
-}\r
-\r
-static void\r
-uuidcache_init(void) {\r
-       char line[100];\r
-       char *s;\r
-       int ma, mi, sz;\r
-       static char ptname[100];\r
-       FILE *procpt;\r
-       char uuid[16], *label;\r
-       char device[110];\r
-       int firstPass;\r
-       int handleOnFirst;\r
-       char * chptr, * endptr;\r
-\r
-       if (uuidCache)\r
-               return;\r
-\r
-       procpt = fopen(PROC_PARTITIONS, "r");\r
-       if (!procpt) {\r
-               static int warn = 0;\r
-               if (!warn++)\r
-                   fprintf (stderr, _("mount: could not open %s, so UUID and LABEL "\r
-                            "conversion cannot be done.\n"),\r
-                      PROC_PARTITIONS);\r
-               return;\r
-       }\r
-\r
-       for (firstPass = 1; firstPass >= 0; firstPass--) {\r
-           fseek(procpt, 0, SEEK_SET);\r
-\r
-           while (fgets(line, sizeof(line), procpt)) {\r
-               /* The original version of this code used sscanf, but\r
-                  diet's sscanf is quite limited */\r
-               chptr = line;\r
-               if (*chptr++ != ' ') continue;\r
-\r
-               ma = strtol(chptr, &endptr, 0);\r
-               if (endptr == chptr) continue;\r
-               while (isspace(*endptr)) endptr++;\r
-               chptr = endptr;\r
-\r
-               mi = strtol(chptr, &endptr, 0);\r
-               if (endptr == chptr) continue;\r
-               while (isspace(*endptr)) endptr++;\r
-               chptr = endptr;\r
-\r
-               sz = strtol(chptr, &endptr, 0);\r
-               if (endptr == chptr) continue;\r
-               while (isspace(*endptr)) endptr++;\r
-               chptr = endptr;\r
-\r
-               while (!isspace(*endptr) && *endptr != '\n') endptr++;\r
-               if (chptr == endptr) continue;\r
-               strncpy(ptname, chptr, endptr - chptr);\r
-               ptname[endptr - chptr] = '\0';\r
-\r
-               /* skip extended partitions (heuristic: size 1) */\r
-               if (sz == 1)\r
-                       continue;\r
-\r
-               /* look only at md devices on first pass */\r
-               handleOnFirst = !strncmp(ptname, "md", 2);\r
-               if (firstPass != handleOnFirst)\r
-                       continue;\r
-\r
-               /* skip entire disk (minor 0, 64, ... on ide;\r
-                  0, 16, ... on sd) */\r
-               /* heuristic: partition name ends in a digit */\r
-\r
-               for(s = ptname; *s; s++);\r
-\r
-               if (isdigit(s[-1])) {\r
-                       char * ptr;\r
-                       char * deviceDir;\r
-                       int mustRemove = 0;\r
-                       int mustRemoveDir = 0;\r
-                       int i;\r
-\r
-                       sprintf(device, "%s/%s", DEVLABELDIR, ptname);\r
-                       if (access(device, F_OK)) {\r
-                           ptr = device;\r
-                           i = 0;\r
-                           while (*ptr)\r
-                               if (*ptr++ == '/')\r
-                                   i++;\r
-                           if (i > 2) {\r
-                               deviceDir = alloca(strlen(device) + 1);\r
-                               strcpy(deviceDir, device);\r
-                               ptr = deviceDir + (strlen(device) - 1);\r
-                               while (*ptr != '/')\r
-                                   *ptr-- = '\0';\r
-                               if (mkdir(deviceDir, 0644)) {\r
-                                   printf("mkdir: cannot create directory %s: %d\n", deviceDir, errno);\r
-                               } else {\r
-                                   mustRemoveDir = 1;\r
-                               }\r
-                           }\r
-\r
-                           mknod(device, S_IFBLK | 0600, makedev(ma, mi));\r
-                           mustRemove = 1;\r
-                       }\r
-                       if (!get_label_uuid(device, &label, uuid))\r
-                               uuidcache_addentry(strdup(device), ma, mi, \r
-                                                  label, uuid);\r
-\r
-                       if (mustRemove) unlink(device);\r
-                       if (mustRemoveDir) rmdir(deviceDir);\r
-               }\r
-           }\r
-       }\r
-\r
-       fclose(procpt);\r
-}\r
-\r
-#define UUID   1\r
-#define VOL    2\r
-\r
-static char *\r
-get_spec_by_x(int n, const char *t, int * majorPtr, int * minorPtr) {\r
-       struct uuidCache_s *uc;\r
-\r
-       uuidcache_init();\r
-       uc = uuidCache;\r
-\r
-       while(uc) {\r
-               switch (n) {\r
-               case UUID:\r
-                       if (!memcmp(t, uc->uuid, sizeof(uc->uuid))) {\r
-                               *majorPtr = uc->major;\r
-                               *minorPtr = uc->minor;\r
-                               return uc->device;\r
-                       }\r
-                       break;\r
-               case VOL:\r
-                       if (!strcmp(t, uc->label)) {\r
-                               *majorPtr = uc->major;\r
-                               *minorPtr = uc->minor;\r
-                               return uc->device;\r
-                       }\r
-                       break;\r
-               }\r
-               uc = uc->next;\r
-       }\r
-       return NULL;\r
-}\r
-\r
-static unsigned char\r
-fromhex(char c) {\r
-       if (isdigit(c))\r
-               return (c - '0');\r
-       else if (islower(c))\r
-               return (c - 'a' + 10);\r
-       else\r
-               return (c - 'A' + 10);\r
-}\r
-\r
-char *\r
-get_spec_by_uuid(const char *s, int * major, int * minor) {\r
-       unsigned char uuid[16];\r
-       int i;\r
-\r
-       if (strlen(s) != 36 ||\r
-           s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-')\r
-               goto bad_uuid;\r
-       for (i=0; i<16; i++) {\r
-           if (*s == '-') s++;\r
-           if (!isxdigit(s[0]) || !isxdigit(s[1]))\r
-                   goto bad_uuid;\r
-           uuid[i] = ((fromhex(s[0])<<4) | fromhex(s[1]));\r
-           s += 2;\r
-       }\r
-       return get_spec_by_x(UUID, uuid, major, minor);\r
-\r
- bad_uuid:\r
-       fprintf(stderr, _("mount: bad UUID"));\r
-       return 0;\r
-}\r
-\r
-char *\r
-get_spec_by_volume_label(const char *s, int * major, int * minor) {\r
-       return get_spec_by_x(VOL, s, major, minor);\r
-}\r
-\r
-int display_uuid_cache(void) {\r
-       struct uuidCache_s * u;\r
-       int i;\r
-\r
-       uuidcache_init();\r
-\r
-       u = uuidCache;\r
-       while (u) {\r
-           printf("%s %s ", u->device, u->label);\r
-           for (i = 0; i < sizeof(u->uuid); i++) {\r
-               if (i == 4 || i == 6 || i == 8 || i == 10)\r
-                   printf("-");\r
-               printf("%x", u->uuid[i] & 0xff);\r
-           }\r
-           printf("\n");\r
-           u = u->next;\r
-       }\r
-\r
-       return 0;\r
-}\r
-\r
+/*
+ * taken from util-linux 2.11g and hacked into nash
+ *
+ * mount_by_label.c - aeb
+ *
+ * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
+ * - added Native Language Support
+ * 2000-01-20 James Antill <james@and.org>
+ * - Added error message if /proc/partitions cannot be opened
+ * 2000-05-09 Erik Troan <ewt@redhat.com>
+ * - Added cache for UUID and disk labels
+ * 2000-11-07 Nathan Scott <nathans@sgi.com>
+ * - Added XFS support
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include "linux_fs.h"
+#include "mount_by_label.h"
+
+#define PROC_PARTITIONS "/proc/partitions"
+#define DEVLABELDIR    "/dev"
+
+#define _(str) (str)
+
+static struct uuidCache_s {
+       struct uuidCache_s *next;
+       char uuid[16];
+       char *device;
+       char *label;
+       int major, minor;
+} *uuidCache = NULL;
+
+/* for now, only ext2, ext3 and xfs are supported */
+static int
+get_label_uuid(const char *device, char **label, char *uuid) {
+
+       /* start with ext2/3 and xfs tests, taken from mount_guess_fstype */
+       /* should merge these later */
+       int fd;
+       int rv = 1;
+       size_t namesize;
+       struct ext2_super_block e2sb;
+       struct xfs_super_block xfsb;
+
+       fd = open(device, O_RDONLY);
+       if (fd < 0)
+               return rv;
+
+       if (lseek(fd, 1024, SEEK_SET) == 1024
+           && read(fd, (char *) &e2sb, sizeof(e2sb)) == sizeof(e2sb)
+           && (ext2magic(e2sb) == EXT2_SUPER_MAGIC)) {
+               memcpy(uuid, e2sb.s_uuid, sizeof(e2sb.s_uuid));
+               namesize = sizeof(e2sb.s_volume_name);
+               if ((*label = calloc(namesize + 1, 1)) != NULL)
+                       memcpy(*label, e2sb.s_volume_name, namesize);
+               rv = 0;
+       }
+       else if (lseek(fd, 0, SEEK_SET) == 0
+           && read(fd, (char *) &xfsb, sizeof(xfsb)) == sizeof(xfsb)
+           && (strncmp((char *)xfsb.s_magic, XFS_SUPER_MAGIC, 4) == 0)) {
+               memcpy(uuid, xfsb.s_uuid, sizeof(xfsb.s_uuid));
+               namesize = sizeof(xfsb.s_fname);
+               if ((*label = calloc(namesize + 1, 1)) != NULL)
+                       memcpy(*label, xfsb.s_fname, namesize);
+               rv = 0;
+       }
+
+       close(fd);
+       return rv;
+}
+
+static void
+uuidcache_addentry(char * device, int major, int minor, char *label, char *uuid) {
+       struct uuidCache_s *last;
+    
+       if (!uuidCache) {
+               last = uuidCache = malloc(sizeof(*uuidCache));
+       } else {
+               for (last = uuidCache; last->next; last = last->next) ;
+               last->next = malloc(sizeof(*uuidCache));
+               last = last->next;
+       }
+       last->next = NULL;
+       last->label = label;
+       last->device = device;
+       last->major = major;
+       last->minor = minor;
+       memcpy(last->uuid, uuid, sizeof(last->uuid));
+}
+
+static void
+uuidcache_init(void) {
+       char line[100];
+       char *s;
+       int ma, mi, sz;
+       static char ptname[100];
+       FILE *procpt;
+       char uuid[16], *label;
+       char device[110];
+       int firstPass;
+       int handleOnFirst;
+       char * chptr, * endptr;
+
+       if (uuidCache)
+               return;
+
+       procpt = fopen(PROC_PARTITIONS, "r");
+       if (!procpt) {
+               static int warn = 0;
+               if (!warn++)
+                   fprintf (stderr, _("mount: could not open %s, so UUID and LABEL "
+                            "conversion cannot be done.\n"),
+                      PROC_PARTITIONS);
+               return;
+       }
+
+       for (firstPass = 1; firstPass >= 0; firstPass--) {
+           fseek(procpt, 0, SEEK_SET);
+
+           while (fgets(line, sizeof(line), procpt)) {
+               /* The original version of this code used sscanf, but
+                  diet's sscanf is quite limited */
+               chptr = line;
+               if (*chptr++ != ' ') continue;
+
+               ma = strtol(chptr, &endptr, 0);
+               if (endptr == chptr) continue;
+               while (isspace(*endptr)) endptr++;
+               chptr = endptr;
+
+               mi = strtol(chptr, &endptr, 0);
+               if (endptr == chptr) continue;
+               while (isspace(*endptr)) endptr++;
+               chptr = endptr;
+
+               sz = strtol(chptr, &endptr, 0);
+               if (endptr == chptr) continue;
+               while (isspace(*endptr)) endptr++;
+               chptr = endptr;
+
+               while (!isspace(*endptr) && *endptr != '\n') endptr++;
+               if (chptr == endptr) continue;
+               strncpy(ptname, chptr, endptr - chptr);
+               ptname[endptr - chptr] = '\0';
+
+               /* skip extended partitions (heuristic: size 1) */
+               if (sz == 1)
+                       continue;
+
+               /* look only at md devices on first pass */
+               handleOnFirst = !strncmp(ptname, "md", 2);
+               if (firstPass != handleOnFirst)
+                       continue;
+
+               /* skip entire disk (minor 0, 64, ... on ide;
+                  0, 16, ... on sd) */
+               /* heuristic: partition name ends in a digit */
+
+               for(s = ptname; *s; s++);
+
+               if (isdigit(s[-1])) {
+                       char * ptr;
+                       char * deviceDir = NULL;
+                       int mustRemove = 0;
+                       int mustRemoveDir = 0;
+                       int i;
+
+                       sprintf(device, "%s/%s", DEVLABELDIR, ptname);
+                       if (access(device, F_OK)) {
+                           ptr = device;
+                           i = 0;
+                           while (*ptr)
+                               if (*ptr++ == '/')
+                                   i++;
+                           if (i > 2) {
+                               deviceDir = alloca(strlen(device) + 1);
+                               strcpy(deviceDir, device);
+                               ptr = deviceDir + (strlen(device) - 1);
+                               while (*ptr != '/')
+                                   *ptr-- = '\0';
+                               if (mkdir(deviceDir, 0644)) {
+                                   printf("mkdir: cannot create directory %s: %d\n", deviceDir, errno);
+                               } else {
+                                   mustRemoveDir = 1;
+                               }
+                           }
+
+                           mknod(device, S_IFBLK | 0600, makedev(ma, mi));
+                           mustRemove = 1;
+                       }
+                       if (!get_label_uuid(device, &label, uuid))
+                               uuidcache_addentry(strdup(device), ma, mi, 
+                                                  label, uuid);
+
+                       if (mustRemove) unlink(device);
+                       if (mustRemoveDir) rmdir(deviceDir);
+               }
+           }
+       }
+
+       fclose(procpt);
+}
+
+#define UUID   1
+#define VOL    2
+
+static char *
+get_spec_by_x(int n, const char *t, int * majorPtr, int * minorPtr) {
+       struct uuidCache_s *uc;
+
+       uuidcache_init();
+       uc = uuidCache;
+
+       while(uc) {
+               switch (n) {
+               case UUID:
+                       if (!memcmp(t, uc->uuid, sizeof(uc->uuid))) {
+                               *majorPtr = uc->major;
+                               *minorPtr = uc->minor;
+                               return uc->device;
+                       }
+                       break;
+               case VOL:
+                       if (!strcmp(t, uc->label)) {
+                               *majorPtr = uc->major;
+                               *minorPtr = uc->minor;
+                               return uc->device;
+                       }
+                       break;
+               }
+               uc = uc->next;
+       }
+       return NULL;
+}
+
+static unsigned char
+fromhex(char c) {
+       if (isdigit(c))
+               return (c - '0');
+       else if (islower(c))
+               return (c - 'a' + 10);
+       else
+               return (c - 'A' + 10);
+}
+
+char *
+get_spec_by_uuid(const char *s, int * major, int * minor) {
+       unsigned char uuid[16];
+       int i;
+
+       if (strlen(s) != 36 ||
+           s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-')
+               goto bad_uuid;
+       for (i=0; i<16; i++) {
+           if (*s == '-') s++;
+           if (!isxdigit(s[0]) || !isxdigit(s[1]))
+                   goto bad_uuid;
+           uuid[i] = ((fromhex(s[0])<<4) | fromhex(s[1]));
+           s += 2;
+       }
+       return get_spec_by_x(UUID, (char *)uuid, major, minor);
+
+ bad_uuid:
+       fprintf(stderr, _("mount: bad UUID"));
+       return 0;
+}
+
+char *
+get_spec_by_volume_label(const char *s, int * major, int * minor) {
+       return get_spec_by_x(VOL, s, major, minor);
+}
+
+int display_uuid_cache(void) {
+       struct uuidCache_s * u;
+       size_t i;
+
+       uuidcache_init();
+
+       u = uuidCache;
+       while (u) {
+           printf("%s %s ", u->device, u->label);
+           for (i = 0; i < sizeof(u->uuid); i++) {
+               if (i == 4 || i == 6 || i == 8 || i == 10)
+                   printf("-");
+               printf("%x", u->uuid[i] & 0xff);
+           }
+           printf("\n");
+           u = u->next;
+       }
+
+       return 0;
+}
+
index 21866bff16e7748a9bcd02f55dc80a3f0317d1da..8ea6b0347c26d1c96234dfc9de2908b0ad1adcb2 100644 (file)
@@ -1,2 +1,2 @@
-char * get_spec_by_uuid(const char *uuid, int * major, int * minor);\r
-char * get_spec_by_volume_label(const char *volumelabel, int * major, int * minor);\r
+char * get_spec_by_uuid(const char *uuid, int * major, int * minor);
+char * get_spec_by_volume_label(const char *volumelabel, int * major, int * minor);
diff --git a/src/nash/name_to_dev_t.c b/src/nash/name_to_dev_t.c
new file mode 100644 (file)
index 0000000..e882804
--- /dev/null
@@ -0,0 +1,139 @@
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <fcntl.h>
+
+static dev_t try_name(char *name, int part)
+{
+       char path[64];
+       char buf[32];
+       int range;
+       dev_t res;
+       char *s;
+       int len;
+       int fd;
+       unsigned int maj, min;
+
+       /* read device number from .../dev */
+
+       sprintf(path, "/sys/block/%s/dev", name);
+       fd = open(path, O_RDONLY);
+       if (fd < 0)
+               goto fail;
+       len = read(fd, buf, 32);
+       close(fd);
+       if (len <= 0 || len == 32 || buf[len - 1] != '\n')
+               goto fail;
+       buf[len - 1] = '\0';
+       if (sscanf(buf, "%u:%u", &maj, &min) != 2)
+               goto fail;
+       res = makedev(maj, min);
+       if (maj != major(res) || min != minor(res))
+               goto fail;
+
+       /* if it's there and we are not looking for a partition - that's it */
+       if (!part)
+               return res;
+
+       /* otherwise read range from .../range */
+       snprintf(path, 64, "/sys/block/%s/range", name);
+       fd = open(path, O_RDONLY);
+       if (fd < 0)
+               goto fail;
+       len = read(fd, buf, 32);
+       close(fd);
+       if (len <= 0 || len == 32 || buf[len - 1] != '\n')
+               goto fail;
+       buf[len - 1] = '\0';
+       range = strtoul(buf, &s, 10);
+       if (*s)
+               goto fail;
+
+       /* if partition is within range - we got it */
+       if (part < range)
+               return res + part;
+fail:
+       return 0;
+}
+
+/*
+ *     Convert a name into device number.  We accept the following variants:
+ *
+ *     1) device number in hexadecimal represents itself
+ *     2) /dev/nfs represents Root_NFS (0xff)
+ *     3) /dev/<disk_name> represents the device number of disk
+ *     4) /dev/<disk_name><decimal> represents the device number
+ *         of partition - device number of disk plus the partition number
+ *     5) /dev/<disk_name>p<decimal> - same as the above, that form is
+ *        used when disk name of partitioned disk ends on a digit.
+ *
+ *     If name doesn't have fall into the categories above, we return 0.
+ *     sysfs is used to check if something is a disk name - it has
+ *     all known disks under bus/block/devices.  If the disk name
+ *     contains slashes, name of driverfs node has them replaced with
+ *     bangs.  try_name() does the actual checks, assuming that sysfs
+ *     is mounted on /sys.
+ *
+ *     Note that cases (1) and (2) are already handled by the kernel,
+ *     so we can ifdef them out, provided that we check real-root-dev
+ *     first.
+ */
+
+dev_t name_to_dev_t(char *name)
+{
+       char s[32];
+       char *p;
+       dev_t res = 0;
+       int part;
+
+       if (strncmp(name, "/dev/", 5) != 0) {
+#if 1 /* kernel used to do this */
+               unsigned maj, min;
+
+               if (sscanf(name, "%u:%u", &maj, &min) == 2) {
+                       res = makedev(maj, min);
+                       if (maj != major(res) || min != minor(res))
+                               return 0;
+               } else {
+                       res = strtoul(name, &p, 16);
+                       if (*p)
+                               return 0;
+               }
+#endif
+               return res;
+       }
+
+       name += 5;
+
+#if 1 /* kernel used to do this */
+       if (strcmp(name, "nfs") == 0)
+               return makedev(0, 255);
+#endif
+
+       if (strlen(name) > 31)
+               return 0;
+       strcpy(s, name);
+       for (p = s; *p; p++)
+               if (*p == '/')
+                       *p = '!';
+       res = try_name(s, 0);
+       if (res)
+               return res;
+
+       while (p > s && isdigit(p[-1]))
+               p--;
+       if (p == s || !*p || *p == '0')
+               return 0;
+       part = strtoul(p, NULL, 10);
+       *p = '\0';
+       res = try_name(s, part);
+       if (res)
+               return res;
+
+       if (p < s + 2 || !isdigit(p[-2]) || p[-1] != 'p')
+               return 0;
+       p[-1] = '\0';
+       return try_name(s, part);
+}
index f895ffa45493f0bb53d0141a87ea5b4037745af8..73ac16bfa0c4540ee2dfb6395fe7bb3f9e102e41 100644 (file)
@@ -1,5 +1,4 @@
-.TH NASH 8 "Sat Mar 27 1999"
-.UC 4
+.TH NASH 8 "Mon Aug 02 2004"
 .SH NAME
 nash \- script interpretor to interpret linuxrc images
 .SH SYNOPSIS
@@ -69,6 +68,12 @@ Creates a device inode for \fIpath\fR. This is identical to \fBmkdev\fR(1)
 which the exceptions that it will not create named pipes and if the directories
 in \fIpath\fR do not exist they will be automatically created.
 
+.TP
+\fBmkdmnod\fR
+Creates a device inode for the device mapper control inode as
+\fI/dev/mapper/control\fR.  If it already exists with the correct
+major/minor, it will not be recreated.
+
 .TP
 \fBmkrootdev \fIpath\fR
 Makes \fIpath\fR a block inode for the device which should be mounted
@@ -93,15 +98,33 @@ The \fBdefaults\fR mount option is silently ignored.
 Makes the filesystem mounted at \fInewrootpath\fR the new root filesystem,
 and mounts the current root filesystem as \fIoldrootpath\fR.
 
+.TP
+\fBreadlink \fIpath\fR
+Displays the value of the symbolic link \fIpath\fR.
+
 .TP
 \fBraidautorun \fImddevice\fR
 Runs raid autodetection on all raid-typed partitions. \fImddevice\fR must
 be a raid device (any will do).
 
+.TP
+\fBsetquiet\fR
+Cause any later echos in this script to not be displayed.
+
 .TP
 \fBshowlabels\fR
 Display a table of devices, their filesystem labels, and their uuids.
 
+.TP
+\fBsleep \fInum\fR
+Sleep for \fInum\fR seconds
+
+.TP
+\fBswitchroot \fInewrootpath\fR
+Makes the filesystem mounted at \fInewrootpath\fR the new root
+filesystem by moving the mountpoint.  This will only work in 2.6 or
+later kernels.
+
 .TP
 \fBumount \fIpath\fR
 Unmounts the filesystem mounted at \fIpath\fR.
index cfde50c0bd2f2ccfe5b3d68b98237365da52d818..42525b5a01177cf7ef77e7f47a282a602f0c4bcd 100644 (file)
-/*\r
- * nash.c\r
- * \r
- * Simple code to load modules, mount root, and get things going. Uses\r
- * dietlibc to keep things small.\r
- *\r
- * Erik Troan (ewt@redhat.com)\r
- *\r
- * Copyright 2002 Red Hat Software \r
- *\r
- * This software may be freely redistributed under the terms of the GNU\r
- * public license.\r
- *\r
- * You should have received a copy of the GNU General Public License\r
- * along with this program; if not, write to the Free Software\r
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\r
- *\r
- */\r
-\r
-/* We internalize losetup, mount, raidautorun, and echo commands. Other\r
-   commands are run from the filesystem. Comments and blank lines work as \r
-   well, argument parsing is screwy. */\r
-\r
-#include <ctype.h>\r
-#include <dirent.h>\r
-#include <errno.h>\r
-#include <fcntl.h>\r
-#include <net/if.h>\r
-#include <signal.h>\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <string.h>\r
-#include <sys/ioctl.h>\r
-#include <sys/mount.h>\r
-#include <sys/socket.h>\r
-#include <sys/stat.h>\r
-#include <sys/time.h>\r
-#include <sys/types.h>\r
-#include <sys/un.h>\r
-#include <sys/wait.h>\r
-#include <unistd.h>\r
-#include <sys/ioctl.h>\r
-#include <sys/reboot.h>\r
-#include <termios.h>\r
-\r
-#include <asm/unistd.h>\r
-\r
-#include "mount_by_label.h"\r
-\r
-/* Need to tell loop.h what the actual dev_t type is. */\r
-#undef dev_t\r
-#if defined(__alpha) || (defined(__sparc__) && defined(__arch64__))\r
-#define dev_t unsigned int\r
-#else\r
-#define dev_t unsigned short\r
-#endif\r
-#include <linux/loop.h>\r
-#undef dev_t\r
-#define dev_t dev_t\r
-\r
-#define syslog klogctl\r
-\r
-#include <linux/cdrom.h>\r
-#define MD_MAJOR 9\r
-#include <linux/raid/md_u.h>\r
-\r
-#ifndef RAID_AUTORUN\r
-#define RAID_AUTORUN           _IO (MD_MAJOR, 0x14)\r
-#endif\r
-\r
-#ifndef MS_REMOUNT\r
-#define MS_REMOUNT      32\r
-#endif\r
-\r
-#ifdef USE_DIET\r
-static inline _syscall2(int,pivot_root,const char *,one,const char *,two)\r
-#endif\r
-\r
-#define MAX(a, b) ((a) > (b) ? a : b)\r
-\r
-int testing = 0, quiet = 0;\r
-\r
-#define PATH "/usr/bin:/bin:/sbin:/usr/sbin"\r
-\r
-char * env[] = {\r
-    "PATH=" PATH,\r
-    NULL\r
-};\r
-\r
-int smartmknod(char * device, mode_t mode, dev_t dev) {\r
-    char buf[256];\r
-    char * end;\r
-\r
-    strcpy(buf, device);\r
-\r
-    end = buf;\r
-    while (*end) {\r
-       if (*end == '/') {\r
-           *end = '\0';\r
-           if (access(buf, F_OK) && errno == ENOENT) \r
-               mkdir(buf, 0700);\r
-           *end = '/';\r
-       }\r
-\r
-       end++;\r
-    }\r
-\r
-    return mknod(device, mode, dev);\r
-}\r
-\r
-char * getArg(char * cmd, char * end, char ** arg) {\r
-    char quote = '\0';\r
-\r
-    if (cmd >= end) return NULL;\r
-\r
-    while (isspace(*cmd) && cmd < end) cmd++;\r
-    if (cmd >= end) return NULL;\r
-\r
-    if (*cmd == '"')\r
-       cmd++, quote = '"';\r
-    else if (*cmd == '\'')\r
-       cmd++, quote = '\'';\r
-\r
-    if (quote) {\r
-       *arg = cmd;\r
-\r
-       /* This doesn't support \ escapes */\r
-       while (cmd < end && *cmd != quote) cmd++;\r
-\r
-       if (cmd == end) {\r
-           printf("error: quote mismatch for %s\n", *arg);\r
-           return NULL;\r
-       }\r
-\r
-       *cmd = '\0';\r
-       cmd++;\r
-    } else {\r
-       *arg = cmd;\r
-       while (!isspace(*cmd) && cmd < end) cmd++;\r
-       *cmd = '\0';\r
-    }\r
-\r
-    cmd++;\r
-\r
-    while (isspace(*cmd)) cmd++;\r
-\r
-    return cmd;\r
-}\r
-\r
-int mountCommand(char * cmd, char * end) {\r
-    char * fsType = NULL;\r
-    char * device;\r
-    char * mntPoint;\r
-    char * deviceDir;\r
-    char * options = NULL;\r
-    int mustRemove = 0;\r
-    int mustRemoveDir = 0;\r
-    int rc;\r
-    int flags = MS_MGC_VAL;\r
-    char * newOpts;\r
-\r
-    cmd = getArg(cmd, end, &device);\r
-    if (!cmd) {\r
-       printf("usage: mount [--ro] [-o <opts>] -t <type> <device> <mntpoint>\n");\r
-       return 1;\r
-    }\r
-\r
-    while (cmd && *device == '-') {\r
-       if (!strcmp(device, "--ro")) {\r
-           flags |= MS_RDONLY;\r
-       } else if (!strcmp(device, "-o")) {\r
-           cmd = getArg(cmd, end, &options);\r
-           if (!cmd) {\r
-               printf("mount: -o requires arguments\n");\r
-               return 1;\r
-           }\r
-       } else if (!strcmp(device, "-t")) {\r
-           if (!(cmd = getArg(cmd, end, &fsType))) {\r
-               printf("mount: missing filesystem type\n");\r
-               return 1;\r
-           }\r
-       }\r
-\r
-       cmd = getArg(cmd, end, &device);\r
-    }\r
-\r
-    if (!cmd) {\r
-       printf("mount: missing device\n");\r
-       return 1;\r
-    }\r
-\r
-    if (!(cmd = getArg(cmd, end, &mntPoint))) {\r
-       printf("mount: missing mount point\n");\r
-       return 1;\r
-    }\r
-\r
-    if (!fsType) {\r
-       printf("mount: filesystem type expected\n");\r
-       return 1;\r
-    }\r
-\r
-    if (cmd < end) {\r
-       printf("mount: unexpected arguments\n");\r
-       return 1;\r
-    }\r
-\r
-    /* need to deal with options */ \r
-    if (options) {\r
-       char * end;\r
-       char * start = options;\r
-\r
-       newOpts = alloca(strlen(options) + 1);\r
-       *newOpts = '\0';\r
-\r
-       while (*start) {\r
-           end = strchr(start, ',');\r
-           if (!end) {\r
-               end = start + strlen(start);\r
-           } else {\r
-               *end = '\0';\r
-               end++;\r
-           }\r
-\r
-           if (!strcmp(start, "ro"))\r
-               flags |= MS_RDONLY;\r
-           else if (!strcmp(start, "rw"))\r
-               flags &= ~MS_RDONLY;\r
-           else if (!strcmp(start, "nosuid"))\r
-               flags |= MS_NOSUID;\r
-           else if (!strcmp(start, "suid"))\r
-               flags &= ~MS_NOSUID;\r
-           else if (!strcmp(start, "nodev"))\r
-               flags |= MS_NODEV;\r
-           else if (!strcmp(start, "dev"))\r
-               flags &= ~MS_NODEV;\r
-           else if (!strcmp(start, "noexec"))\r
-               flags |= MS_NOEXEC;\r
-           else if (!strcmp(start, "exec"))\r
-               flags &= ~MS_NOEXEC;\r
-           else if (!strcmp(start, "sync"))\r
-               flags |= MS_SYNCHRONOUS;\r
-           else if (!strcmp(start, "async"))\r
-               flags &= ~MS_SYNCHRONOUS;\r
-           else if (!strcmp(start, "nodiratime"))\r
-               flags |= MS_NODIRATIME;\r
-           else if (!strcmp(start, "diratime"))\r
-               flags &= ~MS_NODIRATIME;\r
-           else if (!strcmp(start, "noatime"))\r
-               flags |= MS_NOATIME;\r
-           else if (!strcmp(start, "atime"))\r
-               flags &= ~MS_NOATIME;\r
-           else if (!strcmp(start, "remount"))\r
-               flags |= MS_REMOUNT;\r
-           else if (!strcmp(start, "defaults"))\r
-               ;\r
-           else {\r
-               if (*newOpts)\r
-                   strcat(newOpts, ",");\r
-               strcat(newOpts, start);\r
-           }\r
-\r
-           start = end;\r
-       }\r
-\r
-       options = newOpts;\r
-    }\r
-\r
-    if (!strncmp("LABEL=", device, 6)) {\r
-       int major, minor;\r
-       char * devName;\r
-       char * ptr;\r
-       int i;\r
-\r
-       devName = get_spec_by_volume_label(device + 6, &major, &minor);\r
-\r
-       if (devName) {\r
-           device = devName;\r
-           if (access(device, F_OK)) {\r
-               ptr = device;\r
-               i = 0;\r
-               while (*ptr)\r
-                   if (*ptr++ == '/')\r
-                       i++;\r
-               if (i > 2) {\r
-                   deviceDir = alloca(strlen(device) + 1);\r
-                   strcpy(deviceDir, device);\r
-                   ptr = deviceDir + (strlen(device) - 1);\r
-                   while (*ptr != '/')\r
-                       *ptr-- = '\0';\r
-                   if (mkdir(deviceDir, 0644)) {\r
-                     printf("mkdir: cannot create directory %s\n", deviceDir);\r
-                   } else {\r
-                     mustRemoveDir = 1;\r
-                   }\r
-               }\r
-               if (smartmknod(device, S_IFBLK | 0600, makedev(major, minor))) {\r
-                   printf("mount: cannot create device %s (%d,%d)\n",\r
-                          device, major, minor);\r
-                   return 1;\r
-               }\r
-               mustRemove = 1;\r
-           }\r
-       }\r
-    }\r
-\r
-    if (testing) {\r
-       printf("mount %s%s%s-t '%s' '%s' '%s' (%s%s%s%s%s%s%s)\n", \r
-               options ? "-o '" : "",  \r
-               options ? options : "", \r
-               options ? "\' " : "",   \r
-               fsType, device, mntPoint,\r
-               (flags & MS_RDONLY) ? "ro " : "",\r
-               (flags & MS_NOSUID) ? "nosuid " : "",\r
-               (flags & MS_NODEV) ? "nodev " : "",\r
-               (flags & MS_NOEXEC) ? "noexec " : "",\r
-               (flags & MS_SYNCHRONOUS) ? "sync " : "",\r
-               (flags & MS_REMOUNT) ? "remount " : "",\r
-               (flags & MS_NOATIME) ? "noatime " : ""\r
-           );\r
-    } else {\r
-       if (mount(device, mntPoint, fsType, flags, options)) {\r
-           printf("mount: error %d mounting %s\n", errno, fsType);\r
-           rc = 1;\r
-       }\r
-    }\r
-\r
-    if (mustRemove) unlink(device);\r
-    if (mustRemoveDir) rmdir(deviceDir);\r
-\r
-    return rc;\r
-}\r
-\r
-int otherCommand(char * bin, char * cmd, char * end, int doFork) {\r
-    char * args[128];\r
-    char ** nextArg;\r
-    int pid;\r
-    int status;\r
-    char fullPath[255];\r
-    const static char * sysPath = PATH;\r
-    const char * pathStart;\r
-    const char * pathEnd;\r
-    char * stdoutFile = NULL;\r
-    int stdoutFd = 0;\r
-\r
-    nextArg = args;\r
-\r
-    if (!strchr(bin, '/')) {\r
-       pathStart = sysPath;\r
-       while (*pathStart) {\r
-           pathEnd = strchr(pathStart, ':');\r
-\r
-           if (!pathEnd) pathEnd = pathStart + strlen(pathStart);\r
-\r
-           strncpy(fullPath, pathStart, pathEnd - pathStart);\r
-           fullPath[pathEnd - pathStart] = '/';\r
-           strcpy(fullPath + (pathEnd - pathStart + 1), bin); \r
-\r
-           pathStart = pathEnd;\r
-           if (*pathStart) pathStart++;\r
-\r
-           if (!access(fullPath, X_OK)) {\r
-               bin = fullPath;\r
-               break;\r
-           }\r
-       }\r
-    }\r
-\r
-    *nextArg = bin;\r
-\r
-    while (cmd && cmd < end) {\r
-       nextArg++;\r
-       cmd = getArg(cmd, end, nextArg);\r
-    }\r
-       \r
-    if (cmd) nextArg++;\r
-    *nextArg = NULL;\r
-\r
-    /* if the next-to-last arg is a >, redirect the output properly */\r
-    if (((nextArg - args) >= 2) && !strcmp(*(nextArg - 2), ">")) {\r
-       stdoutFile = *(nextArg - 1);\r
-       *(nextArg - 2) = NULL;\r
-\r
-       stdoutFd = open(stdoutFile, O_CREAT | O_RDWR | O_TRUNC, 0600);\r
-       if (stdoutFd < 0) {\r
-           printf("nash: failed to open %s: %d\n", stdoutFile, errno);\r
-           return 1;\r
-       }\r
-    }\r
-\r
-    if (testing) {\r
-       printf("%s ", bin);\r
-       nextArg = args + 1;\r
-       while (*nextArg)\r
-           printf(" '%s'", *nextArg++);\r
-       if (stdoutFile)\r
-           printf(" (> %s)", stdoutFile);\r
-       printf("\n");\r
-    } else {\r
-       if (!doFork || !(pid = fork())) {\r
-           /* child */\r
-           dup2(stdoutFd, 1);\r
-           execve(args[0], args, env);\r
-           printf("ERROR: failed in exec of %s\n", args[0]);\r
-           return 1;\r
-       }\r
-\r
-       close(stdoutFd);\r
-\r
-       wait4(-1, &status, 0, NULL);\r
-       if (!WIFEXITED(status) || WEXITSTATUS(status)) {\r
-           printf("ERROR: %s exited abnormally!\n", args[0]);\r
-           return 1;\r
-       }\r
-    }\r
-\r
-    return 0;\r
-}\r
-\r
-int execCommand(char * cmd, char * end) {\r
-    char * bin;\r
-\r
-    if (!(cmd = getArg(cmd, end, &bin))) {\r
-       printf("exec: argument expected\n");\r
-       return 1;\r
-    }\r
-\r
-    return otherCommand(bin, cmd, end, 0);\r
-}\r
-\r
-int losetupCommand(char * cmd, char * end) {\r
-    char * device;\r
-    char * file;\r
-    int fd;\r
-    struct loop_info loopInfo;\r
-    int dev;\r
-\r
-    if (!(cmd = getArg(cmd, end, &device))) {\r
-       printf("losetup: missing device\n");\r
-       return 1;\r
-    }\r
-\r
-    if (!(cmd = getArg(cmd, end, &file))) {\r
-       printf("losetup: missing file\n");\r
-       return 1;\r
-    }\r
-\r
-    if (cmd < end) {\r
-       printf("losetup: unexpected arguments\n");\r
-       return 1;\r
-    }\r
-\r
-    if (testing) {\r
-       printf("losetup '%s' '%s'\n", device, file);\r
-    } else {\r
-       dev = open(device, O_RDWR, 0);\r
-       if (dev < 0) {\r
-           printf("losetup: failed to open %s: %d\n", device, errno);\r
-           return 1;\r
-       }\r
-\r
-       fd = open(file, O_RDWR, 0);\r
-       if (fd < 0) {\r
-           printf("losetup: failed to open %s: %d\n", file, errno);\r
-           close(dev);\r
-           return 1;\r
-       }\r
-\r
-       if (ioctl(dev, LOOP_SET_FD, (long) fd)) {\r
-           printf("losetup: LOOP_SET_FD failed: %d\n", errno);\r
-           close(dev);\r
-           close(fd);\r
-           return 1;\r
-       }\r
-\r
-       close(fd);\r
-\r
-       memset(&loopInfo, 0, sizeof(loopInfo));\r
-       strcpy(loopInfo.lo_name, file);\r
-\r
-       if (ioctl(dev, LOOP_SET_STATUS, &loopInfo)) \r
-           printf("losetup: LOOP_SET_STATUS failed: %d\n", errno);\r
-\r
-       close(dev);\r
-    }\r
-\r
-    return 0;\r
-}\r
-\r
-int raidautorunCommand(char * cmd, char * end) {\r
-    char * device;\r
-    int fd;\r
-\r
-    if (!(cmd = getArg(cmd, end, &device))) {\r
-       printf("raidautorun: raid device expected as first argument\n");\r
-       return 1;\r
-    }\r
-\r
-    if (cmd < end) {\r
-       printf("raidautorun: unexpected arguments\n");\r
-       return 1;\r
-    }\r
-\r
-    fd = open(device, O_RDWR, 0);\r
-    if (fd < 0) {\r
-       printf("raidautorun: failed to open %s: %d\n", device, errno);\r
-       return 1;\r
-    }\r
-\r
-    if (ioctl(fd, RAID_AUTORUN, 0)) {\r
-       printf("raidautorun: RAID_AUTORUN failed: %d\n", errno);\r
-       close(fd);\r
-       return 1;\r
-    }\r
-\r
-    close(fd);\r
-    return 0;\r
-}\r
-\r
-static int my_pivot_root(char * one, char * two) {\r
-#ifdef USE_DIET\r
-    return pivot_root(one, two);\r
-#else\r
-    return syscall(__NR_pivot_root, one, two);\r
-#endif\r
-}\r
-\r
-int pivotrootCommand(char * cmd, char * end) {\r
-    char * new;\r
-    char * old;\r
-\r
-    if (!(cmd = getArg(cmd, end, &new))) {\r
-       printf("pivotroot: new root mount point expected\n");\r
-       return 1;\r
-    }\r
-\r
-    if (!(cmd = getArg(cmd, end, &old))) {\r
-       printf("pivotroot: old root mount point expected\n");\r
-       return 1;\r
-    }\r
-\r
-    if (cmd < end) {\r
-       printf("pivotroot: unexpected arguments\n");\r
-       return 1;\r
-    }\r
-\r
-    if (my_pivot_root(new, old)) {\r
-       printf("pivotroot: pivot_root(%s,%s) failed: %d\n", new, old, errno);\r
-       return 1;\r
-    }\r
-\r
-    return 0;\r
-}\r
-\r
-int echoCommand(char * cmd, char * end) {\r
-    char * args[256];\r
-    char ** nextArg = args;\r
-    int outFd = 1;\r
-    int num = 0;\r
-    int i;\r
-\r
-    if (testing && !quiet) {\r
-       printf("(echo) ");\r
-       fflush(stdout);\r
-    }\r
-\r
-    while ((cmd = getArg(cmd, end, nextArg)))\r
-       nextArg++, num++;\r
-\r
-    if ((nextArg - args >= 2) && !strcmp(*(nextArg - 2), ">")) {\r
-       outFd = open(*(nextArg - 1), O_RDWR | O_CREAT | O_TRUNC, 0644);\r
-       if (outFd < 0) {\r
-           printf("echo: cannot open %s for write: %d\n", \r
-                   *(nextArg - 1), errno);\r
-           return 1;\r
-       }\r
-\r
-       num -= 2;\r
-    }\r
-\r
-    for (i = 0; i < num;i ++) {\r
-       if (i)\r
-           write(outFd, " ", 1);\r
-       write(outFd, args[i], strlen(args[i]));\r
-    }\r
-\r
-    write(outFd, "\n", 1);\r
-\r
-    if (outFd != 1) close(outFd);\r
-\r
-    return 0;\r
-}\r
-\r
-int umountCommand(char * cmd, char * end) {\r
-    char * path;\r
-\r
-    if (!(cmd = getArg(cmd, end, &path))) {\r
-       printf("umount: path expected\n");\r
-       return 1;\r
-    }\r
-\r
-    if (cmd < end) {\r
-       printf("umount: unexpected arguments\n");\r
-       return 1;\r
-    }\r
-\r
-    if (umount(path)) {\r
-       printf("umount %s failed: %d\n", path, errno);\r
-       return 1;\r
-    }\r
-\r
-    return 0;\r
-}\r
-\r
-int mkrootdevCommand(char * cmd, char * end) {\r
-    char * path;\r
-    char * start, * chptr;\r
-    unsigned int devNum = 0;\r
-    int fd;\r
-    int i;\r
-    char buf[1024];\r
-    int major, minor;\r
-\r
-    if (!(cmd = getArg(cmd, end, &path))) {\r
-       printf("mkrootdev: path expected\n");\r
-       return 1;\r
-    }\r
-\r
-    if (cmd < end) {\r
-       printf("mkrootdev: unexpected arguments\n");\r
-       return 1;\r
-    }\r
-\r
-    fd = open("/proc/cmdline", O_RDONLY, 0);\r
-    if (fd < 0) {\r
-       printf("mkrootdev: failed to open /proc/cmdline: %d\n", errno);\r
-       return 1;\r
-    }\r
-\r
-    i = read(fd, buf, sizeof(buf));\r
-    if (i < 0) {\r
-       printf("mkrootdev: failed to read /proc/cmdline: %d\n", errno);\r
-       close(fd);\r
-       return 1;\r
-    }\r
-\r
-    close(fd);\r
-    buf[i - 1] = '\0';\r
-\r
-    start = buf;\r
-    while (*start && isspace(*start)) start++;\r
-    while (*start && strncmp(start, "root=", 5)) {\r
-       while (*start && !isspace(*start)) start++;\r
-       while (*start && isspace(*start)) start++;\r
-    }\r
-\r
-    start += 5;\r
-    chptr = start;\r
-    while (*chptr && !isspace(*chptr)) chptr++;\r
-    *chptr = '\0';\r
-\r
-    if (!strncmp(start, "LABEL=", 6)) {\r
-       if (get_spec_by_volume_label(start + 6, &major, &minor)) {\r
-           if (smartmknod(path, S_IFBLK | 0600, makedev(major, minor))) {\r
-               printf("mount: cannot create device %s (%d,%d)\n",\r
-                      path, major, minor);\r
-               return 1;\r
-           }\r
-\r
-           return 0;\r
-       }\r
-\r
-       printf("mkrootdev: label %s not found\n", start + 6);\r
-\r
-       return 1;\r
-    }\r
-\r
-    fd = open("/proc/sys/kernel/real-root-dev", O_RDONLY, 0);\r
-    if (fd < 0) {\r
-       printf("mkrootdev: failed to open /proc/sys/kernel/real-root-dev: %d\n", errno);\r
-       return 1;\r
-    }\r
-\r
-    i = read(fd, buf, sizeof(buf));\r
-    if (i < 0) {\r
-       printf("mkrootdev: failed to read real-root-dev: %d\n", errno);\r
-       close(fd);\r
-       return 1;\r
-    }\r
-\r
-    close(fd);\r
-    buf[i - 1] = '\0';\r
-\r
-    devNum = atoi(buf);\r
-    if (devNum < 0) {\r
-       printf("mkrootdev: bad device %s\n", buf);\r
-       return 1;\r
-    }\r
-\r
-    if (smartmknod(path, S_IFBLK | 0700, devNum)) {\r
-       printf("mkrootdev: mknod failed: %d\n", errno);\r
-       return 1;\r
-    }\r
-\r
-    return 0;\r
-}\r
-\r
-int mkdirCommand(char * cmd, char * end) {\r
-    char * dir;\r
-    int ignoreExists = 0;\r
-\r
-    cmd = getArg(cmd, end, &dir);\r
-\r
-    if (cmd && !strcmp(dir, "-p")) {\r
-       ignoreExists = 1;\r
-       cmd = getArg(cmd, end, &dir);\r
-    }\r
-\r
-    if (!cmd) {\r
-       printf("mkdir: directory expected\n");\r
-       return 1;\r
-    }\r
-\r
-    if (mkdir(dir, 0755)) {\r
-       if (!ignoreExists && errno == EEXIST) {\r
-           printf("mkdir: failed to create %s: %d\n", dir, errno);\r
-           return 1;\r
-       }\r
-    }\r
-\r
-    return 0;\r
-}\r
-\r
-int accessCommand(char * cmd, char * end) {\r
-    char * permStr;\r
-    int perms = 0;\r
-    char * file;\r
-\r
-    cmd = getArg(cmd, end, &permStr);\r
-    if (cmd) cmd = getArg(cmd, end, &file);\r
-\r
-    if (!cmd || *permStr != '-') {\r
-       printf("usage: access -[perm] file\n");\r
-       return 1;\r
-    }\r
-\r
-    permStr++;\r
-    while (*permStr) {\r
-       switch (*permStr) {\r
-         case 'r': perms |= R_OK; break;\r
-         case 'w': perms |= W_OK; break;\r
-         case 'x': perms |= X_OK; break;\r
-         case 'f': perms |= F_OK; break;\r
-         default:\r
-           printf("perms must be -[r][w][x][f]\n");\r
-           return 1;\r
-       }\r
-\r
-       permStr++;\r
-    }\r
-\r
-    if (access(file, perms))\r
-       return 1;\r
-\r
-    return 0;\r
-}\r
-\r
-int sleepCommand(char * cmd, char * end) {\r
-    char *delaystr;\r
-    int delay;\r
-\r
-    if (!(cmd = getArg(cmd, end, &delaystr))) {\r
-       printf("sleep: delay expected\n");\r
-       return 1;\r
-    }\r
-\r
-    delay = atoi(delaystr);\r
-    sleep(delay);\r
-\r
-    return 0;\r
-}\r
-\r
-int readlinkCommand(char * cmd, char * end) {\r
-    char * path;\r
-    char * buf, * respath, * fullpath;\r
-    struct stat sb;\r
-\r
-    if (!(cmd = getArg(cmd, end, &path))) {\r
-        printf("readlink: file expected\n");\r
-        return 1;\r
-    }\r
-\r
-    if (lstat(path, &sb) == -1) {\r
-        fprintf(stderr, "unable to stat %s: %d\n", path, errno);\r
-        return 1;\r
-    }\r
-\r
-    if (!S_ISLNK(sb.st_mode)) {\r
-        printf("%s\n", path);\r
-        return 0;\r
-    }\r
-    \r
-    buf = malloc(512);\r
-    if (readlink(path, buf, 512) == -1) {\r
-       fprintf(stderr, "error readlink %s: %d\n", path, errno);\r
-       return 1;\r
-    }\r
-\r
-    /* symlink is absolute */\r
-    if (buf[0] == '/') {\r
-        printf("%s\n", buf);\r
-        return 0;\r
-    } \r
-   \r
-    /* nope, need to handle the relative symlink case too */\r
-    respath = strrchr(path, '/');\r
-    if (respath) {\r
-        *respath = '\0';\r
-    }\r
-\r
-    fullpath = malloc(512);\r
-    /* and normalize it */\r
-    snprintf(fullpath, 512, "%s/%s", path, buf);\r
-    respath = malloc(PATH_MAX);\r
-    if (!(respath = realpath(fullpath, respath))) {\r
-        fprintf(stderr, "error realpath %s: %d\n", fullpath, errno);\r
-        return 1;\r
-    }\r
-\r
-    printf("%s\n", respath);\r
-    return 0;\r
-}\r
-\r
-int doFind(char * dirName, char * name) {\r
-    struct stat sb;\r
-    DIR * dir;\r
-    struct dirent * d;\r
-    char * strBuf = alloca(strlen(dirName) + 1024);\r
-\r
-    if (!(dir = opendir(dirName))) {\r
-       fprintf(stderr, "error opening %s: %d\n", dirName, errno);\r
-       return 0;\r
-    }\r
-\r
-    errno = 0;\r
-    while ((d = readdir(dir))) {\r
-       errno = 0;\r
-\r
-       strcpy(strBuf, dirName);\r
-       strcat(strBuf, "/");\r
-       strcat(strBuf, d->d_name);\r
-\r
-       if (!strcmp(d->d_name, name))\r
-           printf("%s\n", strBuf);\r
-\r
-       if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) {\r
-           errno = 0;\r
-           continue;\r
-       }\r
-\r
-       if (lstat(strBuf, &sb)) {\r
-           fprintf(stderr, "failed to stat %s: %d\n", strBuf, errno);\r
-           errno = 0;\r
-           continue;\r
-       }\r
-\r
-       if (S_ISDIR(sb.st_mode))\r
-           doFind(strBuf, name);\r
-    }\r
-\r
-    if (errno) {\r
-       closedir(dir);\r
-       printf("error reading from %s: %d\n", dirName, errno);\r
-       return 1;\r
-    }\r
-\r
-    closedir(dir);\r
-\r
-    return 0;\r
-}\r
-\r
-int findCommand(char * cmd, char * end) {\r
-    char * dir;\r
-    char * name;\r
-\r
-    cmd = getArg(cmd, end, &dir);\r
-    if (cmd) cmd = getArg(cmd, end, &name);\r
-    if (cmd && strcmp(name, "-name")) {\r
-       printf("usage: find [path] -name [file]\n");\r
-       return 1;\r
-    }\r
-\r
-    if (cmd) cmd = getArg(cmd, end, &name);\r
-    if (!cmd) {\r
-       printf("usage: find [path] -name [file]\n");\r
-       return 1;\r
-    }\r
-\r
-    return doFind(dir, name);\r
-}\r
-\r
-int findlodevCommand(char * cmd, char * end) {\r
-    char devName[20];\r
-    int devNum;\r
-    int fd;\r
-    struct loop_info loopInfo;\r
-    char separator[2] = "";\r
-\r
-    if (*end != '\n') {\r
-       printf("usage: findlodev\n");\r
-       return 1;\r
-    }\r
-\r
-    if (!access("/dev/.devfsd", X_OK))\r
-       strcpy(separator, "/");\r
-\r
-    for (devNum = 0; devNum < 256; devNum++) {\r
-       sprintf(devName, "/dev/loop%s%d", separator, devNum);\r
-       if ((fd = open(devName, O_RDONLY)) < 0) return 0;\r
-\r
-       if (ioctl(fd, LOOP_GET_STATUS, &loopInfo)) {\r
-           close(fd);\r
-           printf("%s\n", devName);\r
-           return 0;\r
-       }\r
-\r
-       close(fd);\r
-    }\r
-\r
-    return 0;\r
-}\r
-\r
-int mknodCommand(char * cmd, char * end) {\r
-    char * path, * type;\r
-    char * majorStr, * minorStr;\r
-    int major;\r
-    int minor;\r
-    char * chptr;\r
-    mode_t mode;\r
-\r
-    cmd = getArg(cmd, end, &path);\r
-    cmd = getArg(cmd, end, &type);\r
-    cmd = getArg(cmd, end, &majorStr);\r
-    cmd = getArg(cmd, end, &minorStr);\r
-    if (!minorStr) {\r
-       printf("mknod: usage mknod <path> [c|b] <major> <minor>\n");\r
-       return 1;\r
-    }\r
-\r
-    if (!strcmp(type, "b")) {\r
-       mode = S_IFBLK;\r
-    } else if (!strcmp(type, "c")) {\r
-       mode = S_IFCHR;\r
-    } else {\r
-       printf("mknod: invalid type\n");\r
-       return 1;\r
-    }\r
-\r
-    major = strtol(majorStr, &chptr, 10);\r
-    if (*chptr) {\r
-       printf("invalid major number\n");\r
-       return 1;\r
-    }\r
-\r
-    minor = strtol(minorStr, &chptr, 10);\r
-    if (*chptr) {\r
-       printf("invalid minor number\n");\r
-       return 1;\r
-    }\r
-\r
-    if (smartmknod(path, mode | 0600, makedev(major, minor))) {\r
-       printf("mknod: failed to create %s: %d\n", path, errno);\r
-       return 1;\r
-    }\r
-\r
-    return 0;\r
-}\r
-\r
-int mkdevicesCommand(char * cmd, char * end) {\r
-    int fd;\r
-    char buf[32768];\r
-    int i;\r
-    char * start, * chptr;\r
-    int major, minor;\r
-    char old;\r
-    char devName[128];\r
-    char * prefix;\r
-\r
-    if (!(cmd = getArg(cmd, end, &prefix))) {\r
-       printf("mkdevices: path expected\n");\r
-       return 1;\r
-    }\r
-\r
-    if (cmd < end) {\r
-       printf("mkdevices: unexpected arguments\n");\r
-       return 1;\r
-    }\r
-\r
-    if ((fd = open("/proc/partitions", O_RDONLY)) < 0) {\r
-       printf("mkrootdev: failed to open /proc/partitions: %d\n", errno);\r
-       return 1;\r
-    }\r
-\r
-    i = read(fd, buf, sizeof(buf));\r
-    if (i < 1) {\r
-       close(fd);\r
-       printf("failed to read /proc/partitions: %d\n", errno);\r
-       return 1;\r
-    }\r
-    buf[i] = '\0';\r
-    close(fd);\r
-\r
-    start = strchr(buf, '\n');\r
-    if (start) {\r
-       start++;\r
-       start = strchr(buf, '\n');\r
-    }\r
-    if (!start) return 1;\r
-\r
-    start = start + 1;\r
-    while (*start) {\r
-       while (*start && isspace(*start)) start++;\r
-       major = strtol(start, &chptr, 10);\r
-\r
-       if (start != chptr) {\r
-           start = chptr;\r
-           while (*start && isspace(*start)) start++;\r
-           minor = strtol(start, &chptr, 10);\r
-\r
-           if (start != chptr) {\r
-               start = chptr;\r
-               while (*start && isspace(*start)) start++;\r
-               while (*start && !isspace(*start)) start++;\r
-               while (*start && isspace(*start)) start++;\r
-\r
-               if (*start) {\r
-\r
-                   chptr = start;\r
-                   while (!isspace(*chptr)) chptr++;\r
-                   old = *chptr;\r
-                   *chptr = '\0';\r
-\r
-                   if (testing) {\r
-                       printf("% 3d % 3d %s\n", major, minor, start);\r
-                   } else {\r
-                       char * ptr, * deviceDir;\r
-                       int i;\r
-\r
-                       sprintf(devName, "%s/%s", prefix, start);\r
-                       unlink(devName);\r
-\r
-                       ptr = devName;\r
-                       i = 0;\r
-                       while (*ptr)\r
-                           if (*ptr++ == '/')\r
-                               i++;\r
-                       if (i > 2) {\r
-                           deviceDir = alloca(strlen(devName) + 1);\r
-                           strcpy(deviceDir, devName);\r
-                           ptr = deviceDir + (strlen(devName) - 1);\r
-                           while (*ptr != '/')\r
-                               *ptr-- = '\0';\r
-                           if (access(deviceDir, X_OK) && mkdir(deviceDir, 0644)) {\r
-                               printf("mkdir: cannot create directory %s: %d\n", deviceDir, errno);\r
-                           }\r
-                       }\r
-                       if (smartmknod(devName, S_IFBLK | 0600, \r
-                                 makedev(major, minor))) {\r
-                           printf("failed to create %s\n", devName);\r
-                       }\r
-                   }\r
-\r
-                   *chptr = old;\r
-                   start = chptr;\r
-               }\r
-\r
-           }\r
-       }\r
-\r
-       start = strchr(start, '\n');\r
-       if (!*start) return 1;\r
-       start = start + 1;\r
-    }\r
-\r
-    return 0;\r
-}\r
-\r
-int runStartup(int fd) {\r
-    char contents[32768];\r
-    int i;\r
-    char * start, * end;\r
-    char * chptr;\r
-    int rc;\r
-\r
-    i = read(fd, contents, sizeof(contents) - 1);\r
-    if (i == (sizeof(contents) - 1)) {\r
-       printf("Failed to read /startup.rc -- file too large.\n");\r
-       return 1;\r
-    }\r
-\r
-    contents[i] = '\0';\r
-\r
-    start = contents;\r
-    while (*start) {\r
-       while (isspace(*start) && *start && (*start != '\n')) start++;\r
-\r
-       if (*start == '#')\r
-           while (*start && (*start != '\n')) start++;\r
-\r
-       if (*start == '\n') {\r
-           start++;\r
-           continue;\r
-       }\r
-\r
-       if (!*start) {\r
-           printf("(last line in /startup.rc is empty)\n");\r
-           continue;\r
-       }\r
-\r
-       /* start points to the beginning of the command */\r
-       end = start + 1;\r
-       while (*end && (*end != '\n')) end++;\r
-       if (!*end) {\r
-           printf("(last line in /startup.rc missing \\n -- skipping)\n");\r
-           start = end;\r
-           continue;\r
-       }\r
-\r
-       /* end points to the \n at the end of the command */\r
-\r
-       chptr = start;\r
-       while (chptr < end && !isspace(*chptr)) chptr++;\r
-\r
-       if (!strncmp(start, "mount", MAX(5, chptr - start)))\r
-           rc = mountCommand(chptr, end);\r
-       else if (!strncmp(start, "losetup", MAX(7, chptr - start)))\r
-           rc = losetupCommand(chptr, end);\r
-       else if (!strncmp(start, "echo", MAX(4, chptr - start)))\r
-           rc = echoCommand(chptr, end);\r
-       else if (!strncmp(start, "raidautorun", MAX(11, chptr - start)))\r
-           rc = raidautorunCommand(chptr, end);\r
-       else if (!strncmp(start, "pivot_root", MAX(10, chptr - start)))\r
-           rc = pivotrootCommand(chptr, end);\r
-       else if (!strncmp(start, "mkrootdev", MAX(9, chptr - start)))\r
-           rc = mkrootdevCommand(chptr, end);\r
-       else if (!strncmp(start, "umount", MAX(6, chptr - start)))\r
-           rc = umountCommand(chptr, end);\r
-       else if (!strncmp(start, "exec", MAX(4, chptr - start)))\r
-           rc = execCommand(chptr, end);\r
-       else if (!strncmp(start, "mkdir", MAX(5, chptr - start)))\r
-           rc = mkdirCommand(chptr, end);\r
-       else if (!strncmp(start, "access", MAX(6, chptr - start)))\r
-           rc = accessCommand(chptr, end);\r
-       else if (!strncmp(start, "find", MAX(4, chptr - start)))\r
-           rc = findCommand(chptr, end);\r
-       else if (!strncmp(start, "findlodev", MAX(7, chptr - start)))\r
-           rc = findlodevCommand(chptr, end);\r
-       else if (!strncmp(start, "showlabels", MAX(10, chptr-start)))\r
-           rc = display_uuid_cache();\r
-       else if (!strncmp(start, "mkdevices", MAX(9, chptr-start)))\r
-           rc = mkdevicesCommand(chptr, end);\r
-       else if (!strncmp(start, "sleep", MAX(5, chptr-start)))\r
-           rc = sleepCommand(chptr, end);\r
-       else if (!strncmp(start, "mknod", MAX(5, chptr-start)))\r
-           rc = mknodCommand(chptr, end);\r
-        else if (!strncmp(start, "readlink", MAX(8, chptr-start)))\r
-            rc = readlinkCommand(chptr, end);\r
-       else {\r
-           *chptr = '\0';\r
-           rc = otherCommand(start, chptr + 1, end, 1);\r
-       }\r
-\r
-       start = end + 1;\r
-    }\r
-\r
-    return rc;\r
-}\r
-\r
-int main(int argc, char **argv) {\r
-    int fd = 0;\r
-    char * name;\r
-    int rc;\r
-    int force = 0;\r
-\r
-    name = strrchr(argv[0], '/');\r
-    if (!name) \r
-       name = argv[0];\r
-    else\r
-       name++;\r
-\r
-    if (!strcmp(name, "modprobe"))\r
-       exit(0);\r
-\r
-    testing = (getppid() != 0) && (getppid() != 1);\r
-    argv++, argc--;\r
-\r
-    while (argc && **argv == '-') {\r
-       if (!strcmp(*argv, "--force")) {\r
-           force = 1;\r
-           argv++, argc--;\r
-           testing = 0;\r
-       } else if (!strcmp(*argv, "--quiet")) {\r
-           quiet = 1;\r
-           argv++, argc--;\r
-       } else {\r
-           printf("unknown argument %s\n", *argv);\r
-           return 1;\r
-       }\r
-    }\r
-\r
-    if (force && !quiet)\r
-       printf("(forcing normal run)\n");\r
-\r
-    if (testing && !quiet)\r
-       printf("(running in test mode).\n");\r
-\r
-    if (!quiet) printf("Red Hat nash version %s starting\n", VERSION);\r
-\r
-    if (*argv) {\r
-       fd = open(*argv, O_RDONLY, 0);\r
-       if (fd < 0) {\r
-           printf("nash: cannot open %s: %d\n", *argv, errno);\r
-           exit(1);\r
-       }\r
-    }\r
-\r
-    rc = runStartup(fd);\r
-    close(fd);\r
-\r
-    return rc;\r
-}\r
+/*
+ * nash.c
+ * 
+ * Simple code to load modules, mount root, and get things going. Uses
+ * dietlibc to keep things small.
+ *
+ * Erik Troan (ewt@redhat.com)
+ * Jeremy Katz (katzj@redhat.com)
+ * Peter Jones (pjones@redhat.com)
+ *
+ * Copyright 2002-2005 Red Hat Software 
+ *
+ * This software may be freely redistributed under the terms of the GNU
+ * public license.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+/* We internalize losetup, mount, raidautorun, and echo commands. Other
+   commands are run from the filesystem. Comments and blank lines work as 
+   well, argument parsing is screwy. */
+
+#include <ctype.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <net/if.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/mount.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/reboot.h>
+#include <termios.h>
+
+#include <asm/unistd.h>
+
+#include "mount_by_label.h"
+
+/* Need to tell loop.h what the actual dev_t type is. */
+#undef dev_t
+#if defined(__alpha) || (defined(__sparc__) && defined(__arch64__))
+#define dev_t unsigned int
+#else
+#define dev_t unsigned short
+#endif
+#include <linux/loop.h>
+#undef dev_t
+#define dev_t dev_t
+
+#define syslog klogctl
+
+#include <linux/cdrom.h>
+#define MD_MAJOR 9
+#include <linux/raid/md_u.h>
+
+#ifndef RAID_AUTORUN
+#define RAID_AUTORUN           _IO (MD_MAJOR, 0x14)
+#endif
+
+#ifndef MS_REMOUNT
+#define MS_REMOUNT      32
+#endif
+
+#ifndef MS_BIND
+#define MS_BIND 4096
+#endif
+
+#ifndef MS_MOVE
+#define MS_MOVE 8192
+#endif
+
+#ifndef MNT_FORCE
+#define MNT_FORCE 0x1
+#endif
+
+#ifndef MNT_DETACH
+#define MNT_DETACH 0x2
+#endif
+
+extern dev_t name_to_dev_t(char *name);
+extern int display_uuid_cache(void);
+
+#define MAX(a, b) ((a) > (b) ? a : b)
+
+int testing = 0, quiet = 0, reallyquiet = 0;
+
+#define PATH "/usr/bin:/bin:/sbin:/usr/sbin"
+
+char * env[] = {
+    "PATH=" PATH,
+    "LVM_SUPPRESS_FD_WARNINGS=1",
+    NULL
+};
+
+int smartmknod(char * device, mode_t mode, dev_t dev) {
+    char buf[256];
+    char * end;
+
+    strncpy(buf, device, 256);
+
+    end = buf;
+    while (*end) {
+       if (*end == '/') {
+           *end = '\0';
+           if (access(buf, F_OK) && errno == ENOENT) 
+               mkdir(buf, 0755);
+           *end = '/';
+       }
+
+       end++;
+    }
+
+    return mknod(device, mode, dev);
+}
+
+char * getArg(char * cmd, char * end, char ** arg) {
+    char quote = '\0';
+
+    if (!cmd || cmd >= end) return NULL;
+
+    while (isspace(*cmd) && cmd < end) cmd++;
+    if (cmd >= end) return NULL;
+
+    if (*cmd == '"')
+       cmd++, quote = '"';
+    else if (*cmd == '\'')
+       cmd++, quote = '\'';
+
+    if (quote) {
+       *arg = cmd;
+
+       /* This doesn't support \ escapes */
+       while (cmd < end && *cmd != quote) cmd++;
+
+       if (cmd == end) {
+           printf("error: quote mismatch for %s\n", *arg);
+           return NULL;
+       }
+
+       *cmd = '\0';
+       cmd++;
+    } else {
+       *arg = cmd;
+       while (!isspace(*cmd) && cmd < end) cmd++;
+       *cmd = '\0';
+       if (**arg == '$')
+            *arg = getenv(*arg+1);
+        if (*arg == NULL)
+            *arg = "";
+    }
+
+    cmd++;
+
+    while (isspace(*cmd)) cmd++;
+
+    return cmd;
+}
+
+/* taken from anaconda/isys/probe.c */
+static int readFD (int fd, char **buf)
+{
+    char *p;
+    size_t size = 4096;
+    int s, filesize;
+
+    *buf = malloc (size);
+    if (*buf == 0)
+      return -1;
+
+    filesize = 0;
+    do {
+       p = &(*buf) [filesize];
+       s = read (fd, p, 4096);
+       if (s < 0)
+           break;
+       filesize += s;
+       if (s != 4096)
+           break;
+       size += 4096;
+       *buf = realloc (*buf, size);
+    } while (1);
+
+    if (filesize == 0 && s < 0) {
+       free (*buf);     
+       *buf = NULL;
+       return -1;
+    }
+
+    return filesize;
+}
+
+#ifdef __powerpc__
+#define CMDLINESIZE 256
+#else
+#define CMDLINESIZE 1024
+#endif
+
+/* get the contents of the kernel command line from /proc/cmdline */
+static char * getKernelCmdLine(void) {
+    int fd, i;
+    char * buf;
+
+    fd = open("/proc/cmdline", O_RDONLY, 0);
+    if (fd < 0) {
+       printf("getKernelCmdLine: failed to open /proc/cmdline: %d\n", errno);
+       return NULL;
+    }
+
+    buf = malloc(CMDLINESIZE);
+    if (!buf)
+        return buf;
+
+    i = read(fd, buf, CMDLINESIZE);
+    if (i < 0) {
+       printf("getKernelCmdLine: failed to read /proc/cmdline: %d\n", errno);
+       close(fd);
+       return NULL;
+    }
+
+    close(fd);
+    if (i == 0)
+        buf[0] = '\0';
+    else
+        buf[i - 1] = '\0';
+    return buf;
+}
+
+/* get the start of a kernel arg "arg".  returns everything after it
+ * (useful for things like getting the args to init=).  so if you only
+ * want one arg, you need to terminate it at the n */
+static char * getKernelArg(char * arg) {
+    char * start, * cmdline;
+
+    cmdline = start = getKernelCmdLine();
+    if (start == NULL) return NULL;
+    while (*start) {
+       if (isspace(*start)) {
+           start++;
+           continue;
+       }
+       if (strncmp(start, arg, strlen(arg)) == 0) {
+            return start + strlen(arg);
+        }
+       while (*++start && !isspace(*start))
+           ;
+    }
+
+    return NULL;
+}
+
+int mountCommand(char * cmd, char * end) {
+    char * fsType = NULL;
+    char * device;
+    char * mntPoint;
+    char * deviceDir = NULL;
+    char * options = NULL;
+    int mustRemove = 0;
+    int mustRemoveDir = 0;
+    int rc = 0;
+    int flags = MS_MGC_VAL;
+    char * newOpts;
+
+    cmd = getArg(cmd, end, &device);
+    if (!cmd) {
+       printf("usage: mount [--ro] [-o <opts>] -t <type> <device> <mntpoint>\n");
+       return 1;
+    }
+
+    while (cmd && *device == '-') {
+       if (!strcmp(device, "--ro")) {
+           flags |= MS_RDONLY;
+        } else if (!strcmp(device, "--bind")) {
+            flags = MS_BIND;
+            fsType = "none";
+       } else if (!strcmp(device, "-o")) {
+           cmd = getArg(cmd, end, &options);
+           if (!cmd) {
+               printf("mount: -o requires arguments\n");
+               return 1;
+           }
+       } else if (!strcmp(device, "-t")) {
+           if (!(cmd = getArg(cmd, end, &fsType))) {
+               printf("mount: missing filesystem type\n");
+               return 1;
+           }
+       }
+
+       cmd = getArg(cmd, end, &device);
+    }
+
+    if (!cmd) {
+       printf("mount: missing device\n");
+       return 1;
+    }
+
+    if (!(cmd = getArg(cmd, end, &mntPoint))) {
+       printf("mount: missing mount point\n");
+       return 1;
+    }
+
+    if (!fsType) {
+       printf("mount: filesystem type expected\n");
+       return 1;
+    }
+
+    if (cmd < end) {
+       printf("mount: unexpected arguments\n");
+       return 1;
+    }
+
+    /* need to deal with options */ 
+    if (options) {
+       char * end;
+       char * start = options;
+
+       newOpts = alloca(strlen(options) + 1);
+       *newOpts = '\0';
+
+       while (*start) {
+           end = strchr(start, ',');
+           if (!end) {
+               end = start + strlen(start);
+           } else {
+               *end = '\0';
+               end++;
+           }
+
+           if (!strcmp(start, "ro"))
+               flags |= MS_RDONLY;
+           else if (!strcmp(start, "rw"))
+               flags &= ~MS_RDONLY;
+           else if (!strcmp(start, "nosuid"))
+               flags |= MS_NOSUID;
+           else if (!strcmp(start, "suid"))
+               flags &= ~MS_NOSUID;
+           else if (!strcmp(start, "nodev"))
+               flags |= MS_NODEV;
+           else if (!strcmp(start, "dev"))
+               flags &= ~MS_NODEV;
+           else if (!strcmp(start, "noexec"))
+               flags |= MS_NOEXEC;
+           else if (!strcmp(start, "exec"))
+               flags &= ~MS_NOEXEC;
+           else if (!strcmp(start, "sync"))
+               flags |= MS_SYNCHRONOUS;
+           else if (!strcmp(start, "async"))
+               flags &= ~MS_SYNCHRONOUS;
+           else if (!strcmp(start, "nodiratime"))
+               flags |= MS_NODIRATIME;
+           else if (!strcmp(start, "diratime"))
+               flags &= ~MS_NODIRATIME;
+           else if (!strcmp(start, "noatime"))
+               flags |= MS_NOATIME;
+           else if (!strcmp(start, "atime"))
+               flags &= ~MS_NOATIME;
+           else if (!strcmp(start, "remount"))
+               flags |= MS_REMOUNT;
+           else if (!strcmp(start, "defaults"))
+               ;
+           else {
+               if (*newOpts)
+                   strcat(newOpts, ",");
+               strcat(newOpts, start);
+           }
+
+           start = end;
+       }
+
+       options = newOpts;
+    }
+
+    if (!strncmp("LABEL=", device, 6)) {
+       int major, minor;
+       char * devName;
+       char * ptr;
+       int i;
+
+       devName = get_spec_by_volume_label(device + 6, &major, &minor);
+
+       if (devName) {
+           device = devName;
+           if (access(device, F_OK)) {
+               ptr = device;
+               i = 0;
+               while (*ptr)
+                   if (*ptr++ == '/')
+                       i++;
+               if (i > 2) {
+                   deviceDir = alloca(strlen(device) + 1);
+                   strcpy(deviceDir, device);
+                   ptr = deviceDir + (strlen(device) - 1);
+                   while (*ptr != '/')
+                       *ptr-- = '\0';
+                   if (mkdir(deviceDir, 0644)) {
+                     printf("mkdir: cannot create directory %s\n", deviceDir);
+                   } else {
+                     mustRemoveDir = 1;
+                   }
+               }
+               if (smartmknod(device, S_IFBLK | 0600, makedev(major, minor))) {
+                   printf("mount: cannot create device %s (%d,%d)\n",
+                          device, major, minor);
+                   return 1;
+               }
+               mustRemove = 1;
+           }
+       }
+    }
+
+    if (testing) {
+       printf("mount %s%s%s-t '%s' '%s' '%s' (%s%s%s%s%s%s%s)\n", 
+               options ? "-o '" : "",  
+               options ? options : "", 
+               options ? "\' " : "",   
+               fsType, device, mntPoint,
+               (flags & MS_RDONLY) ? "ro " : "",
+               (flags & MS_NOSUID) ? "nosuid " : "",
+               (flags & MS_NODEV) ? "nodev " : "",
+               (flags & MS_NOEXEC) ? "noexec " : "",
+               (flags & MS_SYNCHRONOUS) ? "sync " : "",
+               (flags & MS_REMOUNT) ? "remount " : "",
+               (flags & MS_NOATIME) ? "noatime " : ""
+           );
+    } else {
+       if (mount(device, mntPoint, fsType, flags, options)) {
+           printf("mount: error %d mounting %s\n", errno, fsType);
+           rc = 1;
+       }
+    }
+
+    if (mustRemove) unlink(device);
+    if (mustRemoveDir) rmdir(deviceDir);
+
+    return rc;
+}
+
+int otherCommand(char * bin, char * cmd, char * end, int doFork) {
+    char ** args;
+    char ** nextArg;
+    int pid, wpid;
+    int status;
+    char fullPath[255];
+    static const char * sysPath = PATH;
+    const char * pathStart;
+    const char * pathEnd;
+    char * stdoutFile = NULL;
+    int stdoutFd = 0;
+
+    args = (char **)malloc(sizeof(char *) * 128);
+    if (!args)
+        return 1;
+    nextArg = args;
+
+    if (!strchr(bin, '/')) {
+       pathStart = sysPath;
+       while (*pathStart) {
+           pathEnd = strchr(pathStart, ':');
+
+           if (!pathEnd) pathEnd = pathStart + strlen(pathStart);
+
+           strncpy(fullPath, pathStart, pathEnd - pathStart);
+           fullPath[pathEnd - pathStart] = '/';
+           strcpy(fullPath + (pathEnd - pathStart + 1), bin); 
+
+           pathStart = pathEnd;
+           if (*pathStart) pathStart++;
+
+           if (!access(fullPath, X_OK)) {
+               bin = fullPath;
+               break;
+           }
+       }
+    }
+
+    *nextArg = strdup(bin);
+
+    while (cmd && cmd < end) {
+       nextArg++;
+       cmd = getArg(cmd, end, nextArg);
+    }
+       
+    if (cmd) nextArg++;
+    *nextArg = NULL;
+
+    /* if the next-to-last arg is a >, redirect the output properly */
+    if (((nextArg - args) >= 2) && !strcmp(*(nextArg - 2), ">")) {
+       stdoutFile = *(nextArg - 1);
+       *(nextArg - 2) = NULL;
+
+       stdoutFd = open(stdoutFile, O_CREAT | O_RDWR | O_TRUNC, 0600);
+       if (stdoutFd < 0) {
+           printf("nash: failed to open %s: %d\n", stdoutFile, errno);
+           return 1;
+       }
+    }
+
+    if (testing) {
+       printf("%s ", bin);
+       nextArg = args + 1;
+       while (*nextArg)
+           printf(" '%s'", *nextArg++);
+       if (stdoutFile)
+           printf(" (> %s)", stdoutFile);
+       printf("\n");
+    } else {
+       if (!doFork || !(pid = fork())) {
+           /* child */
+           dup2(stdoutFd, 1);
+           execve(args[0], args, env);
+           printf("ERROR: failed in exec of %s\n", args[0]);
+           return 1;
+       }
+
+       close(stdoutFd);
+
+       for (;;) {
+            wpid = wait4(-1, &status, 0, NULL);
+            if (wpid == -1) {
+                 printf("ERROR: Failed to wait for process %d\n", wpid);
+            }
+
+            if (wpid != pid)
+                 continue;
+
+            if (!WIFEXITED(status) || WEXITSTATUS(status)) {
+                 printf("ERROR: %s exited abnormally with value %d ! (pid %d)\n", args[0], WEXITSTATUS(status), pid);
+                 return 1;
+            }
+            break;
+       }
+    }
+
+    return 0;
+}
+
+#ifdef DEBUG
+static int lsdir(char *thedir, char * prefix) {
+    DIR * dir;
+    struct dirent * entry;
+    struct stat sb;
+    char * fn;
+
+    if (!(dir = opendir(thedir))) {
+        printf("error opening %s: %d\n", thedir, errno);
+        return 1;
+    }
+
+    fn = malloc(1024);
+    while ((entry = readdir(dir))) {
+        if (entry->d_name[0] == '.')
+            continue;
+        snprintf(fn, 1024, "%s/%s", thedir, entry->d_name);
+        stat(fn, &sb);
+        printf("%s%s", prefix, fn);
+
+        if (S_ISDIR(sb.st_mode)) {
+            char * pfx;
+            pfx = malloc(strlen(prefix) + 3);
+            sprintf(pfx, "%s  ", prefix);
+            printf("/\n");
+        } else if (S_ISCHR(sb.st_mode)) {
+            printf(" c %d %d\n", major(sb.st_rdev), minor(sb.st_rdev));
+        } else if (S_ISBLK(sb.st_mode)) {
+            printf(" b %d %d\n", major(sb.st_rdev), minor(sb.st_rdev));
+        } else if (S_ISLNK(sb.st_mode)) {
+            char * target;
+            target = malloc(1024);
+            readlink(fn, target, 1024);
+            printf("->%s\n", target);
+            free(target);
+        } else {
+            printf("\n");
+        }
+    }    
+    return 0;
+}
+
+int catCommand(char * cmd, char * end) {
+    char * file;
+    char * buf;
+    int fd;
+
+    if (!(cmd = getArg(cmd, end, &file))) {
+       printf("cat: argument expected\n");
+       return 1;
+    }
+
+    if ((fd = open(file, O_RDONLY)) < 0) {
+        printf("cat: error opening %s: %d\n", file, errno);
+        return 1;
+    }
+
+    buf = malloc(1024);
+    while (read(fd, buf, 1024) > 0) {
+        write(1, buf, 1024);
+    }
+    return 0;
+}
+
+int lsCommand(char * cmd, char * end) {
+    char * dir;
+
+    if (!(cmd = getArg(cmd, end, &dir))) {
+       printf("ls: argument expected\n");
+       return 1;
+    }
+
+    lsdir(dir, "");
+    return 0;
+}
+#endif
+
+int execCommand(char * cmd, char * end) {
+    char * bin;
+
+    if (!(cmd = getArg(cmd, end, &bin))) {
+       printf("exec: argument expected\n");
+       return 1;
+    }
+
+    return otherCommand(bin, cmd, end, 0);
+}
+
+int losetupCommand(char * cmd, char * end) {
+    char * device;
+    char * file;
+    int fd;
+    struct loop_info loopInfo;
+    int dev;
+
+    if (!(cmd = getArg(cmd, end, &device))) {
+       printf("losetup: missing device\n");
+       return 1;
+    }
+
+    if (!(cmd = getArg(cmd, end, &file))) {
+       printf("losetup: missing file\n");
+       return 1;
+    }
+
+    if (cmd < end) {
+       printf("losetup: unexpected arguments\n");
+       return 1;
+    }
+
+    if (testing) {
+       printf("losetup '%s' '%s'\n", device, file);
+    } else {
+       dev = open(device, O_RDWR, 0);
+       if (dev < 0) {
+           printf("losetup: failed to open %s: %d\n", device, errno);
+           return 1;
+       }
+
+       fd = open(file, O_RDWR, 0);
+       if (fd < 0) {
+           printf("losetup: failed to open %s: %d\n", file, errno);
+           close(dev);
+           return 1;
+       }
+
+       if (ioctl(dev, LOOP_SET_FD, (long) fd)) {
+           printf("losetup: LOOP_SET_FD failed: %d\n", errno);
+           close(dev);
+           close(fd);
+           return 1;
+       }
+
+       close(fd);
+
+       memset(&loopInfo, 0, sizeof(loopInfo));
+       strcpy(loopInfo.lo_name, file);
+
+       if (ioctl(dev, LOOP_SET_STATUS, &loopInfo)) 
+           printf("losetup: LOOP_SET_STATUS failed: %d\n", errno);
+
+       close(dev);
+    }
+
+    return 0;
+}
+
+#define RAID_MAJOR 9
+int raidautorunCommand(char * cmd, char * end) {
+    char * device;
+    int fd;
+
+    if (!(cmd = getArg(cmd, end, &device))) {
+       printf("raidautorun: raid device expected as first argument\n");
+       return 1;
+    }
+
+    if (cmd < end) {
+       printf("raidautorun: unexpected arguments\n");
+       return 1;
+    }
+
+    /* with udev, the raid devices don't exist until they get started.
+     * this won't work so well with raidautorun.  so, let's be smart
+     * and create them ourselves if we need to */
+    if (access(device, R_OK & W_OK)) {
+        int minor;
+        if (sscanf(device, "/dev/md%d", &minor) != 1) {
+            printf("raidautorun: unable to autocreate %s\n", device);
+            return 1;
+        }
+
+        if (smartmknod(device, S_IFBLK | 0600, makedev(RAID_MAJOR, minor))) {
+            printf("raidautorun: unable to autocreate %s\n", device);
+            return 1;
+        }
+    }
+
+    fd = open(device, O_RDWR, 0);
+    if (fd < 0) {
+       printf("raidautorun: failed to open %s: %d\n", device, errno);
+       return 1;
+    }
+
+    if (ioctl(fd, RAID_AUTORUN, 0)) {
+       printf("raidautorun: RAID_AUTORUN failed: %d\n", errno);
+       close(fd);
+       return 1;
+    }
+
+    close(fd);
+    return 0;
+}
+
+#ifdef USE_DIET
+extern int pivot_root(char *, char *);
+#endif
+
+static int my_pivot_root(char * one, char * two) {
+#ifdef USE_DIET
+    return pivot_root(one, two);
+#else
+    return syscall(__NR_pivot_root, one, two);
+#endif
+}
+
+int pivotrootCommand(char * cmd, char * end) {
+    char * new;
+    char * old;
+
+    if (!(cmd = getArg(cmd, end, &new))) {
+       printf("pivotroot: new root mount point expected\n");
+       return 1;
+    }
+
+    if (!(cmd = getArg(cmd, end, &old))) {
+       printf("pivotroot: old root mount point expected\n");
+       return 1;
+    }
+
+    if (cmd < end) {
+       printf("pivotroot: unexpected arguments\n");
+       return 1;
+    }
+
+    if (my_pivot_root(new, old)) {
+       printf("pivotroot: pivot_root(%s,%s) failed: %d\n", new, old, errno);
+       return 1;
+    }
+
+    return 0;
+}
+
+#define MAX_INIT_ARGS 32
+/* 2.6 magic not-pivot-root but kind of similar stuff.
+ * This is based on code from klibc/utils/run_init.c
+ */
+int switchrootCommand(char * cmd, char * end) {
+    char * new;
+    const char * initprogs[] = { "/sbin/init", "/etc/init", 
+                                 "/bin/init", "/bin/sh", NULL };
+    char * init, * cmdline = NULL;
+    char ** initargs;
+    /*  Don't try to unmount the old "/", there's no way to do it. */
+    const char * umounts[] = { "/dev", "/proc", "/sys", NULL };
+    int fd, i = 0;
+    int moveDev = 0;
+
+    cmd = getArg(cmd, end, &new);
+    if (cmd) {
+        if (!strcmp(new, "--movedev"))
+            moveDev = 1;
+        cmd = getArg(cmd, end, &new);
+    }
+
+    if (!cmd) {
+       printf("switchroot: new root mount point expected\n");
+       return 1;
+    }
+
+    if (chdir(new)) {
+        printf("switchroot: chdir(%s) failed: %d\n", new, errno);
+        return 1;
+    }
+
+    init = getKernelArg("init=");
+    if (init == NULL)
+        cmdline = getKernelCmdLine();
+
+    if (moveDev) {
+        i = 1;
+        mount("/dev", "./dev", NULL, MS_MOVE, NULL);
+    }
+
+    if ((fd = open("./dev/console", O_RDWR)) < 0) {
+        printf("ERROR opening /dev/console!!!!: %d\n", errno);
+        fd = 0;
+    }
+
+    if (dup2(fd, 0) != 0) printf("error dup2'ing fd of %d to 0\n", fd);
+    if (dup2(fd, 1) != 1) printf("error dup2'ing fd of %d to 1\n", fd);
+    if (dup2(fd, 2) != 2) printf("error dup2'ing fd of %d to 2\n", fd);
+    if (fd > 2)
+        close(fd);
+
+    fd = open("/", O_RDONLY);
+    for (; umounts[i] != NULL; i++) {
+        if (!quiet) printf("unmounting old %s\n", umounts[i]);
+        if (umount2(umounts[i], MNT_DETACH)) {
+            printf("ERROR unmounting old %s: %d\n", umounts[i], errno);
+            printf("forcing unmount of %s\n", umounts[i]);
+            umount2(umounts[i], MNT_FORCE);
+        }
+    }
+    i=0;
+
+    if (mount(".", "/", NULL, MS_MOVE, NULL)) {
+        printf("switchroot: mount failed: %d\n", errno);
+        close(fd);
+        return 1;
+    }
+
+    if (chroot(".") || chdir("/")) {
+        printf("switchroot: chroot() failed: %d\n", errno);
+        close(fd);
+        return 1;
+    }
+
+    /* release the old "/" */
+    close(fd);
+
+    if (init == NULL) {
+        int j;
+        for (j = 0; initprogs[j] != NULL; j++) {
+            if (!access(initprogs[j], X_OK)) {
+                init = strdup(initprogs[j]);
+                break;
+            }
+        }
+    }
+
+    initargs = (char **)malloc(sizeof(char *)*(MAX_INIT_ARGS+1));
+    if (cmdline && init) {
+        initargs[i++] = strdup(init);
+    } else {
+        cmdline = init;
+        initargs[0] = NULL;
+    }
+
+    if (cmdline != NULL) {
+        char * chptr, * start;
+
+        start = chptr = cmdline;
+        for (; (i < MAX_INIT_ARGS) && (*start != '\0'); i++) {
+            while (*chptr && !isspace(*chptr)) chptr++;
+            if (*chptr != '\0') *(chptr++) = '\0';
+            initargs[i] = strdup(start);
+            start = chptr;
+        }
+    }
+
+    initargs[i] = NULL;
+
+    if (access(initargs[0], X_OK)) {
+        printf("WARNING: can't access %s\n", initargs[0]);
+    }
+    execv(initargs[0], initargs);
+    printf("exec of init (%s) failed!!!: %d\n", initargs[0], errno);
+    return 1;
+}
+
+int isEchoQuiet(int fd) {
+    if (!reallyquiet) return 0;
+    if (fd != 1) return 0;
+    return 1;
+}
+
+int echoCommand(char * cmd, char * end) {
+    char * args[256];
+    char ** nextArg = args;
+    int outFd = 1;
+    int num = 0;
+    int i;
+    int newline = 1;
+    int length = 0;
+    char *string;
+
+    if (testing && !quiet) {
+       printf("(echo) ");
+       fflush(stdout);
+    }
+
+    while ((cmd = getArg(cmd, end, nextArg))) {
+        if (!strncmp("-n", *nextArg, MAX(2, strlen(*nextArg)))) {
+            newline = 0;
+        } else {
+            length += strlen(*nextArg);
+            nextArg++, num++;
+        }
+    }
+    length += num + 1;
+
+    if ((nextArg - args >= 2) && !strcmp(*(nextArg - 2), ">")) {
+       outFd = open(*(nextArg - 1), O_WRONLY | O_CREAT | O_TRUNC, 0644);
+       if (outFd < 0) {
+           printf("echo: cannot open %s for write: %d\n", 
+                   *(nextArg - 1), errno);
+           return 1;
+       }
+
+        newline = 0;
+       num -= 2;
+    }
+    string = (char *)malloc(length * sizeof(char));
+    *string = '\0';
+    for (i = 0; i < num;i ++) {
+       if (i) strcat(string, " ");
+        strncat(string, args[i], strlen(args[i]));
+    }
+
+    if (newline) strcat(string, "\n");
+    if (!isEchoQuiet(outFd)) write(outFd, string, strlen(string));
+
+    if (outFd != 1) close(outFd);
+    free(string);
+
+    return 0;
+}
+
+int umountCommand(char * cmd, char * end) {
+    char * path;
+
+    if (!(cmd = getArg(cmd, end, &path))) {
+       printf("umount: path expected\n");
+       return 1;
+    }
+
+    if (cmd < end) {
+       printf("umount: unexpected arguments\n");
+       return 1;
+    }
+
+    if (umount(path)) {
+       printf("umount %s failed: %d\n", path, errno);
+       return 1;
+    }
+
+    return 0;
+}
+
+int mkrootdevCommand(char * cmd, char * end) {
+    char * path;
+    char *root, * chptr;
+    int devNum = 0;
+    int fd;
+    int i;
+    char buf[1024];
+    int major, minor;
+
+    if (!(cmd = getArg(cmd, end, &path))) {
+       printf("mkrootdev: path expected\n");
+       return 1;
+    }
+
+    if (cmd < end) {
+       printf("mkrootdev: unexpected arguments\n");
+       return 1;
+    }
+
+    root = getKernelArg("root=");
+
+    if (root) {
+       chptr = root;
+       while (*chptr && !isspace(*chptr)) chptr++;
+       *chptr = '\0';
+    }
+
+    if (root && !access(root, R_OK)) {
+        if (!symlink(root, "/dev/root"))
+            return 0;
+    }
+
+    if (root && !strncmp(root, "LABEL=", 6)) {
+       if (get_spec_by_volume_label(root + 6, &major, &minor)) {
+           if (smartmknod(path, S_IFBLK | 0600, makedev(major, minor))) {
+               printf("mount: cannot create device %s (%d,%d)\n",
+                      path, major, minor);
+               return 1;
+           }
+
+           return 0;
+       }
+
+       printf("mkrootdev: label %s not found\n", root + 6);
+
+       return 1;
+    }
+
+    if (root && !strncmp(root, "UUID=", 5)) {
+        if (get_spec_by_uuid(root+5, &major, &minor)) {
+            if (smartmknod(path, S_IFBLK | 0600, makedev(major, minor))) {
+                printf("mount: cannot create device %s (%d,%d)\n",
+                       path, major, minor);
+                return 1;
+            }
+
+            return 0;
+        }
+
+        printf("mkrootdev: UUID %s not found\n", root+5);
+
+        return 1;
+    }
+
+    fd = open("/proc/sys/kernel/real-root-dev", O_RDONLY, 0);
+    if (fd < 0) {
+       printf("mkrootdev: failed to open /proc/sys/kernel/real-root-dev: %d\n", errno);
+       return 1;
+    }
+
+    i = read(fd, buf, sizeof(buf));
+    if (i < 0) {
+       printf("mkrootdev: failed to read real-root-dev: %d\n", errno);
+       close(fd);
+       return 1;
+    }
+
+    close(fd);
+    if (i == 0)
+        buf[i] = '\0';
+    else
+        buf[i - 1] = '\0';
+
+    devNum = atoi(buf);
+    if (devNum < 0) {
+       printf("mkrootdev: bad device %s\n", buf);
+       return 1;
+    }
+
+    if (!devNum && root)
+       devNum = name_to_dev_t(root);
+
+    if (smartmknod(path, S_IFBLK | 0700, devNum)) {
+       printf("mkrootdev: mknod failed: %d\n", errno);
+       return 1;
+    }
+
+    return 0;
+}
+
+int mkdirCommand(char * cmd, char * end) {
+    char * dir;
+    int ignoreExists = 0;
+
+    cmd = getArg(cmd, end, &dir);
+
+    if (cmd && !strcmp(dir, "-p")) {
+       ignoreExists = 1;
+       cmd = getArg(cmd, end, &dir);
+    }
+
+    if (!cmd) {
+       printf("mkdir: directory expected\n");
+       return 1;
+    }
+
+    if (mkdir(dir, 0755)) {
+       if (!ignoreExists && errno == EEXIST) {
+           printf("mkdir: failed to create %s: %d\n", dir, errno);
+           return 1;
+       }
+    }
+
+    return 0;
+}
+
+int accessCommand(char * cmd, char * end) {
+    char * permStr;
+    int perms = 0;
+    char * file = NULL;
+
+    cmd = getArg(cmd, end, &permStr);
+    if (cmd) cmd = getArg(cmd, end, &file);
+
+    if (!cmd || *permStr != '-') {
+       printf("usage: access -[perm] file\n");
+       return 1;
+    }
+
+    permStr++;
+    while (*permStr) {
+       switch (*permStr) {
+         case 'r': perms |= R_OK; break;
+         case 'w': perms |= W_OK; break;
+         case 'x': perms |= X_OK; break;
+         case 'f': perms |= F_OK; break;
+         default:
+           printf("perms must be -[r][w][x][f]\n");
+           return 1;
+       }
+
+       permStr++;
+    }
+
+    if ((file == NULL) || (access(file, perms)))
+       return 1;
+
+    return 0;
+}
+
+int sleepCommand(char * cmd, char * end) {
+    char *delaystr;
+    int delay;
+
+    if (!(cmd = getArg(cmd, end, &delaystr))) {
+       printf("sleep: delay expected\n");
+       return 1;
+    }
+
+    delay = atoi(delaystr);
+    sleep(delay);
+
+    return 0;
+}
+
+int readlinkCommand(char * cmd, char * end) {
+    char * path;
+    char * buf, * respath, * fullpath;
+    struct stat sb;
+    int rc = 0;
+
+    if (!(cmd = getArg(cmd, end, &path))) {
+        printf("readlink: file expected\n");
+        return 1;
+    }
+
+    if (lstat(path, &sb) == -1) {
+        fprintf(stderr, "unable to stat %s: %d\n", path, errno);
+        return 1;
+    }
+
+    if (!S_ISLNK(sb.st_mode)) {
+        printf("%s\n", path);
+        return 0;
+    }
+    
+    buf = malloc(512);
+    if (readlink(path, buf, 512) == -1) {
+       fprintf(stderr, "error readlink %s: %d\n", path, errno);
+        free(buf);
+       return 1;
+    }
+
+    /* symlink is absolute */
+    if (buf[0] == '/') {
+        printf("%s\n", buf);
+        free(buf);
+        return 0;
+    } 
+   
+    /* nope, need to handle the relative symlink case too */
+    respath = strrchr(path, '/');
+    if (respath) {
+        *respath = '\0';
+    }
+
+    fullpath = malloc(512);
+    /* and normalize it */
+    snprintf(fullpath, 512, "%s/%s", path, buf);
+    respath = malloc(PATH_MAX);
+    if (!(respath = realpath(fullpath, respath))) {
+        fprintf(stderr, "error realpath %s: %d\n", fullpath, errno);
+        rc = 1;
+        goto readlinkout;
+    }
+
+    printf("%s\n", respath);
+ readlinkout:
+    free(buf);
+    free(respath);
+    free(fullpath);
+    return rc;
+}
+
+int doFind(char * dirName, char * name) {
+    struct stat sb;
+    DIR * dir;
+    struct dirent * d;
+    char * strBuf = alloca(strlen(dirName) + 1024);
+
+    if (!(dir = opendir(dirName))) {
+       fprintf(stderr, "error opening %s: %d\n", dirName, errno);
+       return 0;
+    }
+
+    errno = 0;
+    while ((d = readdir(dir))) {
+       errno = 0;
+
+       strcpy(strBuf, dirName);
+       strcat(strBuf, "/");
+       strcat(strBuf, d->d_name);
+
+       if (!strcmp(d->d_name, name))
+           printf("%s\n", strBuf);
+
+       if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) {
+           errno = 0;
+           continue;
+       }
+
+       if (lstat(strBuf, &sb)) {
+           fprintf(stderr, "failed to stat %s: %d\n", strBuf, errno);
+           errno = 0;
+           continue;
+       }
+
+       if (S_ISDIR(sb.st_mode))
+           doFind(strBuf, name);
+    }
+
+    if (errno) {
+       closedir(dir);
+       printf("error reading from %s: %d\n", dirName, errno);
+       return 1;
+    }
+
+    closedir(dir);
+
+    return 0;
+}
+
+int findCommand(char * cmd, char * end) {
+    char * dir;
+    char * name;
+
+    cmd = getArg(cmd, end, &dir);
+    if (cmd) cmd = getArg(cmd, end, &name);
+    if (cmd && strcmp(name, "-name")) {
+       printf("usage: find [path] -name [file]\n");
+       return 1;
+    }
+
+    if (cmd) cmd = getArg(cmd, end, &name);
+    if (!cmd) {
+       printf("usage: find [path] -name [file]\n");
+       return 1;
+    }
+
+    return doFind(dir, name);
+}
+
+int findlodevCommand(char * cmd, char * end) {
+    char devName[20];
+    int devNum;
+    int fd;
+    struct loop_info loopInfo;
+    char separator[2] = "";
+
+    if (*end != '\n') {
+       printf("usage: findlodev\n");
+       return 1;
+    }
+
+    if (!access("/dev/.devfsd", X_OK))
+       strcpy(separator, "/");
+
+    for (devNum = 0; devNum < 256; devNum++) {
+       sprintf(devName, "/dev/loop%s%d", separator, devNum);
+       if ((fd = open(devName, O_RDONLY)) < 0) return 0;
+
+       if (ioctl(fd, LOOP_GET_STATUS, &loopInfo)) {
+           close(fd);
+           printf("%s\n", devName);
+           return 0;
+       }
+
+       close(fd);
+    }
+
+    return 0;
+}
+
+int mknodCommand(char * cmd, char * end) {
+    char * path, * type;
+    char * majorStr, * minorStr;
+    int major;
+    int minor;
+    char * chptr;
+    mode_t mode;
+
+    cmd = getArg(cmd, end, &path);
+    cmd = getArg(cmd, end, &type);
+    cmd = getArg(cmd, end, &majorStr);
+    cmd = getArg(cmd, end, &minorStr);
+    if (!minorStr) {
+       printf("mknod: usage mknod <path> [c|b] <major> <minor>\n");
+       return 1;
+    }
+
+    if (!strcmp(type, "b")) {
+       mode = S_IFBLK;
+    } else if (!strcmp(type, "c")) {
+       mode = S_IFCHR;
+    } else {
+       printf("mknod: invalid type\n");
+       return 1;
+    }
+
+    major = strtol(majorStr, &chptr, 10);
+    if (*chptr) {
+       printf("invalid major number\n");
+       return 1;
+    }
+
+    minor = strtol(minorStr, &chptr, 10);
+    if (*chptr) {
+       printf("invalid minor number\n");
+       return 1;
+    }
+
+    if (smartmknod(path, mode | 0600, makedev(major, minor))) {
+       printf("mknod: failed to create %s: %d\n", path, errno);
+       return 1;
+    }
+
+    return 0;
+}
+
+int mkdevicesCommand(char * cmd, char * end) {
+    int fd;
+    char *buf;
+    int i;
+    char * start, * chptr;
+    int major, minor;
+    char old;
+    char devName[128];
+    char * prefix;
+
+    if (!(cmd = getArg(cmd, end, &prefix))) {
+       printf("mkdevices: path expected\n");
+       return 1;
+    }
+
+    if (cmd < end) {
+       printf("mkdevices: unexpected arguments\n");
+       return 1;
+    }
+
+    if ((fd = open("/proc/partitions", O_RDONLY)) < 0) {
+       printf("mkrootdev: failed to open /proc/partitions: %d\n", errno);
+       return 1;
+    }
+
+    i = readFD(fd, &buf);
+    if (i < 1) {
+       close(fd);
+       printf("failed to read /proc/partitions: %d\n", errno);
+       return 1;
+    }
+    buf[i] = '\0';
+    close(fd);
+
+    start = strchr(buf, '\n');
+    if (start) {
+       start++;
+       start = strchr(buf, '\n');
+    }
+    if (!start) return 1;
+
+    start = start + 1;
+    while (*start) {
+       while (*start && isspace(*start)) start++;
+       major = strtol(start, &chptr, 10);
+
+       if (start != chptr) {
+           start = chptr;
+           while (*start && isspace(*start)) start++;
+           minor = strtol(start, &chptr, 10);
+
+           if (start != chptr) {
+               start = chptr;
+               while (*start && isspace(*start)) start++;
+               while (*start && !isspace(*start)) start++;
+               while (*start && isspace(*start)) start++;
+
+               if (*start) {
+
+                   chptr = start;
+                   while (!isspace(*chptr)) chptr++;
+                   old = *chptr;
+                   *chptr = '\0';
+
+                   if (testing) {
+                       printf("% 3d % 3d %s\n", major, minor, start);
+                   } else {
+                       char * ptr, * deviceDir;
+                       int i;
+
+                       sprintf(devName, "%s/%s", prefix, start);
+                       unlink(devName);
+
+                       ptr = devName;
+                       i = 0;
+                       while (*ptr)
+                           if (*ptr++ == '/')
+                               i++;
+                       if (i > 2) {
+                           deviceDir = alloca(strlen(devName) + 1);
+                           strcpy(deviceDir, devName);
+                           ptr = deviceDir + (strlen(devName) - 1);
+                           while (*ptr != '/')
+                               *ptr-- = '\0';
+                           if (access(deviceDir, X_OK) && mkdir(deviceDir, 0644)) {
+                               printf("mkdir: cannot create directory %s: %d\n", deviceDir, errno);
+                           }
+                       }
+                       if (smartmknod(devName, S_IFBLK | 0600, 
+                                 makedev(major, minor))) {
+                           printf("failed to create %s\n", devName);
+                       }
+                   }
+
+                   *chptr = old;
+                   start = chptr;
+               }
+
+           }
+       }
+
+       start = strchr(start, '\n');
+       if (!*start) return 1;
+       start = start + 1;
+    }
+
+    return 0;
+}
+
+static int getDevNumFromProc(char * file, char * device) {
+    char buf[32768], line[4096];
+    char * start, *end;
+    int num;
+    int fd;
+
+    if ((fd = open(file, O_RDONLY)) == -1) {
+        printf("can't open file %s: %d\n", file, errno);
+        return -1;
+    }
+
+    num = read(fd, buf, sizeof(buf));
+    if (num < 1) {
+        close(fd);
+        printf("failed to read %s: %d\n", file, errno);
+        return -1;
+    }
+    buf[num] = '\0';
+    close(fd);
+
+    start = buf;
+    end = strchr(start, '\n');
+    while (start && end) {
+        *end++ = '\0';
+        if ((sscanf(start, "%d %s", &num, line)) == 2) {
+            if (!strncmp(device, line, strlen(device)))
+                return num;
+        }
+        start = end;
+        end = strchr(start, '\n');
+    }
+    return -1;
+}
+
+int mkDMNodCommand(char * cmd, char * end) {
+    int major = getDevNumFromProc("/proc/devices", "misc");
+    int minor = getDevNumFromProc("/proc/misc", "device-mapper");
+
+    if ((major == -1) || (minor == -1)) {
+        printf("Unable to find device-mapper major/minor\n");
+        return 1;
+    }
+
+    if (!access("/dev/mapper/control", R_OK)) {
+        struct stat sb;
+        if (stat("/dev/mapper/control", &sb) == 0) {
+            if (S_ISCHR(sb.st_mode) && (sb.st_rdev == makedev(major, minor)))
+                return 0;
+        } 
+
+        unlink("/dev/mapper/control");
+    }
+
+    if (smartmknod("/dev/mapper/control", S_IFCHR | 0600, 
+                   makedev(major, minor))) {
+        printf("failed to create /dev/mapper/control\n");
+        return 1;
+    }
+    
+    return 0;
+}
+
+int setQuietCommand(char * cmd, char * end) {
+    int fd, rc;
+
+    if ((fd = open("/proc/cmdline", O_RDONLY)) >= 0) {
+        char * buf = malloc(512);
+        rc = read(fd, buf, 511);
+        if (strstr(buf, "quiet") != NULL)
+            reallyquiet = 1;
+        close(fd);
+        free(buf);
+    }
+
+    if (reallyquiet)
+          quiet = 1;
+
+    return 0;
+}
+
+int runStartup(int fd) {
+    char contents[32768];
+    int i;
+    char * start, * end;
+    char * chptr;
+    int rc;
+
+    i = read(fd, contents, sizeof(contents) - 1);
+    if (i == (sizeof(contents) - 1)) {
+       printf("Failed to read /startup.rc -- file too large.\n");
+       return 1;
+    }
+    close(fd);
+
+    contents[i] = '\0';
+
+    start = contents;
+    while (*start) {
+       while (isspace(*start) && *start && (*start != '\n')) start++;
+
+       if (*start == '#')
+           while (*start && (*start != '\n')) start++;
+
+       if (*start == '\n') {
+           start++;
+           continue;
+       }
+
+       if (!*start) {
+           printf("(last line in /startup.rc is empty)\n");
+           continue;
+       }
+
+       /* start points to the beginning of the command */
+       end = start + 1;
+       while (*end && (*end != '\n')) end++;
+       if (!*end) {
+           printf("(last line in /startup.rc missing \\n -- skipping)\n");
+           start = end;
+           continue;
+       }
+
+       /* end points to the \n at the end of the command */
+
+       chptr = start;
+       while (chptr < end && !isspace(*chptr)) chptr++;
+
+       if (!strncmp(start, "mount", MAX(5, chptr - start)))
+           rc = mountCommand(chptr, end);
+       else if (!strncmp(start, "losetup", MAX(7, chptr - start)))
+           rc = losetupCommand(chptr, end);
+       else if (!strncmp(start, "echo", MAX(4, chptr - start)))
+           rc = echoCommand(chptr, end);
+       else if (!strncmp(start, "raidautorun", MAX(11, chptr - start)))
+           rc = raidautorunCommand(chptr, end);
+       else if (!strncmp(start, "pivot_root", MAX(10, chptr - start)))
+           rc = pivotrootCommand(chptr, end);
+        else if (!strncmp(start, "switchroot", MAX(10, chptr - start)))
+            rc = switchrootCommand(chptr, end);
+       else if (!strncmp(start, "mkrootdev", MAX(9, chptr - start)))
+           rc = mkrootdevCommand(chptr, end);
+       else if (!strncmp(start, "umount", MAX(6, chptr - start)))
+           rc = umountCommand(chptr, end);
+       else if (!strncmp(start, "exec", MAX(4, chptr - start)))
+           rc = execCommand(chptr, end);
+       else if (!strncmp(start, "mkdir", MAX(5, chptr - start)))
+           rc = mkdirCommand(chptr, end);
+       else if (!strncmp(start, "access", MAX(6, chptr - start)))
+           rc = accessCommand(chptr, end);
+       else if (!strncmp(start, "find", MAX(4, chptr - start)))
+           rc = findCommand(chptr, end);
+       else if (!strncmp(start, "findlodev", MAX(7, chptr - start)))
+           rc = findlodevCommand(chptr, end);
+       else if (!strncmp(start, "showlabels", MAX(10, chptr-start)))
+           rc = display_uuid_cache();
+       else if (!strncmp(start, "mkdevices", MAX(9, chptr-start)))
+           rc = mkdevicesCommand(chptr, end);
+       else if (!strncmp(start, "sleep", MAX(5, chptr-start)))
+           rc = sleepCommand(chptr, end);
+       else if (!strncmp(start, "mknod", MAX(5, chptr-start)))
+           rc = mknodCommand(chptr, end);
+        else if (!strncmp(start, "mkdmnod", MAX(7, chptr-start)))
+            rc = mkDMNodCommand(chptr, end);
+        else if (!strncmp(start, "readlink", MAX(8, chptr-start)))
+            rc = readlinkCommand(chptr, end);
+        else if (!strncmp(start, "setquiet", MAX(8, chptr-start)))
+            rc = setQuietCommand(chptr, end);
+#ifdef DEBUG
+        else if (!strncmp(start, "cat", MAX(3, chptr-start)))
+            rc = catCommand(chptr, end);
+        else if (!strncmp(start, "ls", MAX(2, chptr-start)))
+            rc = lsCommand(chptr, end);
+#endif
+       else {
+           *chptr = '\0';
+           rc = otherCommand(start, chptr + 1, end, 1);
+       }
+
+       start = end + 1;
+    }
+
+    return rc;
+}
+
+int main(int argc, char **argv) {
+    int fd = 0;
+    char * name;
+    int rc;
+    int force = 0;
+
+    name = strrchr(argv[0], '/');
+    if (!name) 
+       name = argv[0];
+    else
+       name++;
+
+    if (!strcmp(name, "modprobe"))
+       exit(0);
+    if (!strcmp(name, "hotplug")) {
+        argv[0] = strdup("/sbin/udev");
+        execv(argv[0], argv);
+        printf("ERROR: exec of udev failed!\n");
+        exit(1);
+    }
+
+    testing = (getppid() != 0) && (getppid() != 1);
+    argv++, argc--;
+
+    while (argc && **argv == '-') {
+       if (!strcmp(*argv, "--force")) {
+           force = 1;
+           argv++, argc--;
+           testing = 0;
+       } else if (!strcmp(*argv, "--quiet")) {
+           quiet = 1;
+           argv++, argc--;
+        } else if (!strcmp(*argv, "--reallyquiet")) {
+            reallyquiet = 1;
+            argv++, argc--;
+       } else {
+           printf("unknown argument %s\n", *argv);
+           return 1;
+       }
+    }
+
+    if (force && !quiet)
+       printf("(forcing normal run)\n");
+
+    if (testing && !quiet)
+       printf("(running in test mode).\n");
+
+    if (!quiet) printf("Red Hat nash version %s starting\n", VERSION);
+
+    if (*argv) {
+       fd = open(*argv, O_RDONLY, 0);
+       if (fd < 0) {
+           printf("nash: cannot open %s: %d\n", *argv, errno);
+           exit(1);
+       }
+    }
+
+    /* runStartup closes fd */
+    rc = runStartup(fd);
+
+    return rc;
+}