1 /* SmoothWall install program.
3 * This program is distributed under the terms of the GNU General Public
4 * Licence. See the file COPYING for details.
6 * (c) Lawrence Manning, 2001
7 * Contains main entry point, and misc functions.6
14 #define CDROM_INSTALL 0
16 #define DISK_INSTALL 2
17 #define INST_FILECOUNT 6000
18 #define UNATTENDED_CONF "/cdrom/boot/unattended.conf"
30 extern char url
[STRING_SIZE
];
32 struct nic nics
[20] = { { "" , "" , "" } }; // only defined for compile
33 struct knic knics
[20] = { { "" , "" , "" , "" } }; // only defined for compile
40 char line
[STRING_SIZE
];
43 if ((fd
= fopen("/proc/cpuinfo", "r")) == NULL
) {
46 while (fgets(line
, STRING_SIZE
, fd
) != NULL
) {
47 if (strstr(line
, "processor") == line
) {
52 return (cpu_count
> 1);
55 long calc_swapsize(long memory
, long disk
) {
66 long calc_rootsize(long free
, long max
) {
79 int main(int argc
, char *argv
[])
81 char *langnames
[] = { "Deutsch", "English", NULL
};
82 char *shortlangnames
[] = { "de", "en", NULL
};
83 char **langtrs
[] = { de_tr
, en_tr
, NULL
};
85 char harddrive
[5], sourcedrive
[5]; /* Device holder. */
86 struct devparams hdparams
, cdromparams
; /* Params for CDROM and HD */
87 int cdmounted
= 0; /* Loop flag for inserting a cd. */
89 char commandstring
[STRING_SIZE
];
90 char *installtypes
[] = { "CDROM/USB", "HTTP/FTP", NULL
};
91 int installtype
= CDROM_INSTALL
;
92 char mkfscommand
[STRING_SIZE
];
93 char *fstypes
[] = { "Reiser4", "ReiserFS", "ext3", NULL
};
99 char shortlangname
[10];
101 char title
[STRING_SIZE
];
103 int allok_fastexit
=0;
104 struct keyvalue
*ethernetkv
= initkeyvalues();
105 FILE *handle
, *cmdfile
;
106 char line
[STRING_SIZE
];
107 char string
[STRING_SIZE
];
108 long maximum_free
= 0, current_free
;
110 long system_partition
, boot_partition
, root_partition
, swap_file
;
112 char *yesnoharddisk
[3]; // char *yesnoharddisk = { "NO", "YES", NULL };
115 struct keyvalue
*unattendedkv
= initkeyvalues();
118 setlocale (LC_ALL
, "");
119 sethostname( SNAME
, 10);
121 memset(&hdparams
, 0, sizeof(struct devparams
));
122 memset(&cdromparams
, 0, sizeof(struct devparams
));
124 /* Log file/terminal stuff. */
127 if (!(flog
= fopen(argv
[1], "w+")))
135 fprintf(flog
, "Install program started.\n");
140 /* Do usb detection first for usb keyboard */
141 if (! (cmdfile
= fopen("/proc/cmdline", "r")))
143 fprintf(flog
, "Couldn't open commandline: /proc/cmdline\n");
145 fgets(line
, STRING_SIZE
, cmdfile
);
146 if (strstr (line
, "noide") == NULL
) {
147 fprintf(flog
, "Initializing IDE controllers.\n");
150 fprintf(flog
, "Skipping IDE detection.\n");
152 if (strstr (line
, "nousb") == NULL
) {
153 fprintf(flog
, "Initializing USB controllers.\n");
156 fprintf(flog
, "Skipping USB detection.\n");
158 // check if we have to make an unattended install
159 if (strstr (line
, "unattended") != NULL
) {
162 // Loading the cdrom-filesystem
163 mysystem("/sbin/modprobe iso9660");
167 runcommandwithstatus("/bin/sleep 10", "WARNING: Unattended installation will start in 10 seconds...");
170 /* German is the default */
171 for (choice
= 0; langnames
[choice
]; choice
++)
173 if (strcmp(langnames
[choice
], "Deutsch") == 0)
176 if (!langnames
[choice
])
180 rc
= newtWinMenu("Language selection",
181 "Select the language you wish to use for the " NAME
".", 50, 5, 5, 8,
182 langnames
, &choice
, "Ok", NULL
);
185 ctr
= langtrs
[choice
];
186 strcpy(shortlangname
, shortlangnames
[choice
]);
187 fprintf(flog
, "Selected language: %s\n", shortlangname
);
189 newtDrawRootText(14, 0, NAME
" " VERSION
" - " SLOGAN
);
190 newtPushHelpLine(ctr
[TR_HELPLINE
]);
191 sprintf (title
, "%s %s - %s", NAME
, VERSION
, SLOGAN
);
194 sprintf(message
, ctr
[TR_WELCOME
], NAME
);
195 newtWinMessage(title
, ctr
[TR_OK
], message
);
197 sprintf(message
, ctr
[TR_SELECT_INSTALLATION_MEDIA_LONG
], NAME
);
198 rc
= newtWinMenu(ctr
[TR_SELECT_INSTALLATION_MEDIA
], message
,
199 50, 5, 5, 6, installtypes
, &installtype
, ctr
[TR_OK
],
200 ctr
[TR_CANCEL
], NULL
);
203 installtype
= CDROM_INSTALL
;
209 // Starting hardware detection
210 runcommandwithstatus("/bin/probehw.sh", ctr
[TR_PROBING_HARDWARE
]);
211 runcommandwithstatus("/bin/probenic.sh install", ctr
[TR_PROBING_HARDWARE
]);
214 if (installtype
== CDROM_INSTALL
) {
215 switch (mysystem("/bin/mountsource.sh")) {
217 installtype
= CDROM_INSTALL
;
221 installtype
= DISK_INSTALL
;
224 errorbox(ctr
[TR_NO_CDROM
]);
228 /* read source drive letter */
229 if ((handle
= fopen("/tmp/source_device", "r")) == NULL
) {
230 errorbox(ctr
[TR_ERROR_PROBING_CDROM
]);
233 fgets(sourcedrive
, 5, handle
);
234 fprintf(flog
, "Source drive: %s\n", sourcedrive
);
238 /* Configure the network now! */
239 if (installtype
== URL_INSTALL
) {
240 /* Network driver and params. */
241 if (!(networkmenu(ethernetkv
))) {
242 errorbox(ctr
[TR_NETWORK_SETUP_FAILED
]);
246 /* Check for ipfire-<VERSION>.tbz2 */
247 if (checktarball(SNAME
"-" VERSION
".tbz2", ctr
[TR_ENTER_URL
])) {
248 errorbox(ctr
[TR_NO_IPCOP_TARBALL_FOUND
]);
256 fprintf(flog
, "Harddisk scan pass %i\n", i
);
258 switch (mysystem("/bin/mountdest.sh") % 255) {
259 case 0: // Found IDE disk
263 case 1: // Found SCSI disk
267 case 10: // No harddisk found
269 errorbox(ctr
[TR_NO_HARDDISK
]);
272 // Do this if the kudzu-scan fails...
273 runcommandwithstatus("/bin/probehw.sh deep-scan", ctr
[TR_PROBING_HARDWARE
]);
279 // Need to clean this up at some point
280 // scsi disk is sdb/sdc when sda/sdb is used for usb-key
281 // if scsi-disk is sdd or more, it is not discovered
282 // Support only 2 usb keys, none could be unplugged
283 if (checkusb("sdb") && try_scsi("sdc")) {
285 sprintf(harddrive, "sdc");
286 goto FOUND_DESTINATION;
288 if (checkusb("sda") && try_scsi("sdb")) {
290 sprintf(harddrive, "sdb");
291 goto FOUND_DESTINATION;
293 if (try_scsi("sda")) {
295 sprintf(harddrive, "sda");
296 goto FOUND_DESTINATION;
298 if (try_scsi("ida/c0d0")) {
300 sprintf(harddrive, "ida/c0d0");
301 goto FOUND_DESTINATION;
303 if (try_scsi("cciss/c0d0")) {
305 sprintf(harddrive, "cciss/c0d0");
306 goto FOUND_DESTINATION;
308 if (try_scsi("rd/c0d0")) {
310 sprintf(harddrive, "rd/c0d0");
311 goto FOUND_DESTINATION;
313 if (try_scsi("ataraid/d0")) {
315 sprintf(harddrive, "ataraid/d0");
316 goto FOUND_DESTINATION;
320 if ((handle
= fopen("/tmp/dest_device", "r")) == NULL
) {
321 errorbox(ctr
[TR_NO_HARDDISK
]);
324 fgets(harddrive
, 5, handle
);
327 /* load unattended configuration */
329 fprintf(flog
, "unattended: Reading unattended.conf\n");
331 (void) readkeyvalues(unattendedkv
, UNATTENDED_CONF
);
334 /* Make the hdparms struct and print the contents.
335 With USB-KEY install and SCSI disk, while installing, the disk
336 is named 'sdb,sdc,...' (following keys)
337 On reboot, it will become 'sda'
338 To avoid many test, all names are built in the struct.
340 sprintf(hdparams
.devnode_disk
, "/dev/%s", harddrive
);
341 /* Address the partition or raid partition (eg dev/sda or /dev/sdap1 */
342 sprintf(hdparams
.devnode_part
, "/dev/%s%s", harddrive
,raid_disk
? "p" : "");
343 /* Now the names after the machine is booted. Only scsi is affected
344 and we only install on the first scsi disk. */
346 strcpy(tmp
, scsi_disk
? "sda" : harddrive
);
347 sprintf(hdparams
.devnode_disk_run
, "/dev/%s", tmp
);
348 sprintf(hdparams
.devnode_part_run
, "/dev/%s%s", tmp
, raid_disk
? "p" : "");
351 fprintf(flog
, "Destination drive: %s\n", hdparams
.devnode_disk
);
353 sprintf(message
, ctr
[TR_PREPARE_HARDDISK
], hdparams
.devnode_disk
);
358 yesnoharddisk
[0] = ctr
[TR_NO
];
359 yesnoharddisk
[1] = ctr
[TR_YES
];
360 yesnoharddisk
[2] = NULL
;
363 rc
= newtWinMenu(title
, message
,
364 50, 5, 5, 6, yesnoharddisk
,
366 ctr
[TR_CANCEL
], NULL
);
374 sprintf(message
, "(TR) Bitte waehlen Sie ihr Dateisystem aus:");
375 rc
= newtWinMenu("(TR) Dateisystemauswahl", message
,
376 50, 5, 5, 6, fstypes
, &fstype
, ctr
[TR_OK
],
377 ctr
[TR_CANCEL
], NULL
);
380 fstype
= REISER4
; // Reiser4 is our standard filesystem. Love it or shut up!
385 /* Calculate amount of memory in machine */
386 if ((handle
= fopen("/proc/meminfo", "r")))
388 while (fgets(line
, STRING_SIZE
-1, handle
)) {
389 if (sscanf (line
, "MemTotal: %s kB", string
)) {
390 memory
= atoi(string
) / 1024 ;
396 /* Partition, mkswp, mkfs.
397 * before partitioning, first determine the sizes of each
398 * partition. In order to do that we need to know the size of
401 /* Don't use mysystem here so we can redirect output */
402 sprintf(commandstring
, "/bin/sfdisk -s /dev/%s > /tmp/disksize 2> /dev/null", harddrive
);
403 system(commandstring
);
405 /* Calculate amount of disk space */
406 if ((handle
= fopen("/tmp/disksize", "r"))) {
407 fgets(line
, STRING_SIZE
-1, handle
);
408 if (sscanf (line
, "%s", string
)) {
409 maximum_free
= atoi(string
) / 1024;
414 fprintf(flog
, "maximum_free = %ld, memory = %ld", maximum_free
, memory
);
416 swap_file
= calc_swapsize(memory
, maximum_free
);
418 if (maximum_free
< 768 + swap_file
) {
419 if (maximum_free
< 768) {
420 errorbox(ctr
[TR_DISK_TOO_SMALL
]);
425 rc
= newtWinChoice(title
, ctr
[TR_OK
], ctr
[TR_CANCEL
], ctr
[TR_CONTINUE_NO_SWAP
]);
436 boot_partition
= 20; /* in MB */
437 current_free
= maximum_free
- boot_partition
- swap_file
;
439 if (current_free
< 768) {
440 errorbox(ctr
[TR_DISK_TOO_SMALL
]);
444 root_partition
= calc_rootsize(current_free
, maximum_free
);
446 if (root_partition
== 0) {
447 errorbox(ctr
[TR_DISK_TOO_SMALL
]);
450 current_free
= current_free
- root_partition
;
453 if (current_free
< 256) {
454 errorbox(ctr
[TR_DISK_TOO_SMALL
]);
458 system_partition
= current_free
;
460 fprintf(flog
, "boot = %ld, swap = %ld, mylog = %ld, root = %ld\n",
461 boot_partition
, swap_file
, system_partition
, root_partition
);
463 handle
= fopen("/tmp/partitiontable", "w");
467 fprintf(handle
, ",%ld,L,*\n,%ld,S,\n,%ld,L,\n,,L,\n",
468 boot_partition
, swap_file
, root_partition
);
470 fprintf(handle
, ",%ld,L,*\n,0,0,\n,%ld,L,\n,,L,\n",
471 boot_partition
, root_partition
);
476 snprintf(commandstring
, STRING_SIZE
, "/bin/sfdisk -L -uM %s < /tmp/partitiontable", hdparams
.devnode_disk
);
477 if (runcommandwithstatus(commandstring
, ctr
[TR_PARTITIONING_DISK
]))
479 errorbox(ctr
[TR_UNABLE_TO_PARTITION
]);
483 if (fstype
== REISER4
) {
484 mysystem("/sbin/modprobe reiser4");
485 sprintf(mkfscommand
, "/sbin/mkfs.reiser4 -y");
486 } else if (fstype
== REISERFS
) {
487 mysystem("/sbin/modprobe reiserfs");
488 sprintf(mkfscommand
, "/sbin/mkreiserfs -f");
489 } else if (fstype
== EXT3
) {
490 mysystem("/sbin/modprobe ext3");
491 sprintf(mkfscommand
, "/bin/mke2fs -T ext3 -c");
494 snprintf(commandstring
, STRING_SIZE
, "/bin/mke2fs -T ext2 -c %s1", hdparams
.devnode_part
);
495 if (runcommandwithstatus(commandstring
, ctr
[TR_MAKING_BOOT_FILESYSTEM
]))
497 errorbox(ctr
[TR_UNABLE_TO_MAKE_BOOT_FILESYSTEM
]);
502 snprintf(commandstring
, STRING_SIZE
, "/sbin/mkswap %s2", hdparams
.devnode_part
);
503 if (runcommandwithstatus(commandstring
, ctr
[TR_MAKING_SWAPSPACE
]))
505 errorbox(ctr
[TR_UNABLE_TO_MAKE_SWAPSPACE
]);
510 snprintf(commandstring
, STRING_SIZE
, "%s %s3", mkfscommand
, hdparams
.devnode_part
);
511 if (runcommandwithstatus(commandstring
, ctr
[TR_MAKING_ROOT_FILESYSTEM
]))
513 errorbox(ctr
[TR_UNABLE_TO_MAKE_ROOT_FILESYSTEM
]);
517 snprintf(commandstring
, STRING_SIZE
, "%s %s4", mkfscommand
, hdparams
.devnode_part
);
518 if (runcommandwithstatus(commandstring
, ctr
[TR_MAKING_LOG_FILESYSTEM
]))
520 errorbox(ctr
[TR_UNABLE_TO_MAKE_LOG_FILESYSTEM
]);
524 snprintf(commandstring
, STRING_SIZE
, "/bin/mount %s3 /harddisk", hdparams
.devnode_part
);
525 if (runcommandwithstatus(commandstring
, ctr
[TR_MOUNTING_ROOT_FILESYSTEM
]))
527 errorbox(ctr
[TR_UNABLE_TO_MOUNT_ROOT_FILESYSTEM
]);
531 mkdir("/harddisk/boot", S_IRWXU
|S_IRWXG
|S_IRWXO
);
532 mkdir("/harddisk/var", S_IRWXU
|S_IRWXG
|S_IRWXO
);
533 mkdir("/harddisk/var/log", S_IRWXU
|S_IRWXG
|S_IRWXO
);
535 snprintf(commandstring
, STRING_SIZE
, "/bin/mount %s1 /harddisk/boot", hdparams
.devnode_part
);
536 if (runcommandwithstatus(commandstring
, ctr
[TR_MOUNTING_BOOT_FILESYSTEM
]))
538 errorbox(ctr
[TR_UNABLE_TO_MOUNT_BOOT_FILESYSTEM
]);
542 snprintf(commandstring
, STRING_SIZE
, "/sbin/swapon %s2", hdparams
.devnode_part
);
543 if (runcommandwithstatus(commandstring
, ctr
[TR_MOUNTING_SWAP_PARTITION
]))
545 errorbox(ctr
[TR_UNABLE_TO_MOUNT_SWAP_PARTITION
]);
549 snprintf(commandstring
, STRING_SIZE
, "/bin/mount %s4 /harddisk/var", hdparams
.devnode_part
);
550 if (runcommandwithstatus(commandstring
, ctr
[TR_MOUNTING_LOG_FILESYSTEM
]))
552 errorbox(ctr
[TR_UNABLE_TO_MOUNT_LOG_FILESYSTEM
]);
556 if (installtype
== URL_INSTALL
) {
557 snprintf(commandstring
, STRING_SIZE
,
558 "/bin/wget -q -O - %s/" SNAME
"-" VERSION
".tbz2 | /bin/tar -C /harddisk -xvjf -", url
);
561 if (installtype
== CDROM_INSTALL
) {
562 snprintf(commandstring
, STRING_SIZE
,
563 "/bin/tar -C /harddisk -xvjf /cdrom/" SNAME
"-" VERSION
".tbz2");
566 if (runcommandwithprogress(60, 4, title
, commandstring
, INST_FILECOUNT
,
567 ctr
[TR_INSTALLING_FILES
]))
569 errorbox(ctr
[TR_UNABLE_TO_INSTALL_FILES
]);
573 /* Save USB controller type to modules.conf */
574 write_usb_modules_conf();
576 /* Save language und local settings */
577 write_lang_configs(shortlangname
);
579 /* touch the modules.dep files */
580 snprintf(commandstring
, STRING_SIZE
,
581 "/bin/touch /harddisk/lib/modules/%s-ipfire/modules.dep",
583 mysystem(commandstring
);
584 snprintf(commandstring
, STRING_SIZE
,
585 "/bin/touch /harddisk/lib/modules/%s-ipfire-smp/modules.dep",
587 mysystem(commandstring
);
590 rename ("/harddisk/bin/uname.bak", "/harddisk/bin/uname");
592 /* mount proc filesystem */
593 mysystem("mkdir /harddisk/proc");
594 mysystem("/bin/mount --bind /proc /harddisk/proc");
595 mysystem("/bin/mount --bind /dev /harddisk/dev");
596 mysystem("/bin/mount --bind /sys /harddisk/sys");
598 /* Build cache lang file */
599 snprintf(commandstring
, STRING_SIZE
, "/sbin/chroot /harddisk /usr/bin/perl -e \"require '" CONFIG_ROOT
"/lang.pl'; &Lang::BuildCacheLang\"");
600 if (runcommandwithstatus(commandstring
, ctr
[TR_INSTALLING_LANG_CACHE
]))
602 errorbox(ctr
[TR_UNABLE_TO_INSTALL_LANG_CACHE
]);
606 /* Update /etc/fstab */
607 replace("/harddisk/etc/fstab", "DEVICE", hdparams
.devnode_part_run
);
609 if (fstype
== REISER4
) {
610 replace("/harddisk/etc/fstab", "FSTYPE", "reiser4");
611 replace("/harddisk/etc/mkinitcpio.conf", "MODULES=\"", "MODULES=\"reiser4 ");
612 replace("/harddisk/boot/grub/grub.conf", "MOUNT", "rw");
613 } else if (fstype
== REISERFS
) {
614 replace("/harddisk/etc/fstab", "FSTYPE", "reiserfs");
615 replace("/harddisk/boot/grub/grub.conf", "MOUNT", "ro");
616 } else if (fstype
== EXT3
) {
617 replace("/harddisk/etc/fstab", "FSTYPE", "ext3");
618 replace("/harddisk/boot/grub/grub.conf", "MOUNT", "ro");
621 /* Going to make our initrd... */
622 snprintf(commandstring
, STRING_SIZE
, "/sbin/chroot /harddisk /sbin/mkinitcpio -v -g /boot/ipfirerd.img -k %s-ipfire", KERNEL_VERSION
);
623 runcommandwithstatus(commandstring
, ctr
[TR_BUILDING_INITRD
]);
624 snprintf(commandstring
, STRING_SIZE
, "/sbin/chroot /harddisk /sbin/mkinitcpio -v -g /boot/ipfirerd-smp.img -k %s-ipfire-smp", KERNEL_VERSION
);
625 runcommandwithstatus(commandstring
, ctr
[TR_BUILDING_INITRD
]);
627 sprintf(string
, "root=%s3", hdparams
.devnode_part_run
);
628 replace( "/harddisk/boot/grub/grub.conf", "root=ROOT", string
);
629 replace( "/harddisk/boot/grub/grubbatch", "DEVICE", hdparams
.devnode_disk
);
631 /* restore permissions */
632 chmod("/harddisk/boot/grub/grubbatch", S_IXUSR
| S_IRUSR
| S_IXGRP
| S_IRGRP
| S_IXOTH
| S_IROTH
);
634 snprintf(commandstring
, STRING_SIZE
,
635 "/sbin/chroot /harddisk /boot/grub/grubbatch");
636 if (runcommandwithstatus(commandstring
, ctr
[TR_INSTALLING_GRUB
])) {
637 errorbox(ctr
[TR_UNABLE_TO_INSTALL_GRUB
]);
641 mysystem("ln -s grub.conf /harddisk/boot/grub/menu.lst");
644 sprintf(message
, ctr
[TR_CONGRATULATIONS_LONG
],
646 newtWinMessage(ctr
[TR_CONGRATULATIONS
], ctr
[TR_OK
], message
);
652 fprintf(flog
, "Install program ended.\n");
655 newtWinMessage(title
, ctr
[TR_OK
], ctr
[TR_PRESS_OK_TO_REBOOT
]);
657 freekeyvalues(ethernetkv
);
659 if (allok
&& !allok_fastexit
)
662 fprintf(flog
, "Entering unattended setup\n");
663 if (unattended_setup(unattendedkv
)) {
664 snprintf(commandstring
, STRING_SIZE
, "/bin/sleep 10");
665 runcommandwithstatus(commandstring
, "Unattended installation finished, system will reboot");
667 errorbox("Unattended setup failed.");
677 // Copy our scanned nics to the disk and lock because scan doesn't work in chroot
678 system("touch /harddisk/var/ipfire/ethernet/scan_lock");
679 system("cp -f /tmp/scanned_nics /harddisk/var/ipfire/ethernet/scanned_nics");
680 if (system("/sbin/chroot /harddisk /usr/local/sbin/setup /dev/tty2 INSTALL"))
681 printf("Unable to run setup.\n");
682 system("rm -f /harddisk/var/ipfire/ethernet/scan_lock");
685 if (system("/bin/umount /harddisk/proc"))
686 printf("Unable to umount /harddisk/proc.\n");
696 snprintf(commandstring
, STRING_SIZE
, "/bin/swapoff %s2", hdparams
.devnode_part
);
701 system("/bin/umount /harddisk/proc");
702 system("/bin/umount /harddisk/dev");
703 system("/bin/umount /harddisk/sys");
705 system("/bin/umount /harddisk/var");
706 system("/bin/umount /harddisk/boot");
707 system("/bin/umount /harddisk");