2 /* SmoothWall install program.
4 * This program is distributed under the terms of the GNU General Public
5 * Licence. See the file COPYING for details.
7 * (c) Lawrence Manning, 2001
8 * Contains main entry point, and misc functions.6
15 #define INST_FILECOUNT 21000
16 #define UNATTENDED_CONF "/cdrom/boot/unattended.conf"
17 #define LICENSE_FILE "/cdrom/COPYING"
29 extern char url
[STRING_SIZE
];
31 struct nic nics
[20] = { { "" , "" , "" } }; // only defined for compile
32 struct knic knics
[20] = { { "" , "" , "" , "" } }; // only defined for compile
43 int main(int argc
, char *argv
[])
46 char discl_msg
[40000] = "Disclaimer\n";
48 char *langnames
[] = { "Deutsch", "English", "Français", "Español", "Nederlands", "Polski", "Русский", "Türkçe", NULL
};
49 char *shortlangnames
[] = { "de", "en", "fr", "es", "nl", "pl", "ru", "tr", NULL
};
50 char **langtrs
[] = { de_tr
, en_tr
, fr_tr
, es_tr
, nl_tr
, pl_tr
, ru_tr
, tr_tr
, NULL
};
52 char harddrive
[30], sourcedrive
[5]; /* Device holder. */
53 char harddrive_info
[STRING_SIZE
]; /* Additional infos about target */
54 struct devparams hdparams
, cdromparams
; /* Params for CDROM and HD */
56 char commandstring
[STRING_SIZE
];
57 char mkfscommand
[STRING_SIZE
];
58 char *fstypes
[] = { "ext2", "ext3", "ext4", "ReiserFS", NULL
};
63 char shortlangname
[10];
65 char title
[STRING_SIZE
];
69 struct keyvalue
*ethernetkv
= initkeyvalues();
70 FILE *handle
, *cmdfile
, *copying
;
71 char line
[STRING_SIZE
];
72 char string
[STRING_SIZE
];
73 long memory
= 0, disk
= 0, free
;
74 long system_partition
, boot_partition
, root_partition
, swap_file
;
76 char *yesnoharddisk
[3]; // char *yesnoharddisk = { "NO", "YES", NULL };
79 int serialconsole
= 0;
80 struct keyvalue
*unattendedkv
= initkeyvalues();
82 char restore_file
[STRING_SIZE
] = "";
84 setlocale (LC_ALL
, "");
85 sethostname( SNAME
, 10);
87 memset(&hdparams
, 0, sizeof(struct devparams
));
88 memset(&cdromparams
, 0, sizeof(struct devparams
));
90 /* Log file/terminal stuff. */
93 if (!(flog
= fopen(argv
[1], "w+")))
101 fprintf(flog
, "Install program started.\n");
106 newtDrawRootText(14, 0, NAME
" " VERSION
" - " SLOGAN
);
107 sprintf (title
, "%s %s - %s", NAME
, VERSION
, SLOGAN
);
109 if (! (cmdfile
= fopen("/proc/cmdline", "r")))
111 fprintf(flog
, "Couldn't open commandline: /proc/cmdline\n");
113 fgets(line
, STRING_SIZE
, cmdfile
);
115 // check if we have to make an unattended install
116 if (strstr (line
, "unattended") != NULL
) {
118 runcommandwithstatus("/bin/sleep 10", "WARNING: Unattended installation will start in 10 seconds...");
120 // check if we have to patch for serial console
121 if (strstr (line
, "console=ttyS0") != NULL
) {
126 // Load common modules
127 mysystem("/sbin/modprobe vfat"); // USB key
129 /* German is the default */
130 for (choice
= 0; langnames
[choice
]; choice
++)
132 if (strcmp(langnames
[choice
], "English") == 0)
135 if (!langnames
[choice
])
139 rc
= newtWinMenu("Language selection", "Select the language you wish to use for the " NAME
".", 50, 5, 5, 8,
140 langnames
, &choice
, "Ok", NULL
);
143 ctr
= langtrs
[choice
];
144 strcpy(shortlangname
, shortlangnames
[choice
]);
146 newtPushHelpLine(ctr
[TR_HELPLINE
]);
149 sprintf(message
, ctr
[TR_WELCOME
], NAME
);
150 newtWinMessage(title
, ctr
[TR_OK
], message
);
153 mysystem("/bin/mountsource.sh");
155 if ((handle
= fopen("/tmp/source_device", "r")) == NULL
) {
156 newtWinMessage(title
, ctr
[TR_OK
], ctr
[TR_NO_LOCAL_SOURCE
]);
157 runcommandwithstatus("/bin/downloadsource.sh",ctr
[TR_DOWNLOADING_ISO
]);
158 if ((handle
= fopen("/tmp/source_device", "r")) == NULL
) {
159 errorbox(ctr
[TR_DOWNLOAD_ERROR
]);
164 fgets(sourcedrive
, 5, handle
);
165 fprintf(flog
, "Source drive: %s\n", sourcedrive
);
169 // Read the license file.
170 if (!(copying
= fopen(LICENSE_FILE
, "r"))) {
171 sprintf(discl_msg
, "Could not open license file: %s\n", LICENSE_FILE
);
172 fprintf(flog
, discl_msg
);
174 fread(discl_msg
, 1, 40000, copying
);
177 if (disclaimerbox(discl_msg
)==0) {
178 errorbox(ctr
[TR_LICENSE_NOT_ACCEPTED
]);
187 fprintf(flog
, "Harddisk scan pass %i\n", i
);
189 switch (mysystem("/bin/mountdest.sh") % 255) {
190 case 0: // Found IDE disk
195 case 1: // Found SCSI disk
200 case 2: // Found RAID disk
205 case 10: // No harddisk found
206 errorbox(ctr
[TR_NO_HARDDISK
]);
211 if ((handle
= fopen("/tmp/dest_device", "r")) == NULL
) {
212 errorbox(ctr
[TR_NO_HARDDISK
]);
215 fgets(harddrive
, 30, handle
);
217 if ((handle
= fopen("/tmp/dest_device_info", "r")) == NULL
) {
218 sprintf(harddrive_info
, "%s", harddrive
);
220 fgets(harddrive_info
, 70, handle
);
224 /* load unattended configuration */
226 fprintf(flog
, "unattended: Reading unattended.conf\n");
228 (void) readkeyvalues(unattendedkv
, UNATTENDED_CONF
);
229 findkey(unattendedkv
, "RESTORE_FILE", restore_file
);
232 /* Make the hdparms struct and print the contents.
233 With USB-KEY install and SCSI disk, while installing, the disk
234 is named 'sdb,sdc,...' (following keys)
235 On reboot, it will become 'sda'
236 To avoid many test, all names are built in the struct.
238 sprintf(hdparams
.devnode_disk
, "/dev/%s", harddrive
);
239 /* Address the partition or raid partition (eg dev/sda or /dev/sdap1 */
240 sprintf(hdparams
.devnode_part
, "/dev/%s%s", harddrive
,raid_disk
? "p" : "");
241 /* Now the names after the machine is booted. Only scsi is affected
242 and we only install on the first scsi disk. */
244 fprintf(flog
, "Destination drive: %s\n", hdparams
.devnode_disk
);
246 sprintf(message
, ctr
[TR_PREPARE_HARDDISK
], harddrive_info
);
250 yesnoharddisk
[0] = ctr
[TR_NO
];
251 yesnoharddisk
[1] = ctr
[TR_YES
];
252 yesnoharddisk
[2] = NULL
;
256 rc
= newtWinMenu(title
, message
,
257 50, 5, 5, 6, yesnoharddisk
,
259 ctr
[TR_CANCEL
], NULL
);
266 fstypes
[0]=ctr
[TR_EXT2FS_DESCR
];
267 fstypes
[1]=ctr
[TR_EXT3FS_DESCR
];
268 fstypes
[2]=ctr
[TR_EXT4FS_DESCR
];
269 fstypes
[3]=ctr
[TR_REISERFS_DESCR
];
273 sprintf(message
, ctr
[TR_CHOOSE_FILESYSTEM
]);
274 rc
= newtWinMenu( ctr
[TR_CHOOSE_FILESYSTEM
], message
,
275 50, 5, 5, 6, fstypes
, &fstype
, ctr
[TR_OK
],
276 ctr
[TR_CANCEL
], NULL
);
284 /* Calculate amount of memory in machine */
285 if ((handle
= fopen("/proc/meminfo", "r")))
287 while (fgets(line
, STRING_SIZE
-1, handle
)) {
288 if (sscanf (line
, "MemTotal: %s kB", string
)) {
289 memory
= atoi(string
) / 1024 ;
295 /* Partition, mkswp, mkfs.
296 * before partitioning, first determine the sizes of each
297 * partition. In order to do that we need to know the size of
300 /* Don't use mysystem here so we can redirect output */
301 sprintf(commandstring
, "/sbin/sfdisk -s /dev/%s > /tmp/disksize 2> /dev/null", harddrive
);
302 system(commandstring
);
304 /* Calculate amount of disk space */
305 if ((handle
= fopen("/tmp/disksize", "r"))) {
306 fgets(line
, STRING_SIZE
-1, handle
);
307 if (sscanf (line
, "%s", string
)) {
308 disk
= atoi(string
) / 1024;
313 fprintf(flog
, "Disksize = %ld, memory = %ld", disk
, memory
);
315 /* Calculating Swap-Size dependend of Ram Size */
318 else if (memory
<= 1024 && memory
> 256)
321 swap_file
= memory
/ 4;
323 /* Calculating Root-Size dependend of Max Disk Space */
325 root_partition
= 200;
326 else if ( disk
>= 756 && disk
<= 3072 )
327 root_partition
= 512;
329 root_partition
= 2048;
332 /* Calculating the amount of free space */
333 boot_partition
= 64; /* in MB */
334 system_partition
= disk
- ( root_partition
+ swap_file
+ boot_partition
);
336 fprintf(flog
, ", boot = %ld, swap = %ld, mylog = %ld, root = %ld\n",
337 boot_partition
, swap_file
, system_partition
, root_partition
);
340 if ( (!unattended
) && (((disk
- (root_partition
+ swap_file
+ boot_partition
)) < 256 ) && ((disk
- (root_partition
+ boot_partition
)) > 256)) ) {
341 rc
= newtWinChoice(title
, ctr
[TR_OK
], ctr
[TR_CANCEL
], ctr
[TR_CONTINUE_NO_SWAP
]);
344 system_partition
= disk
- ( root_partition
+ swap_file
+ boot_partition
);
345 fprintf(flog
, "Changing Swap Size to 0 MB.\n");
348 fprintf(flog
, "Disk is too small.\n");
349 errorbox(ctr
[TR_DISK_TOO_SMALL
]);goto EXIT
;
352 else if (disk
- (root_partition
+ swap_file
+ boot_partition
) >= 256) {
356 fprintf(flog
, "Disk is too small.\n");
357 errorbox(ctr
[TR_DISK_TOO_SMALL
]);goto EXIT
;
360 handle
= fopen("/tmp/partitiontable", "w");
364 fprintf(handle
, ",%ld,L,*\n,%ld,S,\n,%ld,L,\n,,L,\n",
365 boot_partition
, swap_file
, root_partition
);
367 fprintf(handle
, ",%ld,L,*\n,0,0,\n,%ld,L,\n,,L,\n",
368 boot_partition
, root_partition
);
373 if (disk
< 2097150) {
374 // <2TB use sfdisk and normal mbr
375 snprintf(commandstring
, STRING_SIZE
, "/sbin/sfdisk -L -uM %s < /tmp/partitiontable", hdparams
.devnode_disk
);
377 // >2TB use parted with gpt
378 snprintf(commandstring
, STRING_SIZE
, "/usr/sbin/parted -s %s mklabel gpt mkpart boot ext2 1M 64M mkpart swap linux-swap 64M 1000M mkpart root ext4 1000M 5000M mkpart var ext4 5000M 100%% disk_set pmbr_boot on", hdparams
.devnode_disk
);
381 if (runcommandwithstatus(commandstring
, ctr
[TR_PARTITIONING_DISK
]))
383 errorbox(ctr
[TR_UNABLE_TO_PARTITION
]);
387 if (fstype
== EXT2
) {
388 // mysystem("/sbin/modprobe ext2");
389 sprintf(mkfscommand
, "/sbin/mke2fs -T ext2");
390 } else if (fstype
== REISERFS
) {
391 mysystem("/sbin/modprobe reiserfs");
392 sprintf(mkfscommand
, "/sbin/mkreiserfs -f");
393 } else if (fstype
== EXT3
) {
394 // mysystem("/sbin/modprobe ext3");
395 sprintf(mkfscommand
, "/sbin/mke2fs -T ext3");
396 } else if (fstype
== EXT4
) {
397 // mysystem("/sbin/modprobe ext4");
398 sprintf(mkfscommand
, "/sbin/mke2fs -T ext4");
401 snprintf(commandstring
, STRING_SIZE
, "/sbin/mke2fs -T ext2 -I 128 %s1", hdparams
.devnode_part
);
402 if (runcommandwithstatus(commandstring
, ctr
[TR_MAKING_BOOT_FILESYSTEM
]))
404 errorbox(ctr
[TR_UNABLE_TO_MAKE_BOOT_FILESYSTEM
]);
409 snprintf(commandstring
, STRING_SIZE
, "/sbin/mkswap %s2", hdparams
.devnode_part
);
410 if (runcommandwithstatus(commandstring
, ctr
[TR_MAKING_SWAPSPACE
]))
412 errorbox(ctr
[TR_UNABLE_TO_MAKE_SWAPSPACE
]);
417 snprintf(commandstring
, STRING_SIZE
, "%s %s3", mkfscommand
, hdparams
.devnode_part
);
418 if (runcommandwithstatus(commandstring
, ctr
[TR_MAKING_ROOT_FILESYSTEM
]))
420 errorbox(ctr
[TR_UNABLE_TO_MAKE_ROOT_FILESYSTEM
]);
424 snprintf(commandstring
, STRING_SIZE
, "%s %s4", mkfscommand
, hdparams
.devnode_part
);
425 if (runcommandwithstatus(commandstring
, ctr
[TR_MAKING_LOG_FILESYSTEM
]))
427 errorbox(ctr
[TR_UNABLE_TO_MAKE_LOG_FILESYSTEM
]);
431 snprintf(commandstring
, STRING_SIZE
, "/bin/mount %s3 /harddisk", hdparams
.devnode_part
);
432 if (runcommandwithstatus(commandstring
, ctr
[TR_MOUNTING_ROOT_FILESYSTEM
]))
434 errorbox(ctr
[TR_UNABLE_TO_MOUNT_ROOT_FILESYSTEM
]);
438 mkdir("/harddisk/boot", S_IRWXU
|S_IRWXG
|S_IRWXO
);
439 mkdir("/harddisk/var", S_IRWXU
|S_IRWXG
|S_IRWXO
);
440 mkdir("/harddisk/var/log", S_IRWXU
|S_IRWXG
|S_IRWXO
);
442 snprintf(commandstring
, STRING_SIZE
, "/bin/mount %s1 /harddisk/boot", hdparams
.devnode_part
);
443 if (runcommandwithstatus(commandstring
, ctr
[TR_MOUNTING_BOOT_FILESYSTEM
]))
445 errorbox(ctr
[TR_UNABLE_TO_MOUNT_BOOT_FILESYSTEM
]);
449 snprintf(commandstring
, STRING_SIZE
, "/sbin/swapon %s2", hdparams
.devnode_part
);
450 if (runcommandwithstatus(commandstring
, ctr
[TR_MOUNTING_SWAP_PARTITION
]))
452 errorbox(ctr
[TR_UNABLE_TO_MOUNT_SWAP_PARTITION
]);
456 snprintf(commandstring
, STRING_SIZE
, "/bin/mount %s4 /harddisk/var", hdparams
.devnode_part
);
457 if (runcommandwithstatus(commandstring
, ctr
[TR_MOUNTING_LOG_FILESYSTEM
]))
459 errorbox(ctr
[TR_UNABLE_TO_MOUNT_LOG_FILESYSTEM
]);
463 snprintf(commandstring
, STRING_SIZE
,
464 "/bin/tar -C /harddisk -xvf /cdrom/" SNAME
"-" VERSION
".tlz --lzma 2>/dev/null");
466 if (runcommandwithprogress(60, 4, title
, commandstring
, INST_FILECOUNT
,
467 ctr
[TR_INSTALLING_FILES
]))
469 errorbox(ctr
[TR_UNABLE_TO_INSTALL_FILES
]);
473 /* Save language und local settings */
474 write_lang_configs(shortlangname
);
476 /* mount proc filesystem */
477 mysystem("mkdir /harddisk/proc");
478 mysystem("/bin/mount --bind /proc /harddisk/proc");
479 mysystem("/bin/mount --bind /dev /harddisk/dev");
480 mysystem("/bin/mount --bind /sys /harddisk/sys");
482 /* Build cache lang file */
483 snprintf(commandstring
, STRING_SIZE
, "/usr/sbin/chroot /harddisk /usr/bin/perl -e \"require '" CONFIG_ROOT
"/lang.pl'; &Lang::BuildCacheLang\"");
484 if (runcommandwithstatus(commandstring
, ctr
[TR_INSTALLING_LANG_CACHE
]))
486 errorbox(ctr
[TR_UNABLE_TO_INSTALL_LANG_CACHE
]);
490 /* Update /etc/fstab */
491 snprintf(commandstring
, STRING_SIZE
, "/bin/sed -i -e \"s#DEVICE1#UUID=$(/sbin/blkid %s1 -sUUID | /usr/bin/cut -d'\"' -f2)#g\" /harddisk/etc/fstab", hdparams
.devnode_part
);
492 system(commandstring
);
493 snprintf(commandstring
, STRING_SIZE
, "/bin/sed -i -e \"s#DEVICE2#UUID=$(/sbin/blkid %s2 -sUUID | /usr/bin/cut -d'\"' -f2)#g\" /harddisk/etc/fstab", hdparams
.devnode_part
);
494 system(commandstring
);
495 snprintf(commandstring
, STRING_SIZE
, "/bin/sed -i -e \"s#DEVICE3#UUID=$(/sbin/blkid %s3 -sUUID | /usr/bin/cut -d'\"' -f2)#g\" /harddisk/etc/fstab", hdparams
.devnode_part
);
496 system(commandstring
);
497 snprintf(commandstring
, STRING_SIZE
, "/bin/sed -i -e \"s#DEVICE4#UUID=$(/sbin/blkid %s4 -sUUID | /usr/bin/cut -d'\"' -f2)#g\" /harddisk/etc/fstab", hdparams
.devnode_part
);
498 system(commandstring
);
500 if (fstype
== EXT2
) {
501 replace("/harddisk/etc/fstab", "FSTYPE", "ext2");
502 replace("/harddisk/boot/grub/grub.conf", "MOUNT", "ro");
503 } else if (fstype
== REISERFS
) {
504 replace("/harddisk/etc/fstab", "FSTYPE", "reiserfs");
505 replace("/harddisk/boot/grub/grub.conf", "MOUNT", "ro");
506 } else if (fstype
== EXT3
) {
507 replace("/harddisk/etc/fstab", "FSTYPE", "ext3");
508 replace("/harddisk/boot/grub/grub.conf", "MOUNT", "ro");
509 } else if (fstype
== EXT4
) {
510 replace("/harddisk/etc/fstab", "FSTYPE", "ext4");
511 replace("/harddisk/boot/grub/grub.conf", "MOUNT", "ro");
514 replace("/harddisk/boot/grub/grub.conf", "KVER", KERNEL_VERSION
);
516 snprintf(commandstring
, STRING_SIZE
, "/bin/sed -i -e \"s#root=ROOT#root=UUID=$(/sbin/blkid %s3 -sUUID | /usr/bin/cut -d'\"' -f2)#g\" /harddisk/boot/grub/grub.conf", hdparams
.devnode_part
);
517 system(commandstring
);
519 mysystem("ln -s grub.conf /harddisk/boot/grub/menu.lst");
521 system("/bin/sed -e 's#/harddisk#/#g' -e 's#//#/#g' < /proc/mounts > /harddisk/etc/mtab");
524 * Generate device.map to help grub finding the device to install itself on.
527 if (f
= fopen("/harddisk/boot/grub/device.map", "w")) {
528 fprintf(f
, "(hd0) %s\n", hdparams
.devnode_disk
);
532 snprintf(commandstring
, STRING_SIZE
,
533 "/usr/sbin/chroot /harddisk /usr/sbin/grub-install --no-floppy %s", hdparams
.devnode_disk
);
534 if (runcommandwithstatus(commandstring
, ctr
[TR_INSTALLING_GRUB
])) {
535 errorbox(ctr
[TR_UNABLE_TO_INSTALL_GRUB
]);
539 /* Serial console ? */
542 replace("/harddisk/boot/grub/grub.conf", "splashimage", "#splashimage");
543 replace("/harddisk/boot/grub/grub.conf", "#serial", "serial");
544 replace("/harddisk/boot/grub/grub.conf", "#terminal", "terminal");
545 replace("/harddisk/boot/grub/grub.conf", " panic=10 ", " console=ttyS0,38400n8 panic=10 ");
548 replace("/harddisk/etc/inittab", "1:2345:respawn:", "#1:2345:respawn:");
549 replace("/harddisk/etc/inittab", "2:2345:respawn:", "#2:2345:respawn:");
550 replace("/harddisk/etc/inittab", "3:2345:respawn:", "#3:2345:respawn:");
551 replace("/harddisk/etc/inittab", "4:2345:respawn:", "#4:2345:respawn:");
552 replace("/harddisk/etc/inittab", "5:2345:respawn:", "#5:2345:respawn:");
553 replace("/harddisk/etc/inittab", "6:2345:respawn:", "#6:2345:respawn:");
554 replace("/harddisk/etc/inittab", "#7:2345:respawn:", "7:2345:respawn:");
557 /* Set marker that the user has already accepted the gpl */
558 mysystem("/usr/bin/touch /harddisk/var/ipfire/main/gpl_accepted");
560 /* Copy restore file from cdrom */
561 if (unattended
&& (strlen(restore_file
) > 0)) {
562 fprintf(flog
, "unattended: Copy restore file\n");
563 snprintf(commandstring
, STRING_SIZE
,
564 "cp /cdrom/%s /harddisk/var/ipfire/backup", restore_file
);
565 mysystem(commandstring
);
568 mysystem("umount /cdrom");
569 snprintf(commandstring
, STRING_SIZE
, "/usr/bin/eject /dev/%s", sourcedrive
);
570 mysystem(commandstring
);
573 sprintf(message
, ctr
[TR_CONGRATULATIONS_LONG
],
575 newtWinMessage(ctr
[TR_CONGRATULATIONS
], ctr
[TR_PRESS_OK_TO_REBOOT
], message
);
581 fprintf(flog
, "Install program ended.\n");
584 newtWinMessage(title
, ctr
[TR_OK
], ctr
[TR_PRESS_OK_TO_REBOOT
]);
586 freekeyvalues(ethernetkv
);
588 if (allok
&& !allok_fastexit
)
591 fprintf(flog
, "Entering unattended setup\n");
592 if (unattended_setup(unattendedkv
)) {
593 snprintf(commandstring
, STRING_SIZE
, "/bin/sleep 10");
594 runcommandwithstatus(commandstring
, "Unattended installation finished, system will reboot");
596 errorbox("Unattended setup failed.");
605 if (system("/bin/umount /harddisk/proc"))
606 printf("Unable to umount /harddisk/proc.\n");
616 snprintf(commandstring
, STRING_SIZE
, "/bin/swapoff %s2", hdparams
.devnode_part
);
621 system("/bin/umount /harddisk/proc >/dev/null 2>&1");
622 system("/bin/umount /harddisk/dev >/dev/null 2>&1");
623 system("/bin/umount /harddisk/sys >/dev/null 2>&1");
625 system("/bin/umount /harddisk/var >/dev/null 2>&1");
626 system("/bin/umount /harddisk/boot >/dev/null 2>&1");
627 system("/bin/umount /harddisk >/dev/null 2>&1");