2004-01-20 21:32:43 +03:00
/*
* Guillaume Cottenceau ( gc @ mandrakesoft . com )
*
* Copyright 2000 MandrakeSoft
*
* View the homepage : http : //us.mandrakesoft.com/~gc/html/stage1.html
*
*
* 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 0213 9 , USA .
*
*/
/*
* Portions from Erik Troan ( ewt @ redhat . com )
*
* Copyright 1996 Red Hat Software
*
*/
# include <stdlib.h>
# include <unistd.h>
# include <sys/types.h>
# include <sys/stat.h>
# include <fcntl.h>
# include <stdio.h>
# include <sys/ioctl.h>
# include <sys/mount.h>
# include <string.h>
# include <errno.h>
# include <ctype.h>
# include <stdarg.h>
# include <signal.h>
# include "stage1.h"
# include "log.h"
# include "probing.h"
# include "frontend.h"
# include "modules.h"
# include "tools.h"
# include "automatic.h"
# include "mount.h"
# include "insmod.h"
# ifndef DISABLE_CDROM
# include "cdrom.h"
# endif
# ifndef DISABLE_NETWORK
# include "network.h"
# endif
# ifndef DISABLE_DISK
# include "disk.h"
# endif
2008-03-12 15:19:18 +03:00
extern char * env [ ] ;
2004-01-20 21:32:43 +03:00
/************************************************************
* globals */
2004-11-22 16:47:29 +03:00
char version [ 128 ] = DISTRIB_NAME ;
2004-01-20 21:32:43 +03:00
char * method_name ;
void fatal_error ( char * msg )
{
printf ( " FATAL ERROR IN STAGE1: %s \n \n I can't recover from this. \n You may reboot your system. \n " , msg ) ;
while ( 1 ) ;
}
/************************************************************
* special frontend functs
* ( the principle is to not pollute frontend code with stage1 - specific stuff ) */
void stg1_error_message ( char * msg , . . . )
{
va_list args ;
va_start ( args , msg ) ;
log_message ( " unsetting automatic " ) ;
unset_param ( MODE_AUTOMATIC ) ;
verror_message ( msg , args ) ;
va_end ( args ) ;
}
void stg1_info_message ( char * msg , . . . )
{
va_list args ;
va_start ( args , msg ) ;
if ( IS_AUTOMATIC ) {
vlog_message ( msg , args ) ;
return ;
}
vinfo_message ( msg , args ) ;
va_end ( args ) ;
}
/************************************************************
* spawns a shell on console # 2 */
2004-12-01 18:10:51 +03:00
static pid_t shell_pid = 0 ;
2007-05-25 16:37:51 +04:00
static pid_t splash_pid = 0 ;
2004-12-01 18:10:51 +03:00
2004-01-20 21:32:43 +03:00
static void spawn_shell ( void )
{
# ifdef SPAWN_SHELL
int fd ;
2004-11-29 20:18:04 +03:00
char * shell_name [ ] = { " /bin/sh " , NULL } ;
2004-01-20 21:32:43 +03:00
log_message ( " spawning a shell " ) ;
if ( ! IS_TESTING ) {
fd = open ( " /dev/tty2 " , O_RDWR ) ;
if ( fd = = - 1 ) {
log_message ( " cannot open /dev/tty2 -- no shell will be provided " ) ;
return ;
}
else if ( access ( shell_name [ 0 ] , X_OK ) ) {
log_message ( " cannot open shell - %s doesn't exist " , shell_name [ 0 ] ) ;
return ;
}
2004-12-01 18:10:51 +03:00
if ( ! ( shell_pid = fork ( ) ) ) {
2004-01-20 21:32:43 +03:00
dup2 ( fd , 0 ) ;
dup2 ( fd , 1 ) ;
dup2 ( fd , 2 ) ;
close ( fd ) ;
setsid ( ) ;
if ( ioctl ( 0 , TIOCSCTTY , NULL ) )
log_perror ( " could not set new controlling tty " ) ;
2008-03-12 15:19:18 +03:00
execve ( shell_name [ 0 ] , shell_name , env ) ;
2004-01-20 21:32:43 +03:00
log_message ( " execve of %s failed: %s " , shell_name [ 0 ] , strerror ( errno ) ) ;
exit ( - 1 ) ;
}
close ( fd ) ;
}
# endif
}
2007-05-25 16:37:51 +04:00
static void spawn_splash ( void )
{
# ifdef SPAWN_SPLASH
int fd ;
char * splash_name [ ] = { " /sbin/splash " , NULL } ;
log_message ( " spawning a splash screen " ) ;
fd = open ( " /dev/null " , O_RDWR ) ;
if ( fd = = - 1 ) {
log_message ( " cannot open /dev/null " ) ;
return ;
}
else if ( access ( splash_name [ 0 ] , X_OK ) ) {
log_message ( " %s doesn't exist " , splash_name [ 0 ] ) ;
return ;
}
if ( ! ( splash_pid = fork ( ) ) ) {
dup2 ( fd , 0 ) ;
dup2 ( fd , 1 ) ;
dup2 ( fd , 2 ) ;
close ( fd ) ;
setsid ( ) ;
2008-03-12 15:19:18 +03:00
execve ( splash_name [ 0 ] , splash_name , env ) ;
2007-05-25 16:37:51 +04:00
log_message ( " execve of %s failed: %s " , splash_name [ 0 ] , strerror ( errno ) ) ;
exit ( - 1 ) ;
}
2008-03-12 15:19:18 +03:00
2007-05-25 16:37:51 +04:00
close ( fd ) ;
# endif
}
2004-01-20 21:32:43 +03:00
/************************************************************
*/
static void expert_third_party_modules ( void )
{
enum return_type results ;
char * floppy_mount_location = " /tmp/floppy " ;
char * * modules ;
char final_name [ 500 ] ;
char * choice ;
int rc ;
char * questions [ ] = { " Options " , NULL } ;
static char * * answers = NULL ;
results = ask_yes_no ( " If you want to insert third-party kernel modules, insert "
" a Linux (ext2fs) formatted floppy containing the modules and confirm. Otherwise, select \" no \" . " ) ; ;
if ( results ! = RETURN_OK )
return ;
2008-03-01 22:02:06 +03:00
my_insmod ( " floppy " , NULL ) ;
2004-01-20 21:32:43 +03:00
if ( my_mount ( " /dev/fd0 " , floppy_mount_location , " ext2 " , 0 ) = = - 1 ) {
stg1_error_message ( " I can't find a Linux ext2 floppy in first floppy drive. " ) ;
return expert_third_party_modules ( ) ;
}
modules = list_directory ( floppy_mount_location ) ;
if ( ! modules | | ! * modules ) {
stg1_error_message ( " No modules found on floppy disk. " ) ;
umount ( floppy_mount_location ) ;
return expert_third_party_modules ( ) ;
}
results = ask_from_list ( " Which driver would you like to insmod? " , modules , & choice ) ;
if ( results ! = RETURN_OK ) {
umount ( floppy_mount_location ) ;
return ;
}
sprintf ( final_name , " %s/%s " , floppy_mount_location , choice ) ;
results = ask_from_entries ( " Please enter the options: " , questions , & answers , 24 , NULL ) ;
if ( results ! = RETURN_OK ) {
umount ( floppy_mount_location ) ;
return expert_third_party_modules ( ) ;
}
rc = insmod_call ( final_name , answers [ 0 ] ) ;
umount ( floppy_mount_location ) ;
if ( rc ) {
log_message ( " \t failed " ) ;
stg1_error_message ( " Insmod failed. " ) ;
}
return expert_third_party_modules ( ) ;
}
/************************************************************
*/
static enum return_type method_select_and_prepare ( void )
{
enum return_type results ;
char * choice ;
char * means [ 10 ] , * means_auto [ 10 ] ;
int i ;
# ifndef DISABLE_DISK
char * disk_install = " Hard disk " ; char * disk_install_auto = " disk " ;
# endif
# ifndef DISABLE_CDROM
char * cdrom_install = " CDROM drive " ; char * cdrom_install_auto = " cdrom " ;
# endif
# ifndef DISABLE_NETWORK
char * network_nfs_install = " NFS server " ; char * network_nfs_install_auto = " nfs " ;
char * network_ftp_install = " FTP server " ; char * network_ftp_install_auto = " ftp " ;
char * network_http_install = " HTTP server " ; char * network_http_install_auto = " http " ;
# endif
i = 0 ;
# ifndef DISABLE_NETWORK
means [ i ] = network_nfs_install ; means_auto [ i + + ] = network_nfs_install_auto ;
means [ i ] = network_ftp_install ; means_auto [ i + + ] = network_ftp_install_auto ;
means [ i ] = network_http_install ; means_auto [ i + + ] = network_http_install_auto ;
# endif
# ifndef DISABLE_CDROM
means [ i ] = cdrom_install ; means_auto [ i + + ] = cdrom_install_auto ;
# endif
# ifndef DISABLE_DISK
means [ i ] = disk_install ; means_auto [ i + + ] = disk_install_auto ;
# endif
means [ i ] = NULL ;
2005-04-21 15:06:44 +04:00
update_splash ( ) ;
2004-01-20 21:32:43 +03:00
results = ask_from_list_auto ( " Please choose the installation method. " , means , & choice , " method " , means_auto ) ;
if ( results ! = RETURN_OK )
return method_select_and_prepare ( ) ;
results = RETURN_ERROR ;
# ifndef DISABLE_CDROM
if ( ! strcmp ( choice , cdrom_install ) )
results = cdrom_prepare ( ) ;
# endif
2004-11-25 00:44:32 +03:00
2004-01-20 21:32:43 +03:00
# ifndef DISABLE_DISK
if ( ! strcmp ( choice , disk_install ) )
results = disk_prepare ( ) ;
# endif
# ifndef DISABLE_NETWORK
if ( ! strcmp ( choice , network_nfs_install ) )
results = nfs_prepare ( ) ;
if ( ! strcmp ( choice , network_ftp_install ) )
results = ftp_prepare ( ) ;
if ( ! strcmp ( choice , network_http_install ) )
results = http_prepare ( ) ;
# endif
if ( results ! = RETURN_OK )
return method_select_and_prepare ( ) ;
return RETURN_OK ;
}
2004-11-22 16:47:29 +03:00
void getversion ( )
{
FILE * f ;
char * c ;
if ( ! ( f = fopen ( VERSION_FILE , " r " ) ) ) return ;
if ( fgets ( version , sizeof ( version ) , f ) ) {
c = strrchr ( version , ' \n ' ) ;
if ( c ) * c = 0 ;
}
fclose ( f ) ;
}
2004-01-20 21:32:43 +03:00
2008-03-12 15:19:18 +03:00
void stage1 ( )
2004-01-20 21:32:43 +03:00
{
enum return_type ret ;
2004-11-22 16:47:29 +03:00
char buf [ 128 ] ;
2004-11-29 19:53:16 +03:00
2005-05-14 14:23:09 +04:00
open_log ( ) ;
2004-11-22 16:47:29 +03:00
getversion ( ) ;
log_message ( " welcome to the %s install (alt-stage1, built " __DATE__ " " __TIME__ " ) " , version ) ;
2004-01-20 21:32:43 +03:00
process_cmdline ( ) ;
handle_env ( env ) ;
spawn_shell ( ) ;
2007-05-25 16:37:51 +04:00
spawn_splash ( ) ;
2005-04-21 15:06:44 +04:00
prepare_progress ( ) ;
update_splash ( ) ;
2007-08-08 20:03:36 +04:00
snprintf ( buf , sizeof ( buf ) , " Welcome to %s " , version ) ;
2004-11-22 16:47:29 +03:00
init_frontend ( buf ) ;
2005-04-21 15:06:44 +04:00
update_splash ( ) ;
2004-01-20 21:32:43 +03:00
if ( IS_RESCUE & & total_memory ( ) < MEM_LIMIT_RESCUE ) {
stg1_error_message ( " You are starting the rescue with a low memory configuration. "
" From that point, experience showed us that the program may stop "
" or crash at any point without immediate proper reason. Continue at "
" your own risk. Alternatively, you may reboot your system now. " ) ;
}
ret = method_select_and_prepare ( ) ;
finish_frontend ( ) ;
2005-04-21 15:06:44 +04:00
update_splash ( ) ;
2007-07-18 15:30:44 +04:00
close_log ( ) ;
2005-04-21 15:06:44 +04:00
close_progress ( ) ;
2004-01-20 21:32:43 +03:00
if ( ret ! = RETURN_OK )
fatal_error ( " could not select an installation method " ) ;
2004-12-01 18:10:51 +03:00
/* all went good */
if ( shell_pid ! = 0 )
kill ( shell_pid , 9 ) ;
2008-03-12 15:19:18 +03:00
2007-05-25 16:37:51 +04:00
if ( splash_pid ! = 0 )
kill ( splash_pid , 9 ) ;
2004-12-01 18:10:51 +03:00
2005-01-21 16:52:04 +03:00
pass_env ( 4 ) ;
2008-03-12 15:19:18 +03:00
exit ( 0 ) ;
2004-01-20 21:32:43 +03:00
}