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
;
76 char shortlangname
[10];
78 char title
[STRING_SIZE
];
81 struct keyvalue
*ethernetkv
= initkeyvalues();
82 FILE *handle
, *cmdfile
;
83 char line
[STRING_SIZE
];
84 char string
[STRING_SIZE
];
85 long maximum_free
= 0, current_free
;
87 long system_partition
, boot_partition
, root_partition
, swap_file
;
89 char *yesnoharddisk
[3]; // char *yesnoharddisk = { "NO", "YES", NULL };
92 struct keyvalue
*unattendedkv
= initkeyvalues();
95 setlocale (LC_ALL
, "");
96 sethostname( SNAME
, 10);
98 memset(&hdparams
, 0, sizeof(struct devparams
));
99 memset(&cdromparams
, 0, sizeof(struct devparams
));
101 /* Log file/terminal stuff. */
104 if (!(flog
= fopen(argv
[1], "w+")))
112 fprintf(flog
, "Install program started.\n");
117 /* Do usb detection first for usb keyboard */
118 if (! (cmdfile
= fopen("/proc/cmdline", "r")))
120 fprintf(flog
, "Couldn't open commandline: /proc/cmdline\n");
122 fgets(line
, STRING_SIZE
, cmdfile
);
123 if (strstr (line
, "nousb") == NULL
) {
124 fprintf(flog
, "Initializing USB controllers.\n");
127 fprintf(flog
, "Skipping USB detection.\n");
129 // check if we have to make an unattended install
130 if (strstr (line
, "unattended") != NULL
) {
136 runcommandwithstatus("/bin/sleep 10", "WARNING: Unattended installation will start in 10 seconds...");
139 /* German is the default */
140 for (choice
= 0; langnames
[choice
]; choice
++)
142 if (strcmp(langnames
[choice
], "Deutsch") == 0)
145 if (!langnames
[choice
])
149 rc
= newtWinMenu("Language selection",
150 "Select the language you wish to use for the " NAME
".", 50, 5, 5, 8,
151 langnames
, &choice
, "Ok", NULL
);
154 ctr
= langtrs
[choice
];
155 strcpy(shortlangname
, shortlangnames
[choice
]);
156 fprintf(flog
, "Selected language: %s\n", shortlangname
);
158 mysystem("/bin/setfont lat0-16");
160 newtDrawRootText(14, 0, NAME
" " VERSION
" - " SLOGAN
);
161 newtPushHelpLine(ctr
[TR_HELPLINE
]);
162 sprintf (title
, "%s %s - %s", NAME
, VERSION
, SLOGAN
);
165 sprintf(message
, ctr
[TR_WELCOME
], NAME
);
166 newtWinMessage(title
, ctr
[TR_OK
], message
);
168 sprintf(message
, ctr
[TR_SELECT_INSTALLATION_MEDIA_LONG
], NAME
);
169 rc
= newtWinMenu(ctr
[TR_SELECT_INSTALLATION_MEDIA
], message
,
170 50, 5, 5, 6, installtypes
, &installtype
, ctr
[TR_OK
],
171 ctr
[TR_CANCEL
], NULL
);
174 installtype
= CDROM_INSTALL
;
180 // Starting hardware detection
181 runcommandwithstatus("/bin/probehw.sh", ctr
[TR_PROBING_HARDWARE
]);
182 runcommandwithstatus("/bin/probenic.sh install", ctr
[TR_PROBING_HARDWARE
]);
185 if (installtype
== CDROM_INSTALL
) {
186 switch (mysystem("/bin/mountsource.sh")) {
188 installtype
= CDROM_INSTALL
;
192 installtype
= DISK_INSTALL
;
195 errorbox(ctr
[TR_NO_CDROM
]);
199 /* read source drive letter */
200 if ((handle
= fopen("/tmp/source_device", "r")) == NULL
) {
201 errorbox(ctr
[TR_ERROR_PROBING_CDROM
]);
204 fgets(sourcedrive
, 5, handle
);
205 fprintf(flog
, "Source drive: %s\n", sourcedrive
);
208 //snprintf(cdromparams.devnode_disk, STRING_SIZE, "/dev/%s", sourcedrive);
209 fprintf(flog
, "Source device: %s\n", sourcedrive
);
212 /* Configure the network now! */
213 if (installtype
== URL_INSTALL
) {
214 /* Network driver and params. */
215 if (!(networkmenu(ethernetkv
))) {
216 errorbox(ctr
[TR_NETWORK_SETUP_FAILED
]);
220 /* Check for ipfire-<VERSION>.tbz2 */
221 if (checktarball(SNAME
"-" VERSION
".tbz2", ctr
[TR_ENTER_URL
])) {
222 errorbox(ctr
[TR_NO_IPCOP_TARBALL_FOUND
]);
227 // Now try to find destination device...
228 if ((hdletter
= findidetype(IDE_HD
))) {
229 sprintf(harddrive
, "hd%c", hdletter
);
230 goto FOUND_DESTINATION
;
233 /* Need to clean this up at some point
234 scsi disk is sdb/sdc when sda/sdb is used for usb-key
235 if scsi-disk is sdd or more, it is not discovered
236 Support only 2 usb keys, none could be unplugged */
237 if (checkusb("sdb") && try_scsi("sdc")) {
239 sprintf(harddrive
, "sdc");
240 goto FOUND_DESTINATION
;
242 if (checkusb("sda") && try_scsi("sdb")) {
244 sprintf(harddrive
, "sdb");
245 goto FOUND_DESTINATION
;
247 if (try_scsi("sda")) {
249 sprintf(harddrive
, "sda");
250 goto FOUND_DESTINATION
;
252 if (try_scsi("ida/c0d0")) {
254 sprintf(harddrive
, "ida/c0d0");
255 goto FOUND_DESTINATION
;
257 if (try_scsi("cciss/c0d0")) {
259 sprintf(harddrive
, "cciss/c0d0");
260 goto FOUND_DESTINATION
;
262 if (try_scsi("rd/c0d0")) {
264 sprintf(harddrive
, "rd/c0d0");
265 goto FOUND_DESTINATION
;
267 if (try_scsi("ataraid/d0")) {
269 sprintf(harddrive
, "ataraid/d0");
270 goto FOUND_DESTINATION
;
272 /* nothing worked, give up */
273 errorbox(ctr
[TR_NO_HARDDISK
]);
277 /* load unattended configuration */
279 fprintf(flog
, "unattended: Reading unattended.conf\n");
281 (void) readkeyvalues(unattendedkv
, UNATTENDED_CONF
);
284 /* Make the hdparms struct and print the contents.
285 With USB-KEY install and SCSI disk, while installing, the disk
286 is named 'sdb,sdc,...' (following keys)
287 On reboot, it will become 'sda'
288 To avoid many test, all names are built in the struct.
290 sprintf(hdparams
.devnode_disk
, "/dev/%s", harddrive
);
291 /* Address the partition or raid partition (eg dev/sda or /dev/sdap1 */
292 sprintf(hdparams
.devnode_part
, "/dev/%s%s", harddrive
,raid_disk
? "p" : "");
293 /* Now the names after the machine is booted. Only scsi is affected
294 and we only install on the first scsi disk. */
296 strcpy(tmp
, scsi_disk
? "sda" : harddrive
);
297 sprintf(hdparams
.devnode_disk_run
, "/dev/%s", tmp
);
298 sprintf(hdparams
.devnode_part_run
, "/dev/%s%s", tmp
, raid_disk
? "p" : "");
301 fprintf(flog
, "Destination drive: %s\n", hdparams
.devnode_disk
);
303 sprintf(message
, ctr
[TR_PREPARE_HARDDISK
], hdparams
.devnode_disk
);
308 yesnoharddisk
[0] = ctr
[TR_NO
];
309 yesnoharddisk
[1] = ctr
[TR_YES
];
310 yesnoharddisk
[2] = NULL
;
313 rc
= newtWinMenu(title
, message
,
314 50, 5, 5, 6, yesnoharddisk
,
316 ctr
[TR_CANCEL
], NULL
);
323 /* Calculate amount of memory in machine */
324 if ((handle
= fopen("/proc/meminfo", "r")))
326 while (fgets(line
, STRING_SIZE
-1, handle
)) {
327 if (sscanf (line
, "MemTotal: %s kB", string
)) {
328 memory
= atoi(string
) / 1024 ;
334 /* Partition, mkswp, mkfs.
335 * before partitioning, first determine the sizes of each
336 * partition. In order to do that we need to know the size of
339 /* Don't use mysystem here so we can redirect output */
340 sprintf(commandstring
, "/bin/sfdisk -s /dev/%s > /tmp/disksize 2> /dev/null", harddrive
);
341 system(commandstring
);
343 /* Calculate amount of disk space */
344 if ((handle
= fopen("/tmp/disksize", "r")))
346 fgets(line
, STRING_SIZE
-1, handle
);
347 if (sscanf (line
, "%s", string
)) {
348 maximum_free
= atoi(string
) / 1024;
353 fprintf(flog
, "maximum_free = %ld, memory = %ld",
354 maximum_free
, memory
);
356 swap_file
= calc_swapsize(memory
, maximum_free
);
358 if (maximum_free
< 512 + swap_file
) {
359 if (maximum_free
< 512) {
360 errorbox(ctr
[TR_DISK_TOO_SMALL
]);
365 rc
= newtWinChoice(title
, ctr
[TR_OK
], ctr
[TR_CANCEL
], ctr
[TR_CONTINUE_NO_SWAP
]);
376 boot_partition
= 20; /* in MB */
377 current_free
= maximum_free
- boot_partition
- swap_file
;
379 root_partition
= 2048 ;
380 if (current_free
< 512) {
381 errorbox(ctr
[TR_DISK_TOO_SMALL
]);
385 current_free
= current_free
- root_partition
;
387 root_partition
= root_partition
+ swap_file
;
390 system_partition
= current_free
;
392 fprintf(flog
, "boot = %ld, swap = %ld, mylog = %ld, root = %ld\n",
393 boot_partition
, swap_file
, system_partition
, root_partition
);
395 handle
= fopen("/tmp/partitiontable", "w");
399 fprintf(handle
, ",%ld,L,*\n,%ld,S,\n,%ld,L,\n,,L,\n",
400 boot_partition
, swap_file
, root_partition
);
402 fprintf(handle
, ",%ld,L,*\n,0,0,\n,%ld,L,\n,,L,\n",
403 boot_partition
, root_partition
);
408 snprintf(commandstring
, STRING_SIZE
, "/bin/sfdisk -L -uM %s < /tmp/partitiontable", hdparams
.devnode_disk
);
409 if (runcommandwithstatus(commandstring
, ctr
[TR_PARTITIONING_DISK
]))
411 errorbox(ctr
[TR_UNABLE_TO_PARTITION
]);
415 mysystem("/sbin/udevstart");
417 snprintf(commandstring
, STRING_SIZE
, "/bin/mke2fs -T ext2 -c %s1", hdparams
.devnode_part
);
418 if (runcommandwithstatus(commandstring
, ctr
[TR_MAKING_BOOT_FILESYSTEM
]))
420 errorbox(ctr
[TR_UNABLE_TO_MAKE_BOOT_FILESYSTEM
]);
425 snprintf(commandstring
, STRING_SIZE
, "/sbin/mkswap %s2", hdparams
.devnode_part
);
426 if (runcommandwithstatus(commandstring
, ctr
[TR_MAKING_SWAPSPACE
]))
428 errorbox(ctr
[TR_UNABLE_TO_MAKE_SWAPSPACE
]);
433 snprintf(commandstring
, STRING_SIZE
, "/sbin/mkreiserfs -f %s3", hdparams
.devnode_part
);
434 if (runcommandwithstatus(commandstring
, ctr
[TR_MAKING_ROOT_FILESYSTEM
]))
436 errorbox(ctr
[TR_UNABLE_TO_MAKE_ROOT_FILESYSTEM
]);
440 snprintf(commandstring
, STRING_SIZE
, "/sbin/mkreiserfs -f %s4", hdparams
.devnode_part
);
441 if (runcommandwithstatus(commandstring
, ctr
[TR_MAKING_LOG_FILESYSTEM
]))
443 errorbox(ctr
[TR_UNABLE_TO_MAKE_ROOT_FILESYSTEM
]);
447 /* Mount harddisk. */
449 snprintf(commandstring
, STRING_SIZE
, "/bin/mount %s3 /harddisk", hdparams
.devnode_part
);
450 if (runcommandwithstatus(commandstring
, ctr
[TR_MOUNTING_ROOT_FILESYSTEM
]))
452 errorbox(ctr
[TR_UNABLE_TO_MOUNT_ROOT_FILESYSTEM
]);
456 mkdir("/harddisk/boot", S_IRWXU
|S_IRWXG
|S_IRWXO
);
457 mkdir("/harddisk/var", S_IRWXU
|S_IRWXG
|S_IRWXO
);
458 mkdir("/harddisk/var/log", S_IRWXU
|S_IRWXG
|S_IRWXO
);
460 snprintf(commandstring
, STRING_SIZE
, "/bin/mount %s1 /harddisk/boot", hdparams
.devnode_part
);
461 if (runcommandwithstatus(commandstring
, ctr
[TR_MOUNTING_BOOT_FILESYSTEM
]))
463 errorbox(ctr
[TR_UNABLE_TO_MOUNT_BOOT_FILESYSTEM
]);
467 snprintf(commandstring
, STRING_SIZE
, "/sbin/swapon %s2", hdparams
.devnode_part
);
468 if (runcommandwithstatus(commandstring
, ctr
[TR_MOUNTING_SWAP_PARTITION
]))
470 errorbox(ctr
[TR_UNABLE_TO_MOUNT_SWAP_PARTITION
]);
474 snprintf(commandstring
, STRING_SIZE
, "/bin/mount %s4 /harddisk/var", hdparams
.devnode_part
);
475 if (runcommandwithstatus(commandstring
, ctr
[TR_MOUNTING_LOG_FILESYSTEM
]))
477 errorbox(ctr
[TR_UNABLE_TO_MOUNT_LOG_FILESYSTEM
]);
481 if (installtype
== URL_INSTALL
) {
482 snprintf(commandstring
, STRING_SIZE
,
483 "/bin/wget -q -O - %s/" SNAME
"-" VERSION
".tbz2 | /bin/tar -C /harddisk -xvjf -", url
);
486 if (installtype
== CDROM_INSTALL
) {
487 snprintf(commandstring
, STRING_SIZE
,
488 "/bin/tar -C /harddisk -xvjf /cdrom/" SNAME
"-" VERSION
".tbz2");
491 if (runcommandwithprogress(60, 4, title
, commandstring
, INST_FILECOUNT
,
492 ctr
[TR_INSTALLING_FILES
]))
494 errorbox(ctr
[TR_UNABLE_TO_INSTALL_FILES
]);
498 /* Save USB controller type to modules.conf */
499 write_usb_modules_conf();
501 /* Save language und local settings */
502 write_lang_configs(shortlangname
);
504 /* touch the modules.dep files */
505 snprintf(commandstring
, STRING_SIZE
,
506 "/bin/touch /harddisk/lib/modules/%s-ipfire/modules.dep",
508 mysystem(commandstring
);
509 snprintf(commandstring
, STRING_SIZE
,
510 "/bin/touch /harddisk/lib/modules/%s-ipfire-smp/modules.dep",
512 mysystem(commandstring
);
515 rename ("/harddisk/bin/uname.bak", "/harddisk/bin/uname");
517 /* mount proc filesystem */
518 mysystem("mkdir /harddisk/proc");
519 mysystem("/bin/mount -t proc none /harddisk/proc");
520 mysystem("/bin/mount --bind /dev /harddisk/dev");
522 /* Build cache lang file */
523 snprintf(commandstring
, STRING_SIZE
, "/sbin/chroot /harddisk /usr/bin/perl -e \"require '" CONFIG_ROOT
"/lang.pl'; &Lang::BuildCacheLang\"");
524 if (runcommandwithstatus(commandstring
, ctr
[TR_INSTALLING_LANG_CACHE
]))
526 errorbox(ctr
[TR_UNABLE_TO_INSTALL_LANG_CACHE
]);
530 /* Update /etc/fstab */
531 replace("/harddisk/etc/fstab", "DEVICE", hdparams
.devnode_part_run
);
533 /* if we detected SCSI/USB then fixup */
534 /* mysystem("/bin/probecntrl.sh");
535 if ((handle = fopen("/tmp/cntrldriver", "r")))
538 fgets(line, STRING_SIZE-1, handle);
540 line[strlen(line) - 1] = 0;
541 driver = strtok(line, ".");
542 if (strlen(driver) > 1) {
543 fprintf(flog, "Fixing up ipfirerd.img\n");
544 mkdir("/harddisk/initrd", S_IRWXU|S_IRWXG|S_IRWXO);
545 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);
546 runcommandwithstatus(commandstring, ctr[TR_BUILDING_INITRD]);
547 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);
548 runcommandwithstatus(commandstring, ctr[TR_BUILDING_INITRD]);
549 mysystem("/sbin/chroot /harddisk /bin/mv /boot/grub/scsigrub.conf /boot/grub/grub.conf");
553 sprintf(string
, "root=%s3", hdparams
.devnode_part_run
);
554 replace( "/harddisk/boot/grub/grub.conf", "root=ROOT", string
);
555 replace( "/harddisk/boot/grub/grubbatch", "DEVICE", hdparams
.devnode_disk
);
557 /* restore permissions */
558 chmod("/harddisk/boot/grub/grubbatch", S_IXUSR
| S_IRUSR
| S_IXGRP
| S_IRGRP
| S_IXOTH
| S_IROTH
);
560 snprintf(commandstring
, STRING_SIZE
,
561 "/sbin/chroot /harddisk /boot/grub/grubbatch");
562 if (runcommandwithstatus(commandstring
, ctr
[TR_INSTALLING_GRUB
])) {
563 errorbox(ctr
[TR_UNABLE_TO_INSTALL_GRUB
]);
567 /* Install bootsplash */
568 mysystem("/bin/installbootsplash.sh");
570 mysystem("ln -s grub.conf /harddisk/boot/grub/menu.lst");
571 // mysystem("umount /harddisk/proc");
572 // mysystem("umount /harddisk/dev");
575 sprintf(message
, ctr
[TR_CONGRATULATIONS_LONG
],
576 NAME
, SNAME
, SNAME
, NAME
, NAME
, NAME
);
577 newtWinMessage(ctr
[TR_CONGRATULATIONS
], ctr
[TR_OK
], message
);
583 fprintf(flog
, "Install program ended.\n");
588 newtWinMessage(title
, ctr
[TR_OK
], ctr
[TR_PRESS_OK_TO_REBOOT
]);
590 freekeyvalues(ethernetkv
);
592 if (allok
&& !allok_fastexit
)
594 /* /proc is needed by the module checker. We have to mount it
595 * so it can be seen by setup, which is run chrooted. */
596 // if (system("/bin/mount proc -t proc /harddisk/proc"))
597 // printf("Unable to mount proc in /harddisk.");
601 fprintf(flog
, "Entering unattended setup\n");
602 if (unattended_setup(unattendedkv
)) {
603 snprintf(commandstring
, STRING_SIZE
, "/bin/sleep 10");
604 runcommandwithstatus(commandstring
, "Unattended installation finished, system will reboot");
606 errorbox("Unattended setup failed.");
616 // Copy our scanned nics to the disk and lock because scan doesn't work in chroot
617 system("touch /harddisk/var/ipfire/ethernet/scan_lock");
618 system("cp -f /tmp/scanned_nics /harddisk/var/ipfire/ethernet/scanned_nics");
619 if (system("/sbin/chroot /harddisk /usr/local/sbin/setup /dev/tty2 INSTALL"))
620 printf("Unable to run setup.\n");
621 system("rm -f /harddisk/var/ipfire/ethernet/scan_lock");
624 if (system("/bin/umount /harddisk/proc"))
625 printf("Unable to umount /harddisk/proc.\n");
636 snprintf(commandstring
, STRING_SIZE
, "/bin/swapoff %s2", hdparams
.devnode_part
);
641 system("/bin/umount /harddisk/proc");
642 system("/bin/umount /harddisk/dev");
644 system("/bin/umount /harddisk/var");
645 system("/bin/umount /harddisk/boot");
646 system("/bin/umount /harddisk");