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.
14 #define CDROM_INSTALL 0
16 #define DISK_INSTALL 2
17 #define INST_FILECOUNT 7000
18 #define UNATTENDED_CONF "/cdrom/boot/unattended.conf"
26 extern char url
[STRING_SIZE
];
28 struct nic nics
[20] = { { "" , "" } }; // only defined for compile
29 struct knic knics
[20] = { { "" , "" , "" } }; // only defined for compile
36 char line
[STRING_SIZE
];
39 if ((fd
= fopen("/proc/cpuinfo", "r")) == NULL
) {
42 while (fgets(line
, STRING_SIZE
, fd
) != NULL
) {
43 if (strstr(line
, "processor") == line
) {
48 return (cpu_count
> 1);
51 long calc_swapsize(long memory
, long disk
) {
62 int main(int argc
, char *argv
[])
64 char *langnames
[] = { "Deutsch", "English", NULL
};
65 char *shortlangnames
[] = { "de", "en", NULL
};
66 char **langtrs
[] = { de_tr
, en_tr
, NULL
};
68 char harddrive
[5], sourcedrive
[5]; /* Device holder. */
69 struct devparams hdparams
, cdromparams
; /* Params for CDROM and HD */
70 int cdmounted
= 0; /* Loop flag for inserting a cd. */
72 char commandstring
[STRING_SIZE
];
73 char *installtypes
[] = { "CDROM/USB", "HTTP/FTP", NULL
};
74 int installtype
= CDROM_INSTALL
;
79 char shortlangname
[10];
81 char title
[STRING_SIZE
];
84 struct keyvalue
*ethernetkv
= initkeyvalues();
85 FILE *handle
, *cmdfile
;
86 char line
[STRING_SIZE
];
87 char string
[STRING_SIZE
];
88 long maximum_free
= 0, current_free
;
90 long system_partition
, boot_partition
, root_partition
, swap_file
;
92 char *yesnoharddisk
[3]; // char *yesnoharddisk = { "NO", "YES", NULL };
95 struct keyvalue
*unattendedkv
= initkeyvalues();
98 setlocale (LC_ALL
, "");
99 sethostname( SNAME
, 10);
101 memset(&hdparams
, 0, sizeof(struct devparams
));
102 memset(&cdromparams
, 0, sizeof(struct devparams
));
104 /* Log file/terminal stuff. */
107 if (!(flog
= fopen(argv
[1], "w+")))
115 fprintf(flog
, "Install program started.\n");
120 /* Do usb detection first for usb keyboard */
121 if (! (cmdfile
= fopen("/proc/cmdline", "r")))
123 fprintf(flog
, "Couldn't open commandline: /proc/cmdline\n");
125 fgets(line
, STRING_SIZE
, cmdfile
);
126 if (strstr (line
, "noide") == NULL
) {
127 fprintf(flog
, "Initializing IDE controllers.\n");
130 fprintf(flog
, "Skipping IDE detection.\n");
132 if (strstr (line
, "nousb") == NULL
) {
133 fprintf(flog
, "Initializing USB controllers.\n");
136 fprintf(flog
, "Skipping USB detection.\n");
138 // check if we have to make an unattended install
139 if (strstr (line
, "unattended") != NULL
) {
142 // Loading the cdrom-filesystem
143 mysystem("/sbin/modprobe iso9660");
147 runcommandwithstatus("/bin/sleep 10", "WARNING: Unattended installation will start in 10 seconds...");
150 /* German is the default */
151 for (choice
= 0; langnames
[choice
]; choice
++)
153 if (strcmp(langnames
[choice
], "Deutsch") == 0)
156 if (!langnames
[choice
])
160 rc
= newtWinMenu("Language selection",
161 "Select the language you wish to use for the " NAME
".", 50, 5, 5, 8,
162 langnames
, &choice
, "Ok", NULL
);
165 ctr
= langtrs
[choice
];
166 strcpy(shortlangname
, shortlangnames
[choice
]);
167 fprintf(flog
, "Selected language: %s\n", shortlangname
);
169 newtDrawRootText(14, 0, NAME
" " VERSION
" - " SLOGAN
);
170 newtPushHelpLine(ctr
[TR_HELPLINE
]);
171 sprintf (title
, "%s %s - %s", NAME
, VERSION
, SLOGAN
);
174 sprintf(message
, ctr
[TR_WELCOME
], NAME
);
175 newtWinMessage(title
, ctr
[TR_OK
], message
);
177 sprintf(message
, ctr
[TR_SELECT_INSTALLATION_MEDIA_LONG
], NAME
);
178 rc
= newtWinMenu(ctr
[TR_SELECT_INSTALLATION_MEDIA
], message
,
179 50, 5, 5, 6, installtypes
, &installtype
, ctr
[TR_OK
],
180 ctr
[TR_CANCEL
], NULL
);
183 installtype
= CDROM_INSTALL
;
189 // Starting hardware detection
190 runcommandwithstatus("/bin/probehw.sh", ctr
[TR_PROBING_HARDWARE
]);
191 runcommandwithstatus("/bin/probenic.sh install", ctr
[TR_PROBING_HARDWARE
]);
194 if (installtype
== CDROM_INSTALL
) {
195 switch (mysystem("/bin/mountsource.sh")) {
197 installtype
= CDROM_INSTALL
;
201 installtype
= DISK_INSTALL
;
204 errorbox(ctr
[TR_NO_CDROM
]);
208 /* read source drive letter */
209 if ((handle
= fopen("/tmp/source_device", "r")) == NULL
) {
210 errorbox(ctr
[TR_ERROR_PROBING_CDROM
]);
213 fgets(sourcedrive
, 5, handle
);
214 fprintf(flog
, "Source drive: %s\n", sourcedrive
);
218 /* Configure the network now! */
219 if (installtype
== URL_INSTALL
) {
220 /* Network driver and params. */
221 if (!(networkmenu(ethernetkv
))) {
222 errorbox(ctr
[TR_NETWORK_SETUP_FAILED
]);
226 /* Check for ipfire-<VERSION>.tbz2 */
227 if (checktarball(SNAME
"-" VERSION
".tbz2", ctr
[TR_ENTER_URL
])) {
228 errorbox(ctr
[TR_NO_IPCOP_TARBALL_FOUND
]);
236 fprintf(flog
, "Harddisk scan pass %i\n", i
);
238 rc
= mysystem("/bin/mountdest.sh");
239 fprintf(flog
, "RC %d\n", rc
);
241 if (rc
== 0) { // Found IDE disk
244 } else if (rc
== 1) { // Found SCSI/USB/SATA disk
247 } else { // No harddisk found
249 errorbox(ctr
[TR_NO_HARDDISK
]);
252 // Do this if the kudzu-scan fails...
253 runcommandwithstatus("/bin/probehw.sh deep-scan", ctr
[TR_PROBING_HARDWARE
]);
257 /* switch (mysystem("/bin/mountdest.sh")) {
258 case 0: // Found IDE disk
262 case 1: // Found SCSI disk
266 case 10: // No harddisk found
268 errorbox(ctr[TR_NO_HARDDISK]);
271 // Do this if the kudzu-scan fails...
272 runcommandwithstatus("/bin/probehw.sh deep-scan", ctr[TR_PROBING_HARDWARE]);
278 // Need to clean this up at some point
279 // scsi disk is sdb/sdc when sda/sdb is used for usb-key
280 // if scsi-disk is sdd or more, it is not discovered
281 // Support only 2 usb keys, none could be unplugged
282 if (checkusb("sdb") && try_scsi("sdc")) {
284 sprintf(harddrive, "sdc");
285 goto FOUND_DESTINATION;
287 if (checkusb("sda") && try_scsi("sdb")) {
289 sprintf(harddrive, "sdb");
290 goto FOUND_DESTINATION;
292 if (try_scsi("sda")) {
294 sprintf(harddrive, "sda");
295 goto FOUND_DESTINATION;
297 if (try_scsi("ida/c0d0")) {
299 sprintf(harddrive, "ida/c0d0");
300 goto FOUND_DESTINATION;
302 if (try_scsi("cciss/c0d0")) {
304 sprintf(harddrive, "cciss/c0d0");
305 goto FOUND_DESTINATION;
307 if (try_scsi("rd/c0d0")) {
309 sprintf(harddrive, "rd/c0d0");
310 goto FOUND_DESTINATION;
312 if (try_scsi("ataraid/d0")) {
314 sprintf(harddrive, "ataraid/d0");
315 goto FOUND_DESTINATION;
319 if ((handle
= fopen("/tmp/dest_device", "r")) == NULL
) {
320 errorbox(ctr
[TR_NO_HARDDISK
]);
323 fgets(harddrive
, 5, handle
);
326 /* load unattended configuration */
328 fprintf(flog
, "unattended: Reading unattended.conf\n");
330 (void) readkeyvalues(unattendedkv
, UNATTENDED_CONF
);
333 /* Make the hdparms struct and print the contents.
334 With USB-KEY install and SCSI disk, while installing, the disk
335 is named 'sdb,sdc,...' (following keys)
336 On reboot, it will become 'sda'
337 To avoid many test, all names are built in the struct.
339 sprintf(hdparams
.devnode_disk
, "/dev/%s", harddrive
);
340 /* Address the partition or raid partition (eg dev/sda or /dev/sdap1 */
341 sprintf(hdparams
.devnode_part
, "/dev/%s%s", harddrive
,raid_disk
? "p" : "");
342 /* Now the names after the machine is booted. Only scsi is affected
343 and we only install on the first scsi disk. */
345 strcpy(tmp
, scsi_disk
? "sda" : harddrive
);
346 sprintf(hdparams
.devnode_disk_run
, "/dev/%s", tmp
);
347 sprintf(hdparams
.devnode_part_run
, "/dev/%s%s", tmp
, raid_disk
? "p" : "");
350 fprintf(flog
, "Destination drive: %s\n", hdparams
.devnode_disk
);
352 sprintf(message
, ctr
[TR_PREPARE_HARDDISK
], hdparams
.devnode_disk
);
357 yesnoharddisk
[0] = ctr
[TR_NO
];
358 yesnoharddisk
[1] = ctr
[TR_YES
];
359 yesnoharddisk
[2] = NULL
;
362 rc
= newtWinMenu(title
, message
,
363 50, 5, 5, 6, yesnoharddisk
,
365 ctr
[TR_CANCEL
], NULL
);
372 /* Calculate amount of memory in machine */
373 if ((handle
= fopen("/proc/meminfo", "r")))
375 while (fgets(line
, STRING_SIZE
-1, handle
)) {
376 if (sscanf (line
, "MemTotal: %s kB", string
)) {
377 memory
= atoi(string
) / 1024 ;
383 /* Partition, mkswp, mkfs.
384 * before partitioning, first determine the sizes of each
385 * partition. In order to do that we need to know the size of
388 /* Don't use mysystem here so we can redirect output */
389 sprintf(commandstring
, "/bin/sfdisk -s /dev/%s > /tmp/disksize 2> /dev/null", harddrive
);
390 system(commandstring
);
392 /* Calculate amount of disk space */
393 if ((handle
= fopen("/tmp/disksize", "r")))
395 fgets(line
, STRING_SIZE
-1, handle
);
396 if (sscanf (line
, "%s", string
)) {
397 maximum_free
= atoi(string
) / 1024;
402 fprintf(flog
, "maximum_free = %ld, memory = %ld",
403 maximum_free
, memory
);
405 swap_file
= calc_swapsize(memory
, maximum_free
);
407 if (maximum_free
< 512 + swap_file
) {
408 if (maximum_free
< 512) {
409 errorbox(ctr
[TR_DISK_TOO_SMALL
]);
414 rc
= newtWinChoice(title
, ctr
[TR_OK
], ctr
[TR_CANCEL
], ctr
[TR_CONTINUE_NO_SWAP
]);
425 boot_partition
= 20; /* in MB */
426 current_free
= maximum_free
- boot_partition
- swap_file
;
428 root_partition
= 2048 ;
429 if (current_free
< 512) {
430 errorbox(ctr
[TR_DISK_TOO_SMALL
]);
434 current_free
= current_free
- root_partition
;
436 root_partition
= root_partition
+ swap_file
;
439 system_partition
= current_free
;
441 fprintf(flog
, "boot = %ld, swap = %ld, mylog = %ld, root = %ld\n",
442 boot_partition
, swap_file
, system_partition
, root_partition
);
444 handle
= fopen("/tmp/partitiontable", "w");
448 fprintf(handle
, ",%ld,L,*\n,%ld,S,\n,%ld,L,\n,,L,\n",
449 boot_partition
, swap_file
, root_partition
);
451 fprintf(handle
, ",%ld,L,*\n,0,0,\n,%ld,L,\n,,L,\n",
452 boot_partition
, root_partition
);
457 snprintf(commandstring
, STRING_SIZE
, "/bin/sfdisk -L -uM %s < /tmp/partitiontable", hdparams
.devnode_disk
);
458 if (runcommandwithstatus(commandstring
, ctr
[TR_PARTITIONING_DISK
]))
460 errorbox(ctr
[TR_UNABLE_TO_PARTITION
]);
464 mysystem("/sbin/udevstart");
466 snprintf(commandstring
, STRING_SIZE
, "/bin/mke2fs -T ext2 -c %s1", hdparams
.devnode_part
);
467 if (runcommandwithstatus(commandstring
, ctr
[TR_MAKING_BOOT_FILESYSTEM
]))
469 errorbox(ctr
[TR_UNABLE_TO_MAKE_BOOT_FILESYSTEM
]);
474 snprintf(commandstring
, STRING_SIZE
, "/sbin/mkswap %s2", hdparams
.devnode_part
);
475 if (runcommandwithstatus(commandstring
, ctr
[TR_MAKING_SWAPSPACE
]))
477 errorbox(ctr
[TR_UNABLE_TO_MAKE_SWAPSPACE
]);
482 snprintf(commandstring
, STRING_SIZE
, "/sbin/mkreiserfs -f %s3", hdparams
.devnode_part
);
483 if (runcommandwithstatus(commandstring
, ctr
[TR_MAKING_ROOT_FILESYSTEM
]))
485 errorbox(ctr
[TR_UNABLE_TO_MAKE_ROOT_FILESYSTEM
]);
489 snprintf(commandstring
, STRING_SIZE
, "/sbin/mkreiserfs -f %s4", hdparams
.devnode_part
);
490 if (runcommandwithstatus(commandstring
, ctr
[TR_MAKING_LOG_FILESYSTEM
]))
492 errorbox(ctr
[TR_UNABLE_TO_MAKE_ROOT_FILESYSTEM
]);
496 /* Mount harddisk. */
497 mysystem("/sbin/modprobe reiserfs"); // to be banished...
499 snprintf(commandstring
, STRING_SIZE
, "/bin/mount %s3 /harddisk", hdparams
.devnode_part
);
500 if (runcommandwithstatus(commandstring
, ctr
[TR_MOUNTING_ROOT_FILESYSTEM
]))
502 errorbox(ctr
[TR_UNABLE_TO_MOUNT_ROOT_FILESYSTEM
]);
506 mkdir("/harddisk/boot", S_IRWXU
|S_IRWXG
|S_IRWXO
);
507 mkdir("/harddisk/var", S_IRWXU
|S_IRWXG
|S_IRWXO
);
508 mkdir("/harddisk/var/log", S_IRWXU
|S_IRWXG
|S_IRWXO
);
510 snprintf(commandstring
, STRING_SIZE
, "/bin/mount %s1 /harddisk/boot", hdparams
.devnode_part
);
511 if (runcommandwithstatus(commandstring
, ctr
[TR_MOUNTING_BOOT_FILESYSTEM
]))
513 errorbox(ctr
[TR_UNABLE_TO_MOUNT_BOOT_FILESYSTEM
]);
517 snprintf(commandstring
, STRING_SIZE
, "/sbin/swapon %s2", hdparams
.devnode_part
);
518 if (runcommandwithstatus(commandstring
, ctr
[TR_MOUNTING_SWAP_PARTITION
]))
520 errorbox(ctr
[TR_UNABLE_TO_MOUNT_SWAP_PARTITION
]);
524 snprintf(commandstring
, STRING_SIZE
, "/bin/mount %s4 /harddisk/var", hdparams
.devnode_part
);
525 if (runcommandwithstatus(commandstring
, ctr
[TR_MOUNTING_LOG_FILESYSTEM
]))
527 errorbox(ctr
[TR_UNABLE_TO_MOUNT_LOG_FILESYSTEM
]);
531 if (installtype
== URL_INSTALL
) {
532 snprintf(commandstring
, STRING_SIZE
,
533 "/bin/wget -q -O - %s/" SNAME
"-" VERSION
".tbz2 | /bin/tar -C /harddisk -xvjf -", url
);
536 if (installtype
== CDROM_INSTALL
) {
537 snprintf(commandstring
, STRING_SIZE
,
538 "/bin/tar -C /harddisk -xvjf /cdrom/" SNAME
"-" VERSION
".tbz2");
541 if (runcommandwithprogress(60, 4, title
, commandstring
, INST_FILECOUNT
,
542 ctr
[TR_INSTALLING_FILES
]))
544 errorbox(ctr
[TR_UNABLE_TO_INSTALL_FILES
]);
548 /* Save USB controller type to modules.conf */
549 write_usb_modules_conf();
551 /* Save language und local settings */
552 write_lang_configs(shortlangname
);
554 /* touch the modules.dep files */
555 snprintf(commandstring
, STRING_SIZE
,
556 "/bin/touch /harddisk/lib/modules/%s-ipfire/modules.dep",
558 mysystem(commandstring
);
559 snprintf(commandstring
, STRING_SIZE
,
560 "/bin/touch /harddisk/lib/modules/%s-ipfire-smp/modules.dep",
562 mysystem(commandstring
);
565 rename ("/harddisk/bin/uname.bak", "/harddisk/bin/uname");
567 /* mount proc filesystem */
568 mysystem("mkdir /harddisk/proc");
569 mysystem("/bin/mount --bind /proc /harddisk/proc");
570 mysystem("/bin/mount --bind /dev /harddisk/dev");
571 mysystem("/bin/mount --bind /sys /harddisk/sys");
573 /* Build cache lang file */
574 snprintf(commandstring
, STRING_SIZE
, "/sbin/chroot /harddisk /usr/bin/perl -e \"require '" CONFIG_ROOT
"/lang.pl'; &Lang::BuildCacheLang\"");
575 if (runcommandwithstatus(commandstring
, ctr
[TR_INSTALLING_LANG_CACHE
]))
577 errorbox(ctr
[TR_UNABLE_TO_INSTALL_LANG_CACHE
]);
581 /* Update /etc/fstab */
582 replace("/harddisk/etc/fstab", "DEVICE", hdparams
.devnode_part_run
);
584 /* Going to make our initrd... */
585 snprintf(commandstring
, STRING_SIZE
, "/sbin/chroot /harddisk /sbin/mkinitcpio -v -g /boot/ipfirerd.img -k %s-ipfire", KERNEL_VERSION
);
586 runcommandwithstatus(commandstring
, ctr
[TR_BUILDING_INITRD
]);
587 snprintf(commandstring
, STRING_SIZE
, "/sbin/chroot /harddisk /sbin/mkinitcpio -v -g /boot/ipfirerd-smp.img -k %s-smp-ipfire", KERNEL_VERSION
);
588 runcommandwithstatus(commandstring
, ctr
[TR_BUILDING_INITRD
]);
590 sprintf(string
, "root=%s3", hdparams
.devnode_part_run
);
591 replace( "/harddisk/boot/grub/grub.conf", "root=ROOT", string
);
592 replace( "/harddisk/boot/grub/grubbatch", "DEVICE", hdparams
.devnode_disk
);
594 /* restore permissions */
595 chmod("/harddisk/boot/grub/grubbatch", S_IXUSR
| S_IRUSR
| S_IXGRP
| S_IRGRP
| S_IXOTH
| S_IROTH
);
597 snprintf(commandstring
, STRING_SIZE
,
598 "/sbin/chroot /harddisk /boot/grub/grubbatch");
599 if (runcommandwithstatus(commandstring
, ctr
[TR_INSTALLING_GRUB
])) {
600 errorbox(ctr
[TR_UNABLE_TO_INSTALL_GRUB
]);
604 /* Install bootsplash */
605 // mysystem("/bin/installbootsplash.sh"); We cannot use this at the moment, it conflicts with our initrds...
607 mysystem("ln -s grub.conf /harddisk/boot/grub/menu.lst");
610 sprintf(message
, ctr
[TR_CONGRATULATIONS_LONG
],
612 newtWinMessage(ctr
[TR_CONGRATULATIONS
], ctr
[TR_OK
], message
);
618 fprintf(flog
, "Install program ended.\n");
621 newtWinMessage(title
, ctr
[TR_OK
], ctr
[TR_PRESS_OK_TO_REBOOT
]);
623 freekeyvalues(ethernetkv
);
625 if (allok
&& !allok_fastexit
)
628 fprintf(flog
, "Entering unattended setup\n");
629 if (unattended_setup(unattendedkv
)) {
630 snprintf(commandstring
, STRING_SIZE
, "/bin/sleep 10");
631 runcommandwithstatus(commandstring
, "Unattended installation finished, system will reboot");
633 errorbox("Unattended setup failed.");
643 // Copy our scanned nics to the disk and lock because scan doesn't work in chroot
644 system("touch /harddisk/var/ipfire/ethernet/scan_lock");
645 system("cp -f /tmp/scanned_nics /harddisk/var/ipfire/ethernet/scanned_nics");
646 if (system("/sbin/chroot /harddisk /usr/local/sbin/setup /dev/tty2 INSTALL"))
647 printf("Unable to run setup.\n");
648 system("rm -f /harddisk/var/ipfire/ethernet/scan_lock");
651 if (system("/bin/umount /harddisk/proc"))
652 printf("Unable to umount /harddisk/proc.\n");
662 snprintf(commandstring
, STRING_SIZE
, "/bin/swapoff %s2", hdparams
.devnode_part
);
667 system("/bin/umount /harddisk/proc");
668 system("/bin/umount /harddisk/dev");
669 system("/bin/umount /harddisk/sys");
671 system("/bin/umount /harddisk/var");
672 system("/bin/umount /harddisk/boot");
673 system("/bin/umount /harddisk");