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
];
33 char line
[STRING_SIZE
];
36 if ((fd
= fopen("/proc/cpuinfo", "r")) == NULL
) {
39 while (fgets(line
, STRING_SIZE
, fd
) != NULL
) {
40 if (strstr(line
, "processor") == line
) {
45 return (cpu_count
> 1);
48 long calc_swapsize(long memory
, long disk
) {
59 int main(int argc
, char *argv
[])
61 char *langnames
[] = { "Deutsch", "English", NULL
};
62 char *shortlangnames
[] = { "de", "en", NULL
};
63 char **langtrs
[] = { de_tr
, en_tr
, NULL
};
65 char harddrive
[5], sourcedrive
[5]; /* Device holder. */
66 struct devparams hdparams
, cdromparams
; /* Params for CDROM and HD */
67 int cdmounted
= 0; /* Loop flag for inserting a cd. */
69 char commandstring
[STRING_SIZE
];
70 char *installtypes
[] = { "CDROM/USB", "HTTP/FTP", NULL
};
71 int installtype
= CDROM_INSTALL
;
73 char shortlangname
[10];
75 char title
[STRING_SIZE
];
78 struct keyvalue
*ethernetkv
= initkeyvalues();
79 FILE *handle
, *cmdfile
;
80 char line
[STRING_SIZE
];
81 char string
[STRING_SIZE
];
82 long maximum_free
= 0, current_free
;
84 long system_partition
, boot_partition
, root_partition
, swap_file
;
86 char *yesnoharddisk
[] = { "NO", "YES", NULL
};
88 struct keyvalue
*unattendedkv
= initkeyvalues();
91 setlocale (LC_ALL
, "");
92 sethostname( SNAME
, 10);
94 memset(&hdparams
, 0, sizeof(struct devparams
));
95 memset(&cdromparams
, 0, sizeof(struct devparams
));
97 /* Log file/terminal stuff. */
100 if (!(flog
= fopen(argv
[1], "w+")))
108 fprintf(flog
, "Install program started.\n");
113 /* Do usb detection first for usb keyboard */
114 if (! (cmdfile
= fopen("/proc/cmdline", "r")))
116 fprintf(flog
, "Couldn't open commandline: /proc/cmdline\n");
118 fgets(line
, STRING_SIZE
, cmdfile
);
119 if (strstr (line
, "nousb") == NULL
) {
120 fprintf(flog
, "Initializing USB controllers.\n");
123 fprintf(flog
, "Skipping USB detection.\n");
125 // check if we have to make an unattended install
126 if (strstr (line
, "unattended") != NULL
) {
132 runcommandwithstatus("/bin/sleep 10", "WARNING: Unattended installation will start in 10 seconds...");
135 /* German is the default */
136 for (choice
= 0; langnames
[choice
]; choice
++)
138 if (strcmp(langnames
[choice
], "Deutsch") == 0)
141 if (!langnames
[choice
])
145 rc
= newtWinMenu("Language selection",
146 "Select the language you wish to use for the " NAME
".", 50, 5, 5, 8,
147 langnames
, &choice
, "Ok", NULL
);
150 ctr
= langtrs
[choice
];
151 strcpy(shortlangname
, shortlangnames
[choice
]);
152 fprintf(flog
, "Selected language: %s\n", shortlangname
);
154 mysystem("/bin/setfont lat0-16");
156 newtDrawRootText(14, 0, NAME
" " VERSION
" - " SLOGAN
);
157 newtPushHelpLine(ctr
[TR_HELPLINE
]);
158 sprintf (title
, "%s %s - %s", NAME
, VERSION
, SLOGAN
);
161 sprintf(message
, ctr
[TR_WELCOME
], NAME
);
162 newtWinMessage(title
, ctr
[TR_OK
], message
);
164 sprintf(message
, ctr
[TR_SELECT_INSTALLATION_MEDIA_LONG
], NAME
);
165 rc
= newtWinMenu(ctr
[TR_SELECT_INSTALLATION_MEDIA
], message
,
166 50, 5, 5, 6, installtypes
, &installtype
, ctr
[TR_OK
],
167 ctr
[TR_CANCEL
], NULL
);
170 installtype
= CDROM_INSTALL
;
176 // Starting hardware detection
177 runcommandwithstatus("/bin/probehw.sh", ctr
[TR_PROBING_HARDWARE
]);
178 runcommandwithstatus("/bin/probenic.sh install", ctr
[TR_PROBING_HARDWARE
]);
181 if (installtype
== CDROM_INSTALL
) {
182 switch (mysystem("/bin/mountsource.sh")) {
184 installtype
= CDROM_INSTALL
;
188 installtype
= DISK_INSTALL
;
191 errorbox(ctr
[TR_NO_CDROM
]);
195 /* read source drive letter */
196 if ((handle
= fopen("/tmp/source_device", "r")) == NULL
) {
197 errorbox(ctr
[TR_ERROR_PROBING_CDROM
]);
200 fgets(sourcedrive
, 5, handle
);
201 fprintf(flog
, "Source drive: %s\n", sourcedrive
);
204 //snprintf(cdromparams.devnode_disk, STRING_SIZE, "/dev/%s", sourcedrive);
205 fprintf(flog
, "Source device: %s\n", sourcedrive
);
208 /* Configure the network now! */
209 if (installtype
== URL_INSTALL
) {
210 /* Network driver and params. */
211 if (!(networkmenu(ethernetkv
))) {
212 errorbox(ctr
[TR_NETWORK_SETUP_FAILED
]);
216 /* Check for ipfire-<VERSION>.tbz2 */
217 if (checktarball(SNAME
"-" VERSION
".tbz2", ctr
[TR_ENTER_URL
])) {
218 errorbox(ctr
[TR_NO_IPCOP_TARBALL_FOUND
]);
223 // Now try to find destination device...
224 if ((hdletter
= findidetype(IDE_HD
))) {
225 sprintf(harddrive
, "hd%c", hdletter
);
226 goto FOUND_DESTINATION
;
229 /* Need to clean this up at some point
230 scsi disk is sdb/sdc when sda/sdb is used for usb-key
231 if scsi-disk is sdd or more, it is not discovered
232 Support only 2 usb keys, none could be unplugged */
233 if (checkusb("sdb") && try_scsi("sdc")) {
235 sprintf(harddrive
, "sdc");
236 goto FOUND_DESTINATION
;
238 if (checkusb("sda") && try_scsi("sdb")) {
240 sprintf(harddrive
, "sdb");
241 goto FOUND_DESTINATION
;
243 if (try_scsi("sda")) {
245 sprintf(harddrive
, "sda");
246 goto FOUND_DESTINATION
;
248 if (try_scsi("ida/c0d0")) {
250 sprintf(harddrive
, "ida/c0d0");
251 goto FOUND_DESTINATION
;
253 if (try_scsi("cciss/c0d0")) {
255 sprintf(harddrive
, "cciss/c0d0");
256 goto FOUND_DESTINATION
;
258 if (try_scsi("rd/c0d0")) {
260 sprintf(harddrive
, "rd/c0d0");
261 goto FOUND_DESTINATION
;
263 if (try_scsi("ataraid/d0")) {
265 sprintf(harddrive
, "ataraid/d0");
266 goto FOUND_DESTINATION
;
268 /* nothing worked, give up */
269 errorbox(ctr
[TR_NO_HARDDISK
]);
273 /* load unattended configuration */
275 fprintf(flog
, "unattended: Reading unattended.conf\n");
277 (void) readkeyvalues(unattendedkv
, UNATTENDED_CONF
);
280 /* Make the hdparms struct and print the contents.
281 With USB-KEY install and SCSI disk, while installing, the disk
282 is named 'sdb,sdc,...' (following keys)
283 On reboot, it will become 'sda'
284 To avoid many test, all names are built in the struct.
286 sprintf(hdparams
.devnode_disk
, "/dev/%s", harddrive
);
287 /* Address the partition or raid partition (eg dev/sda or /dev/sdap1 */
288 sprintf(hdparams
.devnode_part
, "/dev/%s%s", harddrive
,raid_disk
? "p" : "");
289 /* Now the names after the machine is booted. Only scsi is affected
290 and we only install on the first scsi disk. */
292 strcpy(tmp
, scsi_disk
? "sda" : harddrive
);
293 sprintf(hdparams
.devnode_disk_run
, "/dev/%s", tmp
);
294 sprintf(hdparams
.devnode_part_run
, "/dev/%s%s", tmp
, raid_disk
? "p" : "");
297 fprintf(flog
, "Destination drive: %s\n", hdparams
.devnode_disk
);
299 sprintf(message
, ctr
[TR_PREPARE_HARDDISK
], hdparams
.devnode_disk
);
304 rc
= newtWinMenu(title
, message
,
305 50, 5, 5, 6, yesnoharddisk
,
307 ctr
[TR_CANCEL
], NULL
);
314 /* Calculate amount of memory in machine */
315 if ((handle
= fopen("/proc/meminfo", "r")))
317 while (fgets(line
, STRING_SIZE
-1, handle
)) {
318 if (sscanf (line
, "MemTotal: %s kB", string
)) {
319 memory
= atoi(string
) / 1024 ;
325 /* Partition, mkswp, mkfs.
326 * before partitioning, first determine the sizes of each
327 * partition. In order to do that we need to know the size of
330 /* Don't use mysystem here so we can redirect output */
331 sprintf(commandstring
, "/bin/sfdisk -s /dev/%s > /tmp/disksize 2> /dev/null", harddrive
);
332 system(commandstring
);
334 /* Calculate amount of disk space */
335 if ((handle
= fopen("/tmp/disksize", "r")))
337 fgets(line
, STRING_SIZE
-1, handle
);
338 if (sscanf (line
, "%s", string
)) {
339 maximum_free
= atoi(string
) / 1024;
344 fprintf(flog
, "maximum_free = %ld, memory = %ld",
345 maximum_free
, memory
);
347 swap_file
= calc_swapsize(memory
, maximum_free
);
349 if (maximum_free
< 512 + swap_file
) {
350 if (maximum_free
< 512) {
351 errorbox(ctr
[TR_DISK_TOO_SMALL
]);
356 rc
= newtWinChoice(title
, ctr
[TR_OK
], ctr
[TR_CANCEL
], ctr
[TR_CONTINUE_NO_SWAP
]);
367 boot_partition
= 20; /* in MB */
368 current_free
= maximum_free
- boot_partition
- swap_file
;
370 root_partition
= 2048 ;
371 if (current_free
< 512) {
372 errorbox(ctr
[TR_DISK_TOO_SMALL
]);
376 current_free
= current_free
- root_partition
;
378 root_partition
= root_partition
+ swap_file
;
381 system_partition
= current_free
;
383 fprintf(flog
, "boot = %ld, swap = %ld, mylog = %ld, root = %ld\n",
384 boot_partition
, swap_file
, system_partition
, root_partition
);
386 handle
= fopen("/tmp/partitiontable", "w");
390 fprintf(handle
, ",%ld,L,*\n,%ld,S,\n,%ld,L,\n,,L,\n",
391 boot_partition
, swap_file
, root_partition
);
393 fprintf(handle
, ",%ld,L,*\n,0,0,\n,%ld,L,\n,,L,\n",
394 boot_partition
, root_partition
);
399 snprintf(commandstring
, STRING_SIZE
, "/bin/sfdisk -L -uM %s < /tmp/partitiontable", hdparams
.devnode_disk
);
400 if (runcommandwithstatus(commandstring
, ctr
[TR_PARTITIONING_DISK
]))
402 errorbox(ctr
[TR_UNABLE_TO_PARTITION
]);
406 mysystem("/sbin/udevstart");
408 snprintf(commandstring
, STRING_SIZE
, "/bin/mke2fs -T ext2 -c %s1", hdparams
.devnode_part
);
409 if (runcommandwithstatus(commandstring
, ctr
[TR_MAKING_BOOT_FILESYSTEM
]))
411 errorbox(ctr
[TR_UNABLE_TO_MAKE_BOOT_FILESYSTEM
]);
416 snprintf(commandstring
, STRING_SIZE
, "/sbin/mkswap %s2", hdparams
.devnode_part
);
417 if (runcommandwithstatus(commandstring
, ctr
[TR_MAKING_SWAPSPACE
]))
419 errorbox(ctr
[TR_UNABLE_TO_MAKE_SWAPSPACE
]);
424 snprintf(commandstring
, STRING_SIZE
, "/sbin/mkreiserfs -f %s3", hdparams
.devnode_part
);
425 if (runcommandwithstatus(commandstring
, ctr
[TR_MAKING_ROOT_FILESYSTEM
]))
427 errorbox(ctr
[TR_UNABLE_TO_MAKE_ROOT_FILESYSTEM
]);
431 snprintf(commandstring
, STRING_SIZE
, "/sbin/mkreiserfs -f %s4", hdparams
.devnode_part
);
432 if (runcommandwithstatus(commandstring
, ctr
[TR_MAKING_LOG_FILESYSTEM
]))
434 errorbox(ctr
[TR_UNABLE_TO_MAKE_ROOT_FILESYSTEM
]);
438 /* Mount harddisk. */
440 snprintf(commandstring
, STRING_SIZE
, "/bin/mount %s3 /harddisk", hdparams
.devnode_part
);
441 if (runcommandwithstatus(commandstring
, ctr
[TR_MOUNTING_ROOT_FILESYSTEM
]))
443 errorbox(ctr
[TR_UNABLE_TO_MOUNT_ROOT_FILESYSTEM
]);
447 mkdir("/harddisk/boot", S_IRWXU
|S_IRWXG
|S_IRWXO
);
448 mkdir("/harddisk/var", S_IRWXU
|S_IRWXG
|S_IRWXO
);
449 mkdir("/harddisk/var/log", S_IRWXU
|S_IRWXG
|S_IRWXO
);
451 snprintf(commandstring
, STRING_SIZE
, "/bin/mount %s1 /harddisk/boot", hdparams
.devnode_part
);
452 if (runcommandwithstatus(commandstring
, ctr
[TR_MOUNTING_BOOT_FILESYSTEM
]))
454 errorbox(ctr
[TR_UNABLE_TO_MOUNT_BOOT_FILESYSTEM
]);
458 snprintf(commandstring
, STRING_SIZE
, "/sbin/swapon %s2", hdparams
.devnode_part
);
459 if (runcommandwithstatus(commandstring
, ctr
[TR_MOUNTING_SWAP_PARTITION
]))
461 errorbox(ctr
[TR_UNABLE_TO_MOUNT_SWAP_PARTITION
]);
465 snprintf(commandstring
, STRING_SIZE
, "/bin/mount %s4 /harddisk/var", hdparams
.devnode_part
);
466 if (runcommandwithstatus(commandstring
, ctr
[TR_MOUNTING_LOG_FILESYSTEM
]))
468 errorbox(ctr
[TR_UNABLE_TO_MOUNT_LOG_FILESYSTEM
]);
472 if (installtype
== URL_INSTALL
) {
473 snprintf(commandstring
, STRING_SIZE
,
474 "/bin/wget -q -O - %s/" SNAME
"-" VERSION
".tbz2 | /bin/tar -C /harddisk -xvjf -", url
);
477 if (installtype
== CDROM_INSTALL
) {
478 snprintf(commandstring
, STRING_SIZE
,
479 "/bin/tar -C /harddisk -xvjf /cdrom/" SNAME
"-" VERSION
".tbz2");
482 if (runcommandwithprogress(60, 4, title
, commandstring
, INST_FILECOUNT
,
483 ctr
[TR_INSTALLING_FILES
]))
485 errorbox(ctr
[TR_UNABLE_TO_INSTALL_FILES
]);
489 /* Save USB controller type to modules.conf */
490 write_usb_modules_conf();
492 /* Save language und local settings */
493 write_lang_configs(shortlangname
);
495 /* touch the modules.dep files */
496 snprintf(commandstring
, STRING_SIZE
,
497 "/bin/touch /harddisk/lib/modules/%s-ipfire/modules.dep",
499 mysystem(commandstring
);
500 snprintf(commandstring
, STRING_SIZE
,
501 "/bin/touch /harddisk/lib/modules/%s-ipfire-smp/modules.dep",
503 mysystem(commandstring
);
506 rename ("/harddisk/bin/uname.bak", "/harddisk/bin/uname");
508 /* mount proc filesystem */
509 mysystem("mkdir /harddisk/proc");
510 mysystem("/bin/mount -t proc none /harddisk/proc");
511 mysystem("/bin/mount --bind /dev /harddisk/dev");
513 /* Build cache lang file */
514 snprintf(commandstring
, STRING_SIZE
, "/sbin/chroot /harddisk /usr/bin/perl -e \"require '" CONFIG_ROOT
"/lang.pl'; &Lang::BuildCacheLang\"");
515 if (runcommandwithstatus(commandstring
, ctr
[TR_INSTALLING_LANG_CACHE
]))
517 errorbox(ctr
[TR_UNABLE_TO_INSTALL_LANG_CACHE
]);
521 /* Update /etc/fstab */
522 replace("/harddisk/etc/fstab", "DEVICE", hdparams
.devnode_part_run
);
524 /* if we detected SCSI/USB then fixup */
525 /* mysystem("/bin/probecntrl.sh");
526 if ((handle = fopen("/tmp/cntrldriver", "r")))
529 fgets(line, STRING_SIZE-1, handle);
531 line[strlen(line) - 1] = 0;
532 driver = strtok(line, ".");
533 if (strlen(driver) > 1) {
534 fprintf(flog, "Fixing up ipfirerd.img\n");
535 mkdir("/harddisk/initrd", S_IRWXU|S_IRWXG|S_IRWXO);
536 snprintf(commandstring, STRING_SIZE, "/sbin/chroot /harddisk /sbin/mkinitrd --with=scsi_mod %s --with=sd_mod --with=sr_mod /boot/ipfirerd.img %s-ipfire", driver, KERNEL_VERSION);
537 runcommandwithstatus(commandstring, ctr[TR_BUILDING_INITRD]);
538 snprintf(commandstring, STRING_SIZE, "/sbin/chroot /harddisk /sbin/mkinitrd --with=scsi_mod %s --with=sd_mod --with=sr_mod /boot/ipfirerd-smp.img %s-ipfire-smp", driver, KERNEL_VERSION);
539 runcommandwithstatus(commandstring, ctr[TR_BUILDING_INITRD]);
540 mysystem("/sbin/chroot /harddisk /bin/mv /boot/grub/scsigrub.conf /boot/grub/grub.conf");
544 sprintf(string
, "root=%s3", hdparams
.devnode_part_run
);
545 replace( "/harddisk/boot/grub/grub.conf", "root=ROOT", string
);
546 replace( "/harddisk/boot/grub/grubbatch", "DEVICE", hdparams
.devnode_disk
);
548 /* restore permissions */
549 chmod("/harddisk/boot/grub/grubbatch", S_IXUSR
| S_IRUSR
| S_IXGRP
| S_IRGRP
| S_IXOTH
| S_IROTH
);
551 snprintf(commandstring
, STRING_SIZE
,
552 "/sbin/chroot /harddisk /boot/grub/grubbatch");
553 if (runcommandwithstatus(commandstring
, ctr
[TR_INSTALLING_GRUB
])) {
554 errorbox(ctr
[TR_UNABLE_TO_INSTALL_GRUB
]);
558 /* Install bootsplash */
559 mysystem("/bin/installbootsplash.sh");
561 mysystem("ln -s grub.conf /harddisk/boot/grub/menu.lst");
562 mysystem("umount /harddisk/proc");
563 mysystem("umount /harddisk/dev");
566 sprintf(message
, ctr
[TR_CONGRATULATIONS_LONG
],
567 NAME
, SNAME
, SNAME
, NAME
, NAME
, NAME
);
568 newtWinMessage(ctr
[TR_CONGRATULATIONS
], ctr
[TR_OK
], message
);
574 fprintf(flog
, "Install program ended.\n");
577 newtWinMessage(title
, ctr
[TR_OK
], ctr
[TR_PRESS_OK_TO_REBOOT
]);
579 freekeyvalues(ethernetkv
);
581 if (allok
&& !allok_fastexit
)
583 /* /proc is needed by the module checker. We have to mount it
584 * so it can be seen by setup, which is run chrooted. */
585 if (system("/bin/mount proc -t proc /harddisk/proc"))
586 printf("Unable to mount proc in /harddisk.");
590 fprintf(flog
, "Entering unattended setup\n");
591 if (unattended_setup(unattendedkv
)) {
592 snprintf(commandstring
, STRING_SIZE
, "/bin/sleep 10");
593 runcommandwithstatus(commandstring
, "Unattended installation finished, system will reboot");
595 errorbox("Unattended setup failed.");
605 // Copy our scanned nics to the disk and lock because scan doesn't work in chroot
606 system("touch /harddisk/var/ipfire/ethernet/scan_lock");
607 system("cp -f /tmp/scanned_nics /harddisk/var/ipfire/ethernet/scanned_nics");
608 if (system("/sbin/chroot /harddisk /usr/local/sbin/setup /dev/tty2 INSTALL"))
609 printf("Unable to run setup.\n");
610 system("rm -f /harddisk/var/ipfire/ethernet/scan_lock");
613 if (system("/bin/umount /harddisk/proc"))
614 printf("Unable to umount /harddisk/proc.\n");
620 snprintf(commandstring
, STRING_SIZE
, "/bin/swapoff %s2", hdparams
.devnode_part
);
625 system("/bin/umount /harddisk/var");
626 system("/bin/umount /harddisk/boot");
627 system("/bin/umount /harddisk");