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
18 #include <sys/mount.h>
23 #define INST_FILECOUNT 21000
24 #define UNATTENDED_CONF "/cdrom/boot/unattended.conf"
25 #define LICENSE_FILE "/cdrom/COPYING"
37 extern char url
[STRING_SIZE
];
39 struct nic nics
[20] = { { "" , "" , "" } }; // only defined for compile
40 struct knic knics
[20] = { { "" , "" , "" , "" } }; // only defined for compile
51 int main(int argc
, char *argv
[]) {
52 struct hw
* hw
= hw_init();
54 char discl_msg
[40000] = "Disclaimer\n";
56 char *langnames
[] = { "Deutsch", "English", "Français", "Español", "Nederlands", "Polski", "Русский", "Türkçe", NULL
};
57 char *shortlangnames
[] = { "de", "en", "fr", "es", "nl", "pl", "ru", "tr", NULL
};
58 char **langtrs
[] = { de_tr
, en_tr
, fr_tr
, es_tr
, nl_tr
, pl_tr
, ru_tr
, tr_tr
, NULL
};
60 char harddrive
[30]; /* Device holder. */
61 char* sourcedrive
= NULL
;
62 char harddrive_info
[STRING_SIZE
]; /* Additional infos about target */
63 struct devparams hdparams
, cdromparams
; /* Params for CDROM and HD */
65 char commandstring
[STRING_SIZE
];
66 char mkfscommand
[STRING_SIZE
];
67 char *fstypes
[] = { "ext2", "ext3", "ext4", "ReiserFS", NULL
};
72 char shortlangname
[10];
74 char title
[STRING_SIZE
];
78 struct keyvalue
*ethernetkv
= initkeyvalues();
79 FILE *handle
, *cmdfile
, *copying
;
80 char line
[STRING_SIZE
];
81 char string
[STRING_SIZE
];
82 long memory
= 0, disk
= 0;
83 long system_partition
, boot_partition
, root_partition
, swap_file
;
85 char *yesnoharddisk
[3]; // char *yesnoharddisk = { "NO", "YES", NULL };
88 int serialconsole
= 0;
89 struct keyvalue
*unattendedkv
= initkeyvalues();
91 char restore_file
[STRING_SIZE
] = "";
93 setlocale (LC_ALL
, "");
94 sethostname( SNAME
, 10);
96 memset(&hdparams
, 0, sizeof(struct devparams
));
97 memset(&cdromparams
, 0, sizeof(struct devparams
));
99 /* Log file/terminal stuff. */
102 if (!(flog
= fopen(argv
[1], "w+")))
110 fprintf(flog
, "Install program started.\n");
115 newtDrawRootText(14, 0, NAME
" " VERSION
" - " SLOGAN
);
116 sprintf (title
, "%s %s - %s", NAME
, VERSION
, SLOGAN
);
118 if (! (cmdfile
= fopen("/proc/cmdline", "r")))
120 fprintf(flog
, "Couldn't open commandline: /proc/cmdline\n");
122 fgets(line
, STRING_SIZE
, cmdfile
);
124 // check if we have to make an unattended install
125 if (strstr (line
, "unattended") != NULL
) {
127 runcommandwithstatus("/bin/sleep 10", "WARNING: Unattended installation will start in 10 seconds...");
129 // check if we have to patch for serial console
130 if (strstr (line
, "console=ttyS0") != NULL
) {
135 // Load common modules
136 mysystem("/sbin/modprobe vfat"); // USB key
138 /* German is the default */
139 for (choice
= 0; langnames
[choice
]; choice
++)
141 if (strcmp(langnames
[choice
], "English") == 0)
144 if (!langnames
[choice
])
148 rc
= newtWinMenu("Language selection", "Select the language you wish to use for the " NAME
".", 50, 5, 5, 8,
149 langnames
, &choice
, "Ok", NULL
);
152 ctr
= langtrs
[choice
];
153 strcpy(shortlangname
, shortlangnames
[choice
]);
155 newtPushHelpLine(ctr
[TR_HELPLINE
]);
158 sprintf(message
, ctr
[TR_WELCOME
], NAME
);
159 newtWinMessage(title
, ctr
[TR_OK
], message
);
162 /* Search for a source drive that holds the right
163 * version of the image we are going to install. */
164 sourcedrive
= hw_find_source_medium(hw
);
166 fprintf(flog
, "Source drive: %s\n", sourcedrive
);
168 newtWinMessage(title
, ctr
[TR_OK
], ctr
[TR_NO_LOCAL_SOURCE
]);
169 runcommandwithstatus("/bin/downloadsource.sh", ctr
[TR_DOWNLOADING_ISO
]);
170 if ((handle
= fopen("/tmp/source_device", "r")) == NULL
) {
171 errorbox(ctr
[TR_DOWNLOAD_ERROR
]);
175 fgets(sourcedrive
, 5, handle
);
181 int r
= hw_mount(sourcedrive
, SOURCE_MOUNT_PATH
, MS_RDONLY
);
183 fprintf(flog
, "Could not mount %s to %s\n", sourcedrive
, SOURCE_MOUNT_PATH
);
184 fprintf(flog
, strerror(errno
));
189 // Read the license file.
190 if (!(copying
= fopen(LICENSE_FILE
, "r"))) {
191 sprintf(discl_msg
, "Could not open license file: %s\n", LICENSE_FILE
);
192 fprintf(flog
, discl_msg
);
194 fread(discl_msg
, 1, 40000, copying
);
197 if (disclaimerbox(discl_msg
)==0) {
198 errorbox(ctr
[TR_LICENSE_NOT_ACCEPTED
]);
207 fprintf(flog
, "Harddisk scan pass %i\n", i
);
209 switch (mysystem("/bin/mountdest.sh") % 255) {
210 case 0: // Found IDE disk
215 case 1: // Found SCSI disk
220 case 2: // Found RAID disk
225 case 10: // No harddisk found
226 errorbox(ctr
[TR_NO_HARDDISK
]);
231 if ((handle
= fopen("/tmp/dest_device", "r")) == NULL
) {
232 errorbox(ctr
[TR_NO_HARDDISK
]);
235 fgets(harddrive
, 30, handle
);
237 if ((handle
= fopen("/tmp/dest_device_info", "r")) == NULL
) {
238 sprintf(harddrive_info
, "%s", harddrive
);
240 fgets(harddrive_info
, 70, handle
);
244 /* load unattended configuration */
246 fprintf(flog
, "unattended: Reading unattended.conf\n");
248 (void) readkeyvalues(unattendedkv
, UNATTENDED_CONF
);
249 findkey(unattendedkv
, "RESTORE_FILE", restore_file
);
252 /* Make the hdparms struct and print the contents.
253 With USB-KEY install and SCSI disk, while installing, the disk
254 is named 'sdb,sdc,...' (following keys)
255 On reboot, it will become 'sda'
256 To avoid many test, all names are built in the struct.
258 sprintf(hdparams
.devnode_disk
, "/dev/%s", harddrive
);
259 /* Address the partition or raid partition (eg dev/sda or /dev/sdap1 */
260 sprintf(hdparams
.devnode_part
, "/dev/%s%s", harddrive
,raid_disk
? "p" : "");
261 /* Now the names after the machine is booted. Only scsi is affected
262 and we only install on the first scsi disk. */
264 fprintf(flog
, "Destination drive: %s\n", hdparams
.devnode_disk
);
266 sprintf(message
, ctr
[TR_PREPARE_HARDDISK
], harddrive_info
);
270 yesnoharddisk
[0] = ctr
[TR_NO
];
271 yesnoharddisk
[1] = ctr
[TR_YES
];
272 yesnoharddisk
[2] = NULL
;
276 rc
= newtWinMenu(title
, message
,
277 50, 5, 5, 6, yesnoharddisk
,
279 ctr
[TR_CANCEL
], NULL
);
286 fstypes
[0]=ctr
[TR_EXT2FS_DESCR
];
287 fstypes
[1]=ctr
[TR_EXT3FS_DESCR
];
288 fstypes
[2]=ctr
[TR_EXT4FS_DESCR
];
289 fstypes
[3]=ctr
[TR_REISERFS_DESCR
];
293 sprintf(message
, ctr
[TR_CHOOSE_FILESYSTEM
]);
294 rc
= newtWinMenu( ctr
[TR_CHOOSE_FILESYSTEM
], message
,
295 50, 5, 5, 6, fstypes
, &fstype
, ctr
[TR_OK
],
296 ctr
[TR_CANCEL
], NULL
);
304 /* Calculate amount of memory in machine */
305 if ((handle
= fopen("/proc/meminfo", "r")))
307 while (fgets(line
, STRING_SIZE
-1, handle
)) {
308 if (sscanf (line
, "MemTotal: %s kB", string
)) {
309 memory
= atoi(string
) / 1024 ;
315 /* Partition, mkswp, mkfs.
316 * before partitioning, first determine the sizes of each
317 * partition. In order to do that we need to know the size of
320 /* Don't use mysystem here so we can redirect output */
321 sprintf(commandstring
, "/sbin/sfdisk -s /dev/%s > /tmp/disksize 2> /dev/null", harddrive
);
322 system(commandstring
);
324 /* Calculate amount of disk space */
325 if ((handle
= fopen("/tmp/disksize", "r"))) {
326 fgets(line
, STRING_SIZE
-1, handle
);
327 if (sscanf (line
, "%s", string
)) {
328 disk
= atoi(string
) / 1024;
333 fprintf(flog
, "Disksize = %ld, memory = %ld", disk
, memory
);
335 /* Calculating Swap-Size dependend of Ram Size */
338 else if (memory
<= 1024 && memory
> 256)
341 swap_file
= memory
/ 4;
343 /* Calculating Root-Size dependend of Max Disk Space */
345 root_partition
= 1024;
346 else if ( disk
>= 2048 && disk
<= 3072 )
347 root_partition
= 1536;
349 root_partition
= 2048;
352 /* Calculating the amount of free space */
353 boot_partition
= 64; /* in MB */
354 system_partition
= disk
- ( root_partition
+ swap_file
+ boot_partition
);
356 fprintf(flog
, ", boot = %ld, swap = %ld, mylog = %ld, root = %ld\n",
357 boot_partition
, swap_file
, system_partition
, root_partition
);
360 if ( (!unattended
) && (((disk
- (root_partition
+ swap_file
+ boot_partition
)) < 256 ) && ((disk
- (root_partition
+ boot_partition
)) > 256)) ) {
361 rc
= newtWinChoice(title
, ctr
[TR_OK
], ctr
[TR_CANCEL
], ctr
[TR_CONTINUE_NO_SWAP
]);
364 system_partition
= disk
- ( root_partition
+ swap_file
+ boot_partition
);
365 fprintf(flog
, "Changing Swap Size to 0 MB.\n");
368 fprintf(flog
, "Disk is too small.\n");
369 errorbox(ctr
[TR_DISK_TOO_SMALL
]);goto EXIT
;
372 else if (disk
- (root_partition
+ swap_file
+ boot_partition
) >= 256) {
376 fprintf(flog
, "Disk is too small.\n");
377 errorbox(ctr
[TR_DISK_TOO_SMALL
]);goto EXIT
;
380 handle
= fopen("/tmp/partitiontable", "w");
384 fprintf(handle
, ",%ld,L,*\n,%ld,S,\n,%ld,L,\n,,L,\n",
385 boot_partition
, swap_file
, root_partition
);
387 fprintf(handle
, ",%ld,L,*\n,0,0,\n,%ld,L,\n,,L,\n",
388 boot_partition
, root_partition
);
393 if (disk
< 2097150) {
394 // <2TB use sfdisk and normal mbr
395 snprintf(commandstring
, STRING_SIZE
, "/sbin/sfdisk -L -uM %s < /tmp/partitiontable", hdparams
.devnode_disk
);
397 // >2TB use parted with gpt
398 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
);
401 if (runcommandwithstatus(commandstring
, ctr
[TR_PARTITIONING_DISK
]))
403 errorbox(ctr
[TR_UNABLE_TO_PARTITION
]);
407 if (fstype
== EXT2
) {
408 // mysystem("/sbin/modprobe ext2");
409 sprintf(mkfscommand
, "/sbin/mke2fs -T ext2");
410 } else if (fstype
== REISERFS
) {
411 mysystem("/sbin/modprobe reiserfs");
412 sprintf(mkfscommand
, "/sbin/mkreiserfs -f");
413 } else if (fstype
== EXT3
) {
414 // mysystem("/sbin/modprobe ext3");
415 sprintf(mkfscommand
, "/sbin/mke2fs -T ext3");
416 } else if (fstype
== EXT4
) {
417 // mysystem("/sbin/modprobe ext4");
418 sprintf(mkfscommand
, "/sbin/mke2fs -T ext4");
421 snprintf(commandstring
, STRING_SIZE
, "/sbin/mke2fs -T ext2 -I 128 %s1", hdparams
.devnode_part
);
422 if (runcommandwithstatus(commandstring
, ctr
[TR_MAKING_BOOT_FILESYSTEM
]))
424 errorbox(ctr
[TR_UNABLE_TO_MAKE_BOOT_FILESYSTEM
]);
429 snprintf(commandstring
, STRING_SIZE
, "/sbin/mkswap %s2", hdparams
.devnode_part
);
430 if (runcommandwithstatus(commandstring
, ctr
[TR_MAKING_SWAPSPACE
]))
432 errorbox(ctr
[TR_UNABLE_TO_MAKE_SWAPSPACE
]);
437 snprintf(commandstring
, STRING_SIZE
, "%s %s3", mkfscommand
, hdparams
.devnode_part
);
438 if (runcommandwithstatus(commandstring
, ctr
[TR_MAKING_ROOT_FILESYSTEM
]))
440 errorbox(ctr
[TR_UNABLE_TO_MAKE_ROOT_FILESYSTEM
]);
444 snprintf(commandstring
, STRING_SIZE
, "%s %s4", mkfscommand
, hdparams
.devnode_part
);
445 if (runcommandwithstatus(commandstring
, ctr
[TR_MAKING_LOG_FILESYSTEM
]))
447 errorbox(ctr
[TR_UNABLE_TO_MAKE_LOG_FILESYSTEM
]);
451 snprintf(commandstring
, STRING_SIZE
, "/bin/mount %s3 /harddisk", hdparams
.devnode_part
);
452 if (runcommandwithstatus(commandstring
, ctr
[TR_MOUNTING_ROOT_FILESYSTEM
]))
454 errorbox(ctr
[TR_UNABLE_TO_MOUNT_ROOT_FILESYSTEM
]);
458 mkdir("/harddisk/boot", S_IRWXU
|S_IRWXG
|S_IRWXO
);
459 mkdir("/harddisk/var", S_IRWXU
|S_IRWXG
|S_IRWXO
);
460 mkdir("/harddisk/var/log", S_IRWXU
|S_IRWXG
|S_IRWXO
);
462 snprintf(commandstring
, STRING_SIZE
, "/bin/mount %s1 /harddisk/boot", hdparams
.devnode_part
);
463 if (runcommandwithstatus(commandstring
, ctr
[TR_MOUNTING_BOOT_FILESYSTEM
]))
465 errorbox(ctr
[TR_UNABLE_TO_MOUNT_BOOT_FILESYSTEM
]);
469 snprintf(commandstring
, STRING_SIZE
, "/sbin/swapon %s2", hdparams
.devnode_part
);
470 if (runcommandwithstatus(commandstring
, ctr
[TR_MOUNTING_SWAP_PARTITION
]))
472 errorbox(ctr
[TR_UNABLE_TO_MOUNT_SWAP_PARTITION
]);
476 snprintf(commandstring
, STRING_SIZE
, "/bin/mount %s4 /harddisk/var", hdparams
.devnode_part
);
477 if (runcommandwithstatus(commandstring
, ctr
[TR_MOUNTING_LOG_FILESYSTEM
]))
479 errorbox(ctr
[TR_UNABLE_TO_MOUNT_LOG_FILESYSTEM
]);
483 snprintf(commandstring
, STRING_SIZE
,
484 "/bin/tar -C /harddisk -xvf /cdrom/" SNAME
"-" VERSION
".tlz --lzma 2>/dev/null");
486 if (runcommandwithprogress(60, 4, title
, commandstring
, INST_FILECOUNT
,
487 ctr
[TR_INSTALLING_FILES
]))
489 errorbox(ctr
[TR_UNABLE_TO_INSTALL_FILES
]);
493 /* Save language und local settings */
494 write_lang_configs(shortlangname
);
496 /* mount proc filesystem */
497 mysystem("mkdir /harddisk/proc");
498 mysystem("/bin/mount --bind /proc /harddisk/proc");
499 mysystem("/bin/mount --bind /dev /harddisk/dev");
500 mysystem("/bin/mount --bind /sys /harddisk/sys");
502 /* Build cache lang file */
503 snprintf(commandstring
, STRING_SIZE
, "/usr/sbin/chroot /harddisk /usr/bin/perl -e \"require '" CONFIG_ROOT
"/lang.pl'; &Lang::BuildCacheLang\"");
504 if (runcommandwithstatus(commandstring
, ctr
[TR_INSTALLING_LANG_CACHE
]))
506 errorbox(ctr
[TR_UNABLE_TO_INSTALL_LANG_CACHE
]);
510 /* Update /etc/fstab */
511 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
);
512 system(commandstring
);
513 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
);
514 system(commandstring
);
515 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
);
516 system(commandstring
);
517 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
);
518 system(commandstring
);
520 if (fstype
== EXT2
) {
521 replace("/harddisk/etc/fstab", "FSTYPE", "ext2");
522 replace("/harddisk/boot/grub/grub.conf", "MOUNT", "ro");
523 } else if (fstype
== REISERFS
) {
524 replace("/harddisk/etc/fstab", "FSTYPE", "reiserfs");
525 replace("/harddisk/boot/grub/grub.conf", "MOUNT", "ro");
526 } else if (fstype
== EXT3
) {
527 replace("/harddisk/etc/fstab", "FSTYPE", "ext3");
528 replace("/harddisk/boot/grub/grub.conf", "MOUNT", "ro");
529 } else if (fstype
== EXT4
) {
530 replace("/harddisk/etc/fstab", "FSTYPE", "ext4");
531 replace("/harddisk/boot/grub/grub.conf", "MOUNT", "ro");
534 replace("/harddisk/boot/grub/grub.conf", "KVER", KERNEL_VERSION
);
536 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
);
537 system(commandstring
);
539 mysystem("ln -s grub.conf /harddisk/boot/grub/menu.lst");
541 system("/bin/sed -e 's#/harddisk#/#g' -e 's#//#/#g' < /proc/mounts > /harddisk/etc/mtab");
544 * Generate device.map to help grub finding the device to install itself on.
547 if (f
= fopen("/harddisk/boot/grub/device.map", "w")) {
548 fprintf(f
, "(hd0) %s\n", hdparams
.devnode_disk
);
552 snprintf(commandstring
, STRING_SIZE
,
553 "/usr/sbin/chroot /harddisk /usr/sbin/grub-install --no-floppy %s", hdparams
.devnode_disk
);
554 if (runcommandwithstatus(commandstring
, ctr
[TR_INSTALLING_GRUB
])) {
555 errorbox(ctr
[TR_UNABLE_TO_INSTALL_GRUB
]);
559 /* Serial console ? */
562 replace("/harddisk/boot/grub/grub.conf", "splashimage", "#splashimage");
563 replace("/harddisk/boot/grub/grub.conf", "#serial", "serial");
564 replace("/harddisk/boot/grub/grub.conf", "#terminal", "terminal");
565 replace("/harddisk/boot/grub/grub.conf", " panic=10 ", " console=ttyS0,115200n8 panic=10 ");
568 replace("/harddisk/etc/inittab", "1:2345:respawn:", "#1:2345:respawn:");
569 replace("/harddisk/etc/inittab", "2:2345:respawn:", "#2:2345:respawn:");
570 replace("/harddisk/etc/inittab", "3:2345:respawn:", "#3:2345:respawn:");
571 replace("/harddisk/etc/inittab", "4:2345:respawn:", "#4:2345:respawn:");
572 replace("/harddisk/etc/inittab", "5:2345:respawn:", "#5:2345:respawn:");
573 replace("/harddisk/etc/inittab", "6:2345:respawn:", "#6:2345:respawn:");
574 replace("/harddisk/etc/inittab", "#7:2345:respawn:", "7:2345:respawn:");
577 /* Set marker that the user has already accepted the gpl */
578 mysystem("/usr/bin/touch /harddisk/var/ipfire/main/gpl_accepted");
580 /* Copy restore file from cdrom */
581 if (unattended
&& (strlen(restore_file
) > 0)) {
582 fprintf(flog
, "unattended: Copy restore file\n");
583 snprintf(commandstring
, STRING_SIZE
,
584 "cp /cdrom/%s /harddisk/var/ipfire/backup", restore_file
);
585 mysystem(commandstring
);
588 mysystem("umount /cdrom");
589 snprintf(commandstring
, STRING_SIZE
, "/usr/bin/eject /dev/%s", sourcedrive
);
590 mysystem(commandstring
);
593 sprintf(message
, ctr
[TR_CONGRATULATIONS_LONG
],
595 newtWinMessage(ctr
[TR_CONGRATULATIONS
], ctr
[TR_PRESS_OK_TO_REBOOT
], message
);
601 fprintf(flog
, "Install program ended.\n");
604 newtWinMessage(title
, ctr
[TR_OK
], ctr
[TR_PRESS_OK_TO_REBOOT
]);
606 freekeyvalues(ethernetkv
);
608 if (allok
&& !allok_fastexit
)
611 fprintf(flog
, "Entering unattended setup\n");
612 if (unattended_setup(unattendedkv
)) {
613 snprintf(commandstring
, STRING_SIZE
, "/bin/sleep 10");
614 runcommandwithstatus(commandstring
, "Unattended installation finished, system will reboot");
616 errorbox("Unattended setup failed.");
625 if (system("/bin/umount /harddisk/proc"))
626 printf("Unable to umount /harddisk/proc.\n");
636 snprintf(commandstring
, STRING_SIZE
, "/bin/swapoff %s2", hdparams
.devnode_part
);
641 system("/bin/umount /harddisk/proc >/dev/null 2>&1");
642 system("/bin/umount /harddisk/dev >/dev/null 2>&1");
643 system("/bin/umount /harddisk/sys >/dev/null 2>&1");
645 system("/bin/umount /harddisk/var >/dev/null 2>&1");
646 system("/bin/umount /harddisk/boot >/dev/null 2>&1");
647 system("/bin/umount /harddisk >/dev/null 2>&1");