Files
bpfire/src/install+setup/install/main.c
2010-12-03 19:58:41 +01:00

618 lines
18 KiB
C

/* SmoothWall install program.
*
* This program is distributed under the terms of the GNU General Public
* Licence. See the file COPYING for details.
*
* (c) Lawrence Manning, 2001
* Contains main entry point, and misc functions.6
*
*/
#include "install.h"
#define _GNU_SOURCE
#define INST_FILECOUNT 8400
#define UNATTENDED_CONF "/cdrom/boot/unattended.conf"
#define EXT2 0
#define EXT3 1
#define EXT4 2
#define REISERFS 3
FILE *flog = NULL;
char *mylog;
char **ctr;
extern char url[STRING_SIZE];
struct nic nics[20] = { { "" , "" , "" } }; // only defined for compile
struct knic knics[20] = { { "" , "" , "" , "" } }; // only defined for compile
extern char *en_tr[];
extern char *es_tr[];
extern char *de_tr[];
extern char *fr_tr[];
int main(int argc, char *argv[])
{
char discl_msg[40000] = "Disclaimer\n";
char *langnames[] = { "Deutsch", "English", "Français", "Español", NULL };
char *shortlangnames[] = { "de", "en", "fr", "es", NULL };
char **langtrs[] = { de_tr, en_tr, fr_tr, es_tr, NULL };
char hdletter;
char harddrive[30], sourcedrive[5]; /* Device holder. */
struct devparams hdparams, cdromparams; /* Params for CDROM and HD */
int rc = 0;
char commandstring[STRING_SIZE];
char mkfscommand[STRING_SIZE];
char *fstypes[] = { "ext2", "ext3", "ext4", "ReiserFS", NULL };
int fstype = EXT3;
int choice;
int i;
int found = 0;
int firstrun = 0;
char shortlangname[10];
char message[1000];
char title[STRING_SIZE];
int allok = 0;
int allok_fastexit=0;
int raid_disk = 0;
struct keyvalue *ethernetkv = initkeyvalues();
FILE *handle, *cmdfile, *copying;
char line[STRING_SIZE];
char string[STRING_SIZE];
long memory = 0, disk = 0, free;
long system_partition, boot_partition, root_partition, swap_file;
int scsi_disk = 0;
char *yesnoharddisk[3]; // char *yesnoharddisk = { "NO", "YES", NULL };
int unattended = 0;
int serialconsole = 0;
struct keyvalue *unattendedkv = initkeyvalues();
int hardyn = 0;
char restore_file[STRING_SIZE] = "";
setlocale (LC_ALL, "");
sethostname( SNAME , 10);
memset(&hdparams, 0, sizeof(struct devparams));
memset(&cdromparams, 0, sizeof(struct devparams));
/* Log file/terminal stuff. */
if (argc >= 2)
{
if (!(flog = fopen(argv[1], "w+")))
return 0;
}
else
return 0;
mylog = argv[1];
fprintf(flog, "Install program started.\n");
newtInit();
newtCls();
newtDrawRootText(14, 0, NAME " " VERSION " - " SLOGAN );
sprintf (title, "%s %s - %s", NAME, VERSION, SLOGAN);
if (! (cmdfile = fopen("/proc/cmdline", "r")))
{
fprintf(flog, "Couldn't open commandline: /proc/cmdline\n");
} else {
fgets(line, STRING_SIZE, cmdfile);
// check if we have to make an unattended install
if (strstr (line, "unattended") != NULL) {
unattended = 1;
runcommandwithstatus("/bin/sleep 10", "WARNING: Unattended installation will start in 10 seconds...");
}
// check if we have to patch for serial console
if (strstr (line, "console=ttyS0") != NULL) {
serialconsole = 1;
}
}
// Read gpl ...
if (! (copying = fopen("/COPYING", "r")))
{
fprintf(flog, "Couldn't open gpl (/COPYING)\n");
sprintf(discl_msg, "Couldn't open gpl (/COPYING)\n");
} else {
fread(discl_msg, 1, 40000, copying);
fclose(copying);
}
// Load common modules
mysystem("/sbin/modprobe iso9660"); // CDROM
mysystem("/sbin/modprobe ext2"); // Boot patition
mysystem("/sbin/modprobe vfat"); // USB key
/* German is the default */
for (choice = 0; langnames[choice]; choice++)
{
if (strcmp(langnames[choice], "Deutsch") == 0)
break;
}
if (!langnames[choice])
goto EXIT;
if (!unattended) {
rc = newtWinMenu("Language selection", "Select the language you wish to use for the " NAME ".", 50, 5, 5, 8,
langnames, &choice, "Ok", NULL);
}
ctr = langtrs[choice];
strcpy(shortlangname, shortlangnames[choice]);
newtPushHelpLine(ctr[TR_HELPLINE]);
sprintf(message, ctr[TR_WELCOME], NAME);
newtWinMessage(title, ctr[TR_OK], message);
if (!unattended) {
if (disclaimerbox(discl_msg)==0) {
errorbox(ctr[TR_LICENSE_NOT_ACCEPTED]);
goto EXIT;
}
}
mysystem("/bin/mountsource.sh");
if ((handle = fopen("/tmp/source_device", "r")) == NULL) {
newtWinMessage(title, ctr[TR_OK], ctr[TR_NO_LOCAL_SOURCE]);
runcommandwithstatus("/bin/downloadsource.sh",ctr[TR_DOWNLOADING_ISO]);
if ((handle = fopen("/tmp/source_device", "r")) == NULL) {
errorbox(ctr[TR_DOWNLOAD_ERROR]);
goto EXIT;
}
}
fgets(sourcedrive, 5, handle);
fprintf(flog, "Source drive: %s\n", sourcedrive);
fclose(handle);
i = 0;
while (found == 0) {
i++;
fprintf(flog, "Harddisk scan pass %i\n", i);
switch (mysystem("/bin/mountdest.sh") % 255) {
case 0: // Found IDE disk
scsi_disk = 0;
raid_disk = 0;
found = 1;
break;
case 1: // Found SCSI disk
scsi_disk = 1;
raid_disk = 0;
found = 1;
break;
case 2: // Found RAID disk
scsi_disk = 0;
raid_disk= 1;
found = 1;
break;
case 10: // No harddisk found
if (firstrun == 1) {
errorbox(ctr[TR_NO_HARDDISK]);
goto EXIT;
}
// Do this if the kudzu-scan fails...
runcommandwithstatus("/bin/probehw.sh deep-scan", ctr[TR_PROBING_HARDWARE]);
firstrun = 1;
}
}
if ((handle = fopen("/tmp/dest_device", "r")) == NULL) {
errorbox(ctr[TR_NO_HARDDISK]);
goto EXIT;
}
fgets(harddrive, 30, handle);
fclose(handle);
/* load unattended configuration */
if (unattended) {
fprintf(flog, "unattended: Reading unattended.conf\n");
(void) readkeyvalues(unattendedkv, UNATTENDED_CONF);
findkey(unattendedkv, "RESTORE_FILE", restore_file);
}
/* Make the hdparms struct and print the contents.
With USB-KEY install and SCSI disk, while installing, the disk
is named 'sdb,sdc,...' (following keys)
On reboot, it will become 'sda'
To avoid many test, all names are built in the struct.
*/
sprintf(hdparams.devnode_disk, "/dev/%s", harddrive);
/* Address the partition or raid partition (eg dev/sda or /dev/sdap1 */
sprintf(hdparams.devnode_part, "/dev/%s%s", harddrive,raid_disk ? "p" : "");
/* Now the names after the machine is booted. Only scsi is affected
and we only install on the first scsi disk. */
fprintf(flog, "Destination drive: %s\n", hdparams.devnode_disk);
sprintf(message, ctr[TR_PREPARE_HARDDISK], hdparams.devnode_disk);
if (unattended) {
hardyn = 1;
} else {
yesnoharddisk[0] = ctr[TR_NO];
yesnoharddisk[1] = ctr[TR_YES];
yesnoharddisk[2] = NULL;
}
while (! hardyn) {
rc = newtWinMenu(title, message,
50, 5, 5, 6, yesnoharddisk,
&hardyn, ctr[TR_OK],
ctr[TR_CANCEL], NULL);
if (rc == 2)
goto EXIT;
}
if (rc == 2)
goto EXIT;
fstypes[0]=ctr[TR_EXT2FS_DESCR];
fstypes[1]=ctr[TR_EXT3FS_DESCR];
fstypes[2]=ctr[TR_EXT4FS_DESCR];
fstypes[3]=ctr[TR_REISERFS_DESCR];
fstypes[4]=NULL;
if (!unattended) {
sprintf(message, ctr[TR_CHOOSE_FILESYSTEM]);
rc = newtWinMenu( ctr[TR_CHOOSE_FILESYSTEM], message,
50, 5, 5, 6, fstypes, &fstype, ctr[TR_OK],
ctr[TR_CANCEL], NULL);
} else {
rc = 1;
fstype = EXT3;
}
if (rc == 2)
goto EXIT;
/* Calculate amount of memory in machine */
if ((handle = fopen("/proc/meminfo", "r")))
{
while (fgets(line, STRING_SIZE-1, handle)) {
if (sscanf (line, "MemTotal: %s kB", string)) {
memory = atoi(string) / 1024 ;
}
}
fclose(handle);
}
/* Partition, mkswp, mkfs.
* before partitioning, first determine the sizes of each
* partition. In order to do that we need to know the size of
* the disk.
*/
/* Don't use mysystem here so we can redirect output */
sprintf(commandstring, "/sbin/sfdisk -s /dev/%s > /tmp/disksize 2> /dev/null", harddrive);
system(commandstring);
/* Calculate amount of disk space */
if ((handle = fopen("/tmp/disksize", "r"))) {
fgets(line, STRING_SIZE-1, handle);
if (sscanf (line, "%s", string)) {
disk = atoi(string) / 1024;
}
fclose(handle);
}
fprintf(flog, "Disksize = %ld, memory = %ld", disk, memory);
/* Calculating Swap-Size dependend of Ram Size */
if (memory <= 256)
swap_file = 128;
else if (memory <= 1024 && memory > 256)
swap_file = 256;
else
swap_file = memory / 4;
/* Calculating Root-Size dependend of Max Disk Space */
if ( disk < 756 )
root_partition = 200;
else if ( disk >= 756 && disk <= 3072 )
root_partition = 512;
else
root_partition = 2048;
/* Calculating the amount of free space */
boot_partition = 20; /* in MB */
system_partition = disk - ( root_partition + swap_file + boot_partition );
fprintf(flog, ", boot = %ld, swap = %ld, mylog = %ld, root = %ld\n",
boot_partition, swap_file, system_partition, root_partition);
rc = 0;
if ( (!unattended) && (((disk - (root_partition + swap_file + boot_partition)) < 256 ) && ((disk - (root_partition + boot_partition )) > 256)) ) {
rc = newtWinChoice(title, ctr[TR_OK], ctr[TR_CANCEL], ctr[TR_CONTINUE_NO_SWAP]);
if (rc == 1){
swap_file = 0;
system_partition = disk - ( root_partition + swap_file + boot_partition );
fprintf(flog, "Changing Swap Size to 0 MB.\n");
}
else if (rc == 2){
fprintf(flog, "Disk is too small.\n");
errorbox(ctr[TR_DISK_TOO_SMALL]);goto EXIT;
}
}
else if (disk - (root_partition + swap_file + boot_partition) >= 256) {
}
else {
fprintf(flog, "Disk is too small.\n");
errorbox(ctr[TR_DISK_TOO_SMALL]);goto EXIT;
}
handle = fopen("/tmp/partitiontable", "w");
/* Make swapfile */
if (swap_file) {
fprintf(handle, ",%ld,L,*\n,%ld,S,\n,%ld,L,\n,,L,\n",
boot_partition, swap_file, root_partition);
} else {
fprintf(handle, ",%ld,L,*\n,0,0,\n,%ld,L,\n,,L,\n",
boot_partition, root_partition);
}
fclose(handle);
snprintf(commandstring, STRING_SIZE, "/sbin/sfdisk -L -uM %s < /tmp/partitiontable", hdparams.devnode_disk);
if (runcommandwithstatus(commandstring, ctr[TR_PARTITIONING_DISK]))
{
errorbox(ctr[TR_UNABLE_TO_PARTITION]);
goto EXIT;
}
if (fstype == EXT2) {
mysystem("/sbin/modprobe ext2");
sprintf(mkfscommand, "/sbin/mke2fs -T ext2");
} else if (fstype == REISERFS) {
mysystem("/sbin/modprobe reiserfs");
sprintf(mkfscommand, "/sbin/mkreiserfs -f");
} else if (fstype == EXT3) {
mysystem("/sbin/modprobe ext3");
sprintf(mkfscommand, "/sbin/mke2fs -T ext3");
} else if (fstype == EXT4) {
mysystem("/sbin/modprobe ext4");
sprintf(mkfscommand, "/sbin/mke2fs -T ext4");
}
snprintf(commandstring, STRING_SIZE, "/sbin/mke2fs -T ext2 -I 128 %s1", hdparams.devnode_part);
if (runcommandwithstatus(commandstring, ctr[TR_MAKING_BOOT_FILESYSTEM]))
{
errorbox(ctr[TR_UNABLE_TO_MAKE_BOOT_FILESYSTEM]);
goto EXIT;
}
if (swap_file) {
snprintf(commandstring, STRING_SIZE, "/sbin/mkswap %s2", hdparams.devnode_part);
if (runcommandwithstatus(commandstring, ctr[TR_MAKING_SWAPSPACE]))
{
errorbox(ctr[TR_UNABLE_TO_MAKE_SWAPSPACE]);
goto EXIT;
}
}
snprintf(commandstring, STRING_SIZE, "%s %s3", mkfscommand, hdparams.devnode_part);
if (runcommandwithstatus(commandstring, ctr[TR_MAKING_ROOT_FILESYSTEM]))
{
errorbox(ctr[TR_UNABLE_TO_MAKE_ROOT_FILESYSTEM]);
goto EXIT;
}
snprintf(commandstring, STRING_SIZE, "%s %s4", mkfscommand, hdparams.devnode_part);
if (runcommandwithstatus(commandstring, ctr[TR_MAKING_LOG_FILESYSTEM]))
{
errorbox(ctr[TR_UNABLE_TO_MAKE_LOG_FILESYSTEM]);
goto EXIT;
}
snprintf(commandstring, STRING_SIZE, "/bin/mount %s3 /harddisk", hdparams.devnode_part);
if (runcommandwithstatus(commandstring, ctr[TR_MOUNTING_ROOT_FILESYSTEM]))
{
errorbox(ctr[TR_UNABLE_TO_MOUNT_ROOT_FILESYSTEM]);
goto EXIT;
}
mkdir("/harddisk/boot", S_IRWXU|S_IRWXG|S_IRWXO);
mkdir("/harddisk/var", S_IRWXU|S_IRWXG|S_IRWXO);
mkdir("/harddisk/var/log", S_IRWXU|S_IRWXG|S_IRWXO);
snprintf(commandstring, STRING_SIZE, "/bin/mount %s1 /harddisk/boot", hdparams.devnode_part);
if (runcommandwithstatus(commandstring, ctr[TR_MOUNTING_BOOT_FILESYSTEM]))
{
errorbox(ctr[TR_UNABLE_TO_MOUNT_BOOT_FILESYSTEM]);
goto EXIT;
}
if (swap_file) {
snprintf(commandstring, STRING_SIZE, "/sbin/swapon %s2", hdparams.devnode_part);
if (runcommandwithstatus(commandstring, ctr[TR_MOUNTING_SWAP_PARTITION]))
{
errorbox(ctr[TR_UNABLE_TO_MOUNT_SWAP_PARTITION]);
goto EXIT;
}
}
snprintf(commandstring, STRING_SIZE, "/bin/mount %s4 /harddisk/var", hdparams.devnode_part);
if (runcommandwithstatus(commandstring, ctr[TR_MOUNTING_LOG_FILESYSTEM]))
{
errorbox(ctr[TR_UNABLE_TO_MOUNT_LOG_FILESYSTEM]);
goto EXIT;
}
snprintf(commandstring, STRING_SIZE,
"/bin/tar -C /harddisk -xvf /cdrom/" SNAME "-" VERSION ".tlz --lzma 2>/dev/null");
if (runcommandwithprogress(60, 4, title, commandstring, INST_FILECOUNT,
ctr[TR_INSTALLING_FILES]))
{
errorbox(ctr[TR_UNABLE_TO_INSTALL_FILES]);
goto EXIT;
}
/* Save language und local settings */
write_lang_configs(shortlangname);
/* Rename uname */
rename ("/harddisk/bin/uname.bak", "/harddisk/bin/uname");
/* mount proc filesystem */
mysystem("mkdir /harddisk/proc");
mysystem("/bin/mount --bind /proc /harddisk/proc");
mysystem("/bin/mount --bind /dev /harddisk/dev");
mysystem("/bin/mount --bind /sys /harddisk/sys");
/* Build cache lang file */
snprintf(commandstring, STRING_SIZE, "/usr/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 */
snprintf(commandstring, STRING_SIZE, "/bin/sed -i -e \"s#DEVICE1#UUID=$(/sbin/blkid %s1 -sUUID | /usr/bin/cut -d'\"' -f2)#g\" /harddisk/etc/fstab", hdparams.devnode_part);
system(commandstring);
snprintf(commandstring, STRING_SIZE, "/bin/sed -i -e \"s#DEVICE2#UUID=$(/sbin/blkid %s2 -sUUID | /usr/bin/cut -d'\"' -f2)#g\" /harddisk/etc/fstab", hdparams.devnode_part);
system(commandstring);
snprintf(commandstring, STRING_SIZE, "/bin/sed -i -e \"s#DEVICE3#UUID=$(/sbin/blkid %s3 -sUUID | /usr/bin/cut -d'\"' -f2)#g\" /harddisk/etc/fstab", hdparams.devnode_part);
system(commandstring);
snprintf(commandstring, STRING_SIZE, "/bin/sed -i -e \"s#DEVICE4#UUID=$(/sbin/blkid %s4 -sUUID | /usr/bin/cut -d'\"' -f2)#g\" /harddisk/etc/fstab", hdparams.devnode_part);
system(commandstring);
if (fstype == EXT2) {
replace("/harddisk/etc/fstab", "FSTYPE", "ext2");
replace("/harddisk/boot/grub/grub.conf", "MOUNT", "ro");
} else if (fstype == REISERFS) {
replace("/harddisk/etc/fstab", "FSTYPE", "reiserfs");
replace("/harddisk/boot/grub/grub.conf", "MOUNT", "ro");
} else if (fstype == EXT3) {
replace("/harddisk/etc/fstab", "FSTYPE", "ext3");
replace("/harddisk/boot/grub/grub.conf", "MOUNT", "ro");
} else if (fstype == EXT4) {
replace("/harddisk/etc/fstab", "FSTYPE", "ext4");
replace("/harddisk/boot/grub/grub.conf", "MOUNT", "ro");
}
replace("/harddisk/boot/grub/grub.conf", "KVER", KERNEL_VERSION);
snprintf(commandstring, STRING_SIZE, "/bin/sed -i -e \"s#root=ROOT#root=UUID=$(/sbin/blkid %s3 -sUUID | /usr/bin/cut -d'\"' -f2)#g\" /harddisk/boot/grub/grub.conf", hdparams.devnode_part);
system(commandstring);
mysystem("ln -s grub.conf /harddisk/boot/grub/menu.lst");
system("/bin/sed -e 's#/harddisk#/#g' -e 's#//#/#g' < /proc/mounts > /harddisk/etc/mtab");
snprintf(commandstring, STRING_SIZE,
"/usr/sbin/chroot /harddisk /usr/sbin/grub-install --no-floppy %s", hdparams.devnode_disk);
if (runcommandwithstatus(commandstring, ctr[TR_INSTALLING_GRUB])) {
errorbox(ctr[TR_UNABLE_TO_INSTALL_GRUB]);
goto EXIT;
}
/* Serial console ? */
if (serialconsole) {
/* grub */
replace("/harddisk/boot/grub/grub.conf", "splashimage", "#splashimage");
replace("/harddisk/boot/grub/grub.conf", "#serial", "serial");
replace("/harddisk/boot/grub/grub.conf", "#terminal", "terminal");
replace("/harddisk/boot/grub/grub.conf", " panic=10 ", " console=ttyS0,38400n8 panic=10 ");
/*inittab*/
replace("/harddisk/etc/inittab", "1:2345:respawn:", "#1:2345:respawn:");
replace("/harddisk/etc/inittab", "2:2345:respawn:", "#2:2345:respawn:");
replace("/harddisk/etc/inittab", "3:2345:respawn:", "#3:2345:respawn:");
replace("/harddisk/etc/inittab", "4:2345:respawn:", "#4:2345:respawn:");
replace("/harddisk/etc/inittab", "5:2345:respawn:", "#5:2345:respawn:");
replace("/harddisk/etc/inittab", "6:2345:respawn:", "#6:2345:respawn:");
replace("/harddisk/etc/inittab", "#7:2345:respawn:", "7:2345:respawn:");
}
/* Copy restore file from cdrom */
if (unattended && (strlen(restore_file) > 0)) {
fprintf(flog, "unattended: Copy restore file\n");
snprintf(commandstring, STRING_SIZE,
"cp /cdrom/%s /harddisk/var/ipfire/backup", restore_file);
mysystem(commandstring);
}
mysystem("umount /cdrom");
snprintf(commandstring, STRING_SIZE, "/usr/bin/eject /dev/%s", sourcedrive);
mysystem(commandstring);
if (!unattended) {
sprintf(message, ctr[TR_CONGRATULATIONS_LONG],
NAME, SNAME, NAME);
newtWinMessage(ctr[TR_CONGRATULATIONS], ctr[TR_OK], message);
}
allok = 1;
EXIT:
fprintf(flog, "Install program ended.\n");
if (!(allok))
newtWinMessage(title, ctr[TR_OK], ctr[TR_PRESS_OK_TO_REBOOT]);
freekeyvalues(ethernetkv);
if (allok && !allok_fastexit)
{
if (unattended) {
fprintf(flog, "Entering unattended setup\n");
if (unattended_setup(unattendedkv)) {
snprintf(commandstring, STRING_SIZE, "/bin/sleep 10");
runcommandwithstatus(commandstring, "Unattended installation finished, system will reboot");
} else {
errorbox("Unattended setup failed.");
goto EXIT;
}
}
fflush(flog);
fclose(flog);
newtFinished();
if (unattended) {
// Remove Setup autorun after boot
if (system("rm -f /harddisk/etc/rc.d/rcsysinit.d/S75firstsetup"))
printf("Unable to disable setup autorun.\n");
}
if (system("/bin/umount /harddisk/proc"))
printf("Unable to umount /harddisk/proc.\n");
} else {
fflush(flog);
fclose(flog);
newtFinished();
}
fcloseall();
if (swap_file) {
snprintf(commandstring, STRING_SIZE, "/bin/swapoff %s2", hdparams.devnode_part);
}
newtFinished();
system("/bin/umount /harddisk/proc");
system("/bin/umount /harddisk/dev");
system("/bin/umount /harddisk/sys");
system("/bin/umount /harddisk/var");
system("/bin/umount /harddisk/boot");
system("/bin/umount /harddisk");
if (!(allok))
system("/etc/halt");
return 0;
}