//----------------------------------------------------------------------------- // Copyright © 2001 - Philip Howard - All rights reserved, released under GPL // // This program 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. // // This program 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 this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. //----------------------------------------------------------------------------- // package cdinit // version 0.8.0 // program cdinit3 (cd initializer stage 3) // // description // This program is the stage 3 initializer for the cdinit package. The // stage 2 program will have invoked this program in PID 1. // // action // 1. Unmount /cdrom // 2. Mount /dev/bootcd as /cdrom (same CD as just unmounted) // 3. For /opt and /usr: // 3.1. If /cdrom/${ARCH}/name exists, bind mount it as /name // 4. If /etc/ld.so.cache does not exist, run ldconfig // 5. For each program name in init list, try to execve() it // //----------------------------------------------------------------------------- // author Philip Howard // email phil@ipal.org //----------------------------------------------------------------------------- #include "cdinit.h" //----------------------------------------------------------------------------- // Define list of paths to try to execute. //----------------------------------------------------------------------------- static char * init_list [] = { "/sbin/init", "/etc/init", "/bin/init", "/bin/sh", NULL }; //----------------------------------------------------------------------------- // Define list of directories in / that should be mounted from the CDROM path // appropriate for this architecture. //----------------------------------------------------------------------------- static char * dirlink_list [] = { "opt", "usr", NULL }; static char cdrom_path [] = "/cdrom/" CDINIT_ARCH_NAME "/xxx"; #define CDROM_PATH_MOUNTPT (cdrom_path+sizeof(cdrom_path)-5) //----------------------------------------------------------------------------- // Define argument lists for execve(). //----------------------------------------------------------------------------- static char * ldconfig_command [] = { "/sbin/ldconfig", NULL }; //----------------------------------------------------------------------------- // Define an environment for execve(). //----------------------------------------------------------------------------- static char * environment [] = { "PATH=/sbin:/bin:/usr/sbin:/usr/bin", "HOME=/", "TERM=linux", NULL }; //----------------------------------------------------------------------------- // Where to store trace info. //----------------------------------------------------------------------------- #ifdef CDINIT_TRACE static const char * trace [4]; #endif //----------------------------------------------------------------------------- // Include functions. //----------------------------------------------------------------------------- #include "string_copy.c" #include "write_string.c" #ifdef CDINIT_TRACE #include "write_dec_slong.c" #endif //----------------------------------------------------------------------------- // Function setup does setup to be done only once. //----------------------------------------------------------------------------- static int main1 () { struct stat statbuf ; char * * ptr_ptr ; //------------------------------------------------------------------------- // Remount /cdrom from /dev/bootcd to get the correct name in /proc/mounts. //------------------------------------------------------------------------- trace2( "umount", "/cdrom" ); if ( umount( "/cdrom" ) != 0 ) return 2; trace4( "umount"+1, "/dev/bootcd", "/cdrom", "iso9660" ); if ( mount( "/dev/bootcd", "/cdrom", "iso9660", MS_MGC_VAL | MS_RDONLY, 0 ) != 0 ) return 4; //---------------------------------------------------------- // Mount certain CDROM directories onto directories in root. //---------------------------------------------------------- for ( ptr_ptr = dirlink_list; * ptr_ptr; ++ ptr_ptr ) { string_copy( CDROM_PATH_MOUNTPT+1, * ptr_ptr ); if ( stat( cdrom_path, & statbuf ) == 0 ) { #if 0 write_string( 1, "mount -o bind '" ); write_string( 1, cdrom_path ); write_string( 1, "' '" ); write_string( 1, CDROM_PATH_MOUNTPT ); write_string( 1, "'\n" ); #endif trace4( "umount"+1, cdrom_path, CDROM_PATH_MOUNTPT, "bind" ); if ( mount( cdrom_path, CDROM_PATH_MOUNTPT, "none", MS_BIND | MS_MGC_VAL, 0 ) != 0 ) return 4; } } //---------------------------------------------------- // Unmount /cdrom because it is no longer needed here. //---------------------------------------------------- trace2( "umount", "/cdrom" ); if ( umount( "/cdrom" ) != 0 ) return 2; #if 0 //---------------------------------------------- // If no /etc/ld.so.cache then run ldconfig now. // This probably should be done in the scripts. //---------------------------------------------- if ( stat( "/etc/ld.so.cache", & statbuf ) != 0 ) { int pid, status; trace2( "fork", ldconfig_command[0] ); if ( ( pid = fork() ) < 0 ) return 2; if ( pid == 0 ) { trace1( "execve" ); execve( ldconfig_command[0], ldconfig_command, environment ); return 2; } trace1( "waitpid" ); if ( waitpid( pid, & status, 0 ) < 0 ) return 2; } #endif //---------------------------------------------------------------------- // Search for the init program to run in the same order the kernel does. // Overload the command name space from ldconfig. //---------------------------------------------------------------------- ptr_ptr = init_list; while ( * ptr_ptr ) { ldconfig_command[0] = * ptr_ptr; execve( ldconfig_command[0], ldconfig_command, environment ); ++ ptr_ptr; } trace1( "find init program" ); return 1; } //----------------------------------------------------------------------------- // Function _start is really the main function. //----------------------------------------------------------------------------- void _start () { int rc ; errno = 0; #if 0 write_string( 1, "\r" #ifdef CDINIT_COLOR "\033[33;1m" #endif "cdinit v" CDINIT_VERSION ", " "Copyright (C) 2001, Philip Howard, All rights reserved, See GPL" #ifdef CDINIT_COLOR "\033[0m" #endif "\n" ); #endif rc = main1(); #ifdef CDINIT_TRACE if ( rc != 0 ) { int i; write_string( 1, "Error " ); write_dec_slong( 1, (signed long) ( errno ) ); write_string( 1, " doing:" ); for ( i = 0; i < rc; ++ i ) { write_string( 1, " " ); write_string( 1, trace[i] ); } write_string( 1, "\n" ); } #endif write_string( 1, "halting ... \n\n\n\n\n\n" ); reboot( LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_HALT, NULL ); for (;;); }