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"
29 extern char url
[STRING_SIZE
];
31 struct nic nics
[20] = { { "" , "" , "" } }; // only defined for compile
32 struct knic knics
[20] = { { "" , "" , "" , "" } }; // only defined for compile
39 char line
[STRING_SIZE
];
42 if ((fd
= fopen("/proc/cpuinfo", "r")) == NULL
) {
45 while (fgets(line
, STRING_SIZE
, fd
) != NULL
) {
46 if (strstr(line
, "processor") == line
) {
51 return (cpu_count
> 1);
54 long calc_swapsize(long memory
, long disk
) {
65 long calc_rootsize(long free
, long max
) {
78 int main(int argc
, char *argv
[])
80 char *langnames
[] = { "Deutsch", "English", NULL
};
81 char *shortlangnames
[] = { "de", "en", NULL
};
82 char **langtrs
[] = { de_tr
, en_tr
, NULL
};
84 char harddrive
[11], sourcedrive
[5]; /* Device holder. */
85 struct devparams hdparams
, cdromparams
; /* Params for CDROM and HD */
86 int cdmounted
= 0; /* Loop flag for inserting a cd. */
88 char commandstring
[STRING_SIZE
];
89 char *installtypes
[] = { "CDROM/USB", "HTTP/FTP", NULL
};
90 int installtype
= CDROM_INSTALL
;
91 char mkfscommand
[STRING_SIZE
];
92 char *fstypes
[] = { "Reiser4", "ReiserFS", "ext3", NULL
};
98 char shortlangname
[10];
100 char title
[STRING_SIZE
];
102 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
264 case 1: // Found SCSI disk
269 case 2: // Found RAID disk
274 case 10: // No harddisk found
276 errorbox(ctr
[TR_NO_HARDDISK
]);
279 // Do this if the kudzu-scan fails...
280 runcommandwithstatus("/bin/probehw.sh deep-scan", ctr
[TR_PROBING_HARDWARE
]);
285 if ((handle
= fopen("/tmp/dest_device", "r")) == NULL
) {
286 errorbox(ctr
[TR_NO_HARDDISK
]);
289 fgets(harddrive
, 11, handle
);
292 /* load unattended configuration */
294 fprintf(flog
, "unattended: Reading unattended.conf\n");
296 (void) readkeyvalues(unattendedkv
, UNATTENDED_CONF
);
299 /* Make the hdparms struct and print the contents.
300 With USB-KEY install and SCSI disk, while installing, the disk
301 is named 'sdb,sdc,...' (following keys)
302 On reboot, it will become 'sda'
303 To avoid many test, all names are built in the struct.
305 sprintf(hdparams
.devnode_disk
, "/dev/%s", harddrive
);
306 /* Address the partition or raid partition (eg dev/sda or /dev/sdap1 */
307 sprintf(hdparams
.devnode_part
, "/dev/%s%s", harddrive
,raid_disk
? "p" : "");
308 /* Now the names after the machine is booted. Only scsi is affected
309 and we only install on the first scsi disk. */
311 strcpy(tmp
, scsi_disk
? "sda" : harddrive
);
312 sprintf(hdparams
.devnode_disk_run
, "/dev/%s", tmp
);
313 sprintf(hdparams
.devnode_part_run
, "/dev/%s%s", tmp
, raid_disk
? "p" : "");
316 fprintf(flog
, "Destination drive: %s\n", hdparams
.devnode_disk
);
318 sprintf(message
, ctr
[TR_PREPARE_HARDDISK
], hdparams
.devnode_disk
);
323 yesnoharddisk
[0] = ctr
[TR_NO
];
324 yesnoharddisk
[1] = ctr
[TR_YES
];
325 yesnoharddisk
[2] = NULL
;
328 rc
= newtWinMenu(title
, message
,
329 50, 5, 5, 6, yesnoharddisk
,
331 ctr
[TR_CANCEL
], NULL
);
339 sprintf(message
, "(TR) Bitte waehlen Sie ihr Dateisystem aus:");
340 rc
= newtWinMenu("(TR) Dateisystemauswahl", message
,
341 50, 5, 5, 6, fstypes
, &fstype
, ctr
[TR_OK
],
342 ctr
[TR_CANCEL
], NULL
);
345 fstype
= REISER4
; // Reiser4 is our standard filesystem. Love it or shut up!
350 /* Calculate amount of memory in machine */
351 if ((handle
= fopen("/proc/meminfo", "r")))
353 while (fgets(line
, STRING_SIZE
-1, handle
)) {
354 if (sscanf (line
, "MemTotal: %s kB", string
)) {
355 memory
= atoi(string
) / 1024 ;
361 /* Partition, mkswp, mkfs.
362 * before partitioning, first determine the sizes of each
363 * partition. In order to do that we need to know the size of
366 /* Don't use mysystem here so we can redirect output */
367 sprintf(commandstring
, "/bin/sfdisk -s /dev/%s > /tmp/disksize 2> /dev/null", harddrive
);
368 system(commandstring
);
370 /* Calculate amount of disk space */
371 if ((handle
= fopen("/tmp/disksize", "r"))) {
372 fgets(line
, STRING_SIZE
-1, handle
);
373 if (sscanf (line
, "%s", string
)) {
374 maximum_free
= atoi(string
) / 1024;
379 fprintf(flog
, "maximum_free = %ld, memory = %ld", maximum_free
, memory
);
381 swap_file
= calc_swapsize(memory
, maximum_free
);
383 if (maximum_free
< 768 + swap_file
) {
384 if (maximum_free
< 768) {
385 errorbox(ctr
[TR_DISK_TOO_SMALL
]);
390 rc
= newtWinChoice(title
, ctr
[TR_OK
], ctr
[TR_CANCEL
], ctr
[TR_CONTINUE_NO_SWAP
]);
401 boot_partition
= 20; /* in MB */
402 current_free
= maximum_free
- boot_partition
- swap_file
;
404 if (current_free
< 768) {
405 errorbox(ctr
[TR_DISK_TOO_SMALL
]);
409 root_partition
= calc_rootsize(current_free
, maximum_free
);
411 if (root_partition
== 0) {
412 errorbox(ctr
[TR_DISK_TOO_SMALL
]);
415 current_free
= current_free
- root_partition
;
418 if (current_free
< 256) {
419 errorbox(ctr
[TR_DISK_TOO_SMALL
]);
423 system_partition
= current_free
;
425 fprintf(flog
, "boot = %ld, swap = %ld, mylog = %ld, root = %ld\n",
426 boot_partition
, swap_file
, system_partition
, root_partition
);
428 handle
= fopen("/tmp/partitiontable", "w");
432 fprintf(handle
, ",%ld,L,*\n,%ld,S,\n,%ld,L,\n,,L,\n",
433 boot_partition
, swap_file
, root_partition
);
435 fprintf(handle
, ",%ld,L,*\n,0,0,\n,%ld,L,\n,,L,\n",
436 boot_partition
, root_partition
);
441 snprintf(commandstring
, STRING_SIZE
, "/bin/sfdisk -L -uM %s < /tmp/partitiontable", hdparams
.devnode_disk
);
442 if (runcommandwithstatus(commandstring
, ctr
[TR_PARTITIONING_DISK
]))
444 errorbox(ctr
[TR_UNABLE_TO_PARTITION
]);
448 if (fstype
== REISER4
) {
449 mysystem("/sbin/modprobe reiser4");
450 sprintf(mkfscommand
, "/sbin/mkfs.reiser4 -y");
451 } else if (fstype
== REISERFS
) {
452 mysystem("/sbin/modprobe reiserfs");
453 sprintf(mkfscommand
, "/sbin/mkreiserfs -f");
454 } else if (fstype
== EXT3
) {
455 mysystem("/sbin/modprobe ext3");
456 sprintf(mkfscommand
, "/bin/mke2fs -T ext3 -c");
459 snprintf(commandstring
, STRING_SIZE
, "/bin/mke2fs -T ext2 -c %s1", hdparams
.devnode_part
);
460 if (runcommandwithstatus(commandstring
, ctr
[TR_MAKING_BOOT_FILESYSTEM
]))
462 errorbox(ctr
[TR_UNABLE_TO_MAKE_BOOT_FILESYSTEM
]);
467 snprintf(commandstring
, STRING_SIZE
, "/sbin/mkswap %s2", hdparams
.devnode_part
);
468 if (runcommandwithstatus(commandstring
, ctr
[TR_MAKING_SWAPSPACE
]))
470 errorbox(ctr
[TR_UNABLE_TO_MAKE_SWAPSPACE
]);
475 snprintf(commandstring
, STRING_SIZE
, "%s %s3", mkfscommand
, hdparams
.devnode_part
);
476 if (runcommandwithstatus(commandstring
, ctr
[TR_MAKING_ROOT_FILESYSTEM
]))
478 errorbox(ctr
[TR_UNABLE_TO_MAKE_ROOT_FILESYSTEM
]);
482 snprintf(commandstring
, STRING_SIZE
, "%s %s4", mkfscommand
, hdparams
.devnode_part
);
483 if (runcommandwithstatus(commandstring
, ctr
[TR_MAKING_LOG_FILESYSTEM
]))
485 errorbox(ctr
[TR_UNABLE_TO_MAKE_LOG_FILESYSTEM
]);
489 snprintf(commandstring
, STRING_SIZE
, "/bin/mount %s3 /harddisk", hdparams
.devnode_part
);
490 if (runcommandwithstatus(commandstring
, ctr
[TR_MOUNTING_ROOT_FILESYSTEM
]))
492 errorbox(ctr
[TR_UNABLE_TO_MOUNT_ROOT_FILESYSTEM
]);
496 mkdir("/harddisk/boot", S_IRWXU
|S_IRWXG
|S_IRWXO
);
497 mkdir("/harddisk/var", S_IRWXU
|S_IRWXG
|S_IRWXO
);
498 mkdir("/harddisk/var/log", S_IRWXU
|S_IRWXG
|S_IRWXO
);
500 snprintf(commandstring
, STRING_SIZE
, "/bin/mount %s1 /harddisk/boot", hdparams
.devnode_part
);
501 if (runcommandwithstatus(commandstring
, ctr
[TR_MOUNTING_BOOT_FILESYSTEM
]))
503 errorbox(ctr
[TR_UNABLE_TO_MOUNT_BOOT_FILESYSTEM
]);
507 snprintf(commandstring
, STRING_SIZE
, "/sbin/swapon %s2", hdparams
.devnode_part
);
508 if (runcommandwithstatus(commandstring
, ctr
[TR_MOUNTING_SWAP_PARTITION
]))
510 errorbox(ctr
[TR_UNABLE_TO_MOUNT_SWAP_PARTITION
]);
514 snprintf(commandstring
, STRING_SIZE
, "/bin/mount %s4 /harddisk/var", hdparams
.devnode_part
);
515 if (runcommandwithstatus(commandstring
, ctr
[TR_MOUNTING_LOG_FILESYSTEM
]))
517 errorbox(ctr
[TR_UNABLE_TO_MOUNT_LOG_FILESYSTEM
]);
521 if (installtype
== URL_INSTALL
) {
522 snprintf(commandstring
, STRING_SIZE
,
523 "/bin/wget -q -O - %s/" SNAME
"-" VERSION
".tbz2 | /bin/tar -C /harddisk -xvjf -", url
);
526 if (installtype
== CDROM_INSTALL
) {
527 snprintf(commandstring
, STRING_SIZE
,
528 "/bin/tar -C /harddisk -xvjf /cdrom/" SNAME
"-" VERSION
".tbz2");
531 if (runcommandwithprogress(60, 4, title
, commandstring
, INST_FILECOUNT
,
532 ctr
[TR_INSTALLING_FILES
]))
534 errorbox(ctr
[TR_UNABLE_TO_INSTALL_FILES
]);
538 /* Save USB controller type to modules.conf */
539 write_usb_modules_conf();
541 /* Save language und local settings */
542 write_lang_configs(shortlangname
);
544 /* touch the modules.dep files */
545 snprintf(commandstring
, STRING_SIZE
,
546 "/bin/touch /harddisk/lib/modules/%s-ipfire/modules.dep",
548 mysystem(commandstring
);
549 snprintf(commandstring
, STRING_SIZE
,
550 "/bin/touch /harddisk/lib/modules/%s-ipfire-smp/modules.dep",
552 mysystem(commandstring
);
555 rename ("/harddisk/bin/uname.bak", "/harddisk/bin/uname");
557 /* mount proc filesystem */
558 mysystem("mkdir /harddisk/proc");
559 mysystem("/bin/mount --bind /proc /harddisk/proc");
560 mysystem("/bin/mount --bind /dev /harddisk/dev");
561 mysystem("/bin/mount --bind /sys /harddisk/sys");
563 /* Build cache lang file */
564 snprintf(commandstring
, STRING_SIZE
, "/sbin/chroot /harddisk /usr/bin/perl -e \"require '" CONFIG_ROOT
"/lang.pl'; &Lang::BuildCacheLang\"");
565 if (runcommandwithstatus(commandstring
, ctr
[TR_INSTALLING_LANG_CACHE
]))
567 errorbox(ctr
[TR_UNABLE_TO_INSTALL_LANG_CACHE
]);
571 /* Update /etc/fstab */
572 replace("/harddisk/etc/fstab", "DEVICE", hdparams
.devnode_part_run
);
574 if (fstype
== REISER4
) {
575 replace("/harddisk/etc/fstab", "FSTYPE", "reiser4");
576 replace("/harddisk/etc/mkinitcpio.conf", "MODULES=\"", "MODULES=\"reiser4 ");
577 replace("/harddisk/boot/grub/grub.conf", "MOUNT", "rw");
578 } else if (fstype
== REISERFS
) {
579 replace("/harddisk/etc/fstab", "FSTYPE", "reiserfs");
580 replace("/harddisk/boot/grub/grub.conf", "MOUNT", "ro");
581 } else if (fstype
== EXT3
) {
582 replace("/harddisk/etc/fstab", "FSTYPE", "ext3");
583 replace("/harddisk/boot/grub/grub.conf", "MOUNT", "ro");
586 /* Going to make our initrd... */
587 snprintf(commandstring
, STRING_SIZE
, "/sbin/chroot /harddisk /sbin/mkinitcpio -v -g /boot/ipfirerd.img -k %s-ipfire", KERNEL_VERSION
);
588 runcommandwithstatus(commandstring
, ctr
[TR_BUILDING_INITRD
]);
589 snprintf(commandstring
, STRING_SIZE
, "/sbin/chroot /harddisk /sbin/mkinitcpio -v -g /boot/ipfirerd-smp.img -k %s-ipfire-smp", KERNEL_VERSION
);
590 runcommandwithstatus(commandstring
, ctr
[TR_BUILDING_INITRD
]);
592 sprintf(string
, "root=%s3", hdparams
.devnode_part_run
);
593 replace( "/harddisk/boot/grub/grub.conf", "root=ROOT", string
);
594 replace( "/harddisk/boot/grub/grubbatch", "DEVICE", hdparams
.devnode_disk
);
596 /* restore permissions */
597 chmod("/harddisk/boot/grub/grubbatch", S_IXUSR
| S_IRUSR
| S_IXGRP
| S_IRGRP
| S_IXOTH
| S_IROTH
);
599 snprintf(commandstring
, STRING_SIZE
,
600 "/sbin/chroot /harddisk /boot/grub/grubbatch");
601 if (runcommandwithstatus(commandstring
, ctr
[TR_INSTALLING_GRUB
])) {
602 errorbox(ctr
[TR_UNABLE_TO_INSTALL_GRUB
]);
606 mysystem("ln -s grub.conf /harddisk/boot/grub/menu.lst");
608 mysystem("umount /cdrom");
609 ejectcdrom(sourcedrive
);
612 sprintf(message
, ctr
[TR_CONGRATULATIONS_LONG
],
614 newtWinMessage(ctr
[TR_CONGRATULATIONS
], ctr
[TR_OK
], message
);
620 fprintf(flog
, "Install program ended.\n");
623 newtWinMessage(title
, ctr
[TR_OK
], ctr
[TR_PRESS_OK_TO_REBOOT
]);
625 freekeyvalues(ethernetkv
);
627 if (allok
&& !allok_fastexit
)
630 fprintf(flog
, "Entering unattended setup\n");
631 if (unattended_setup(unattendedkv
)) {
632 snprintf(commandstring
, STRING_SIZE
, "/bin/sleep 10");
633 runcommandwithstatus(commandstring
, "Unattended installation finished, system will reboot");
635 errorbox("Unattended setup failed.");
645 // Copy our scanned nics to the disk and lock because scan doesn't work in chroot
646 system("touch /harddisk/var/ipfire/ethernet/scan_lock");
647 system("cp -f /tmp/scanned_nics /harddisk/var/ipfire/ethernet/scanned_nics");
648 if (system("/sbin/chroot /harddisk /usr/local/sbin/setup /dev/tty2 INSTALL"))
649 printf("Unable to run setup.\n");
650 system("rm -f /harddisk/var/ipfire/ethernet/scan_lock");
653 if (system("/bin/umount /harddisk/proc"))
654 printf("Unable to umount /harddisk/proc.\n");
664 snprintf(commandstring
, STRING_SIZE
, "/bin/swapoff %s2", hdparams
.devnode_part
);
669 system("/bin/umount /harddisk/proc");
670 system("/bin/umount /harddisk/dev");
671 system("/bin/umount /harddisk/sys");
673 system("/bin/umount /harddisk/var");
674 system("/bin/umount /harddisk/boot");
675 system("/bin/umount /harddisk");