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 14400
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
41 int main(int argc
, char *argv
[])
44 char discl_msg
[40000] = "Disclaimer\n";
46 char *langnames
[] = { "Deutsch", "English", "Français", "Español", "Nederlands", "Polski", "Русский", NULL
};
47 char *shortlangnames
[] = { "de", "en", "fr", "es", "nl", "pl", "ru", NULL
};
48 char **langtrs
[] = { de_tr
, en_tr
, fr_tr
, es_tr
, pl_tr
, ru_tr
, NULL
};
50 char harddrive
[30], sourcedrive
[5]; /* Device holder. */
51 char harddrive_info
[STRING_SIZE
]; /* Additional infos about target */
52 struct devparams hdparams
, cdromparams
; /* Params for CDROM and HD */
54 char commandstring
[STRING_SIZE
];
55 char mkfscommand
[STRING_SIZE
];
56 char *fstypes
[] = { "ext2", "ext3", "ext4", "ReiserFS", NULL
};
61 char shortlangname
[10];
63 char title
[STRING_SIZE
];
67 struct keyvalue
*ethernetkv
= initkeyvalues();
68 FILE *handle
, *cmdfile
, *copying
;
69 char line
[STRING_SIZE
];
70 char string
[STRING_SIZE
];
71 long memory
= 0, disk
= 0, free
;
72 long system_partition
, boot_partition
, root_partition
, swap_file
;
74 char *yesnoharddisk
[3]; // char *yesnoharddisk = { "NO", "YES", NULL };
77 int serialconsole
= 0;
78 struct keyvalue
*unattendedkv
= initkeyvalues();
80 char restore_file
[STRING_SIZE
] = "";
82 setlocale (LC_ALL
, "");
83 sethostname( SNAME
, 10);
85 memset(&hdparams
, 0, sizeof(struct devparams
));
86 memset(&cdromparams
, 0, sizeof(struct devparams
));
88 /* Log file/terminal stuff. */
91 if (!(flog
= fopen(argv
[1], "w+")))
99 fprintf(flog
, "Install program started.\n");
104 newtDrawRootText(14, 0, NAME
" " VERSION
" - " SLOGAN
);
105 sprintf (title
, "%s %s - %s", NAME
, VERSION
, SLOGAN
);
107 if (! (cmdfile
= fopen("/proc/cmdline", "r")))
109 fprintf(flog
, "Couldn't open commandline: /proc/cmdline\n");
111 fgets(line
, STRING_SIZE
, cmdfile
);
113 // check if we have to make an unattended install
114 if (strstr (line
, "unattended") != NULL
) {
116 runcommandwithstatus("/bin/sleep 10", "WARNING: Unattended installation will start in 10 seconds...");
118 // check if we have to patch for serial console
119 if (strstr (line
, "console=ttyS0") != NULL
) {
124 // Load common modules
125 mysystem("/sbin/modprobe iso9660"); // CDROM
126 // mysystem("/sbin/modprobe ext2"); // Boot patition
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 snprintf(commandstring
, STRING_SIZE
, "/sbin/sfdisk -L -uM %s < /tmp/partitiontable", hdparams
.devnode_disk
);
374 if (runcommandwithstatus(commandstring
, ctr
[TR_PARTITIONING_DISK
]))
376 errorbox(ctr
[TR_UNABLE_TO_PARTITION
]);
380 if (fstype
== EXT2
) {
381 // mysystem("/sbin/modprobe ext2");
382 sprintf(mkfscommand
, "/sbin/mke2fs -T ext2");
383 } else if (fstype
== REISERFS
) {
384 mysystem("/sbin/modprobe reiserfs");
385 sprintf(mkfscommand
, "/sbin/mkreiserfs -f");
386 } else if (fstype
== EXT3
) {
387 // mysystem("/sbin/modprobe ext3");
388 sprintf(mkfscommand
, "/sbin/mke2fs -T ext3");
389 } else if (fstype
== EXT4
) {
390 // mysystem("/sbin/modprobe ext4");
391 sprintf(mkfscommand
, "/sbin/mke2fs -T ext4");
394 snprintf(commandstring
, STRING_SIZE
, "/sbin/mke2fs -T ext2 -I 128 %s1", hdparams
.devnode_part
);
395 if (runcommandwithstatus(commandstring
, ctr
[TR_MAKING_BOOT_FILESYSTEM
]))
397 errorbox(ctr
[TR_UNABLE_TO_MAKE_BOOT_FILESYSTEM
]);
402 snprintf(commandstring
, STRING_SIZE
, "/sbin/mkswap %s2", hdparams
.devnode_part
);
403 if (runcommandwithstatus(commandstring
, ctr
[TR_MAKING_SWAPSPACE
]))
405 errorbox(ctr
[TR_UNABLE_TO_MAKE_SWAPSPACE
]);
410 snprintf(commandstring
, STRING_SIZE
, "%s %s3", mkfscommand
, hdparams
.devnode_part
);
411 if (runcommandwithstatus(commandstring
, ctr
[TR_MAKING_ROOT_FILESYSTEM
]))
413 errorbox(ctr
[TR_UNABLE_TO_MAKE_ROOT_FILESYSTEM
]);
417 snprintf(commandstring
, STRING_SIZE
, "%s %s4", mkfscommand
, hdparams
.devnode_part
);
418 if (runcommandwithstatus(commandstring
, ctr
[TR_MAKING_LOG_FILESYSTEM
]))
420 errorbox(ctr
[TR_UNABLE_TO_MAKE_LOG_FILESYSTEM
]);
424 snprintf(commandstring
, STRING_SIZE
, "/bin/mount %s3 /harddisk", hdparams
.devnode_part
);
425 if (runcommandwithstatus(commandstring
, ctr
[TR_MOUNTING_ROOT_FILESYSTEM
]))
427 errorbox(ctr
[TR_UNABLE_TO_MOUNT_ROOT_FILESYSTEM
]);
431 mkdir("/harddisk/boot", S_IRWXU
|S_IRWXG
|S_IRWXO
);
432 mkdir("/harddisk/var", S_IRWXU
|S_IRWXG
|S_IRWXO
);
433 mkdir("/harddisk/var/log", S_IRWXU
|S_IRWXG
|S_IRWXO
);
435 snprintf(commandstring
, STRING_SIZE
, "/bin/mount %s1 /harddisk/boot", hdparams
.devnode_part
);
436 if (runcommandwithstatus(commandstring
, ctr
[TR_MOUNTING_BOOT_FILESYSTEM
]))
438 errorbox(ctr
[TR_UNABLE_TO_MOUNT_BOOT_FILESYSTEM
]);
442 snprintf(commandstring
, STRING_SIZE
, "/sbin/swapon %s2", hdparams
.devnode_part
);
443 if (runcommandwithstatus(commandstring
, ctr
[TR_MOUNTING_SWAP_PARTITION
]))
445 errorbox(ctr
[TR_UNABLE_TO_MOUNT_SWAP_PARTITION
]);
449 snprintf(commandstring
, STRING_SIZE
, "/bin/mount %s4 /harddisk/var", hdparams
.devnode_part
);
450 if (runcommandwithstatus(commandstring
, ctr
[TR_MOUNTING_LOG_FILESYSTEM
]))
452 errorbox(ctr
[TR_UNABLE_TO_MOUNT_LOG_FILESYSTEM
]);
456 snprintf(commandstring
, STRING_SIZE
,
457 "/bin/tar -C /harddisk -xvf /cdrom/" SNAME
"-" VERSION
".tlz --lzma 2>/dev/null");
459 if (runcommandwithprogress(60, 4, title
, commandstring
, INST_FILECOUNT
,
460 ctr
[TR_INSTALLING_FILES
]))
462 errorbox(ctr
[TR_UNABLE_TO_INSTALL_FILES
]);
466 /* Save language und local settings */
467 write_lang_configs(shortlangname
);
469 /* mount proc filesystem */
470 mysystem("mkdir /harddisk/proc");
471 mysystem("/bin/mount --bind /proc /harddisk/proc");
472 mysystem("/bin/mount --bind /dev /harddisk/dev");
473 mysystem("/bin/mount --bind /sys /harddisk/sys");
475 /* Build cache lang file */
476 snprintf(commandstring
, STRING_SIZE
, "/usr/sbin/chroot /harddisk /usr/bin/perl -e \"require '" CONFIG_ROOT
"/lang.pl'; &Lang::BuildCacheLang\"");
477 if (runcommandwithstatus(commandstring
, ctr
[TR_INSTALLING_LANG_CACHE
]))
479 errorbox(ctr
[TR_UNABLE_TO_INSTALL_LANG_CACHE
]);
483 /* Update /etc/fstab */
484 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
);
485 system(commandstring
);
486 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
);
487 system(commandstring
);
488 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
);
489 system(commandstring
);
490 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
);
491 system(commandstring
);
493 if (fstype
== EXT2
) {
494 replace("/harddisk/etc/fstab", "FSTYPE", "ext2");
495 replace("/harddisk/boot/grub/grub.conf", "MOUNT", "ro");
496 } else if (fstype
== REISERFS
) {
497 replace("/harddisk/etc/fstab", "FSTYPE", "reiserfs");
498 replace("/harddisk/boot/grub/grub.conf", "MOUNT", "ro");
499 } else if (fstype
== EXT3
) {
500 replace("/harddisk/etc/fstab", "FSTYPE", "ext3");
501 replace("/harddisk/boot/grub/grub.conf", "MOUNT", "ro");
502 } else if (fstype
== EXT4
) {
503 replace("/harddisk/etc/fstab", "FSTYPE", "ext4");
504 replace("/harddisk/boot/grub/grub.conf", "MOUNT", "ro");
507 replace("/harddisk/boot/grub/grub.conf", "KVER", KERNEL_VERSION
);
509 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
);
510 system(commandstring
);
512 mysystem("ln -s grub.conf /harddisk/boot/grub/menu.lst");
514 system("/bin/sed -e 's#/harddisk#/#g' -e 's#//#/#g' < /proc/mounts > /harddisk/etc/mtab");
517 * Generate device.map to help grub finding the device to install itself on.
520 if (f
= fopen("/harddisk/boot/grub/device.map", "w")) {
521 fprintf(f
, "(hd0) %s\n", hdparams
.devnode_disk
);
525 snprintf(commandstring
, STRING_SIZE
,
526 "/usr/sbin/chroot /harddisk /usr/sbin/grub-install --no-floppy %s", hdparams
.devnode_disk
);
527 if (runcommandwithstatus(commandstring
, ctr
[TR_INSTALLING_GRUB
])) {
528 errorbox(ctr
[TR_UNABLE_TO_INSTALL_GRUB
]);
532 /* Serial console ? */
535 replace("/harddisk/boot/grub/grub.conf", "splashimage", "#splashimage");
536 replace("/harddisk/boot/grub/grub.conf", "#serial", "serial");
537 replace("/harddisk/boot/grub/grub.conf", "#terminal", "terminal");
538 replace("/harddisk/boot/grub/grub.conf", " panic=10 ", " console=ttyS0,38400n8 panic=10 ");
541 replace("/harddisk/etc/inittab", "1:2345:respawn:", "#1:2345:respawn:");
542 replace("/harddisk/etc/inittab", "2:2345:respawn:", "#2:2345:respawn:");
543 replace("/harddisk/etc/inittab", "3:2345:respawn:", "#3:2345:respawn:");
544 replace("/harddisk/etc/inittab", "4:2345:respawn:", "#4:2345:respawn:");
545 replace("/harddisk/etc/inittab", "5:2345:respawn:", "#5:2345:respawn:");
546 replace("/harddisk/etc/inittab", "6:2345:respawn:", "#6:2345:respawn:");
547 replace("/harddisk/etc/inittab", "#7:2345:respawn:", "7:2345:respawn:");
550 /* Set marker that the user has already accepted the gpl */
551 mysystem("/usr/bin/touch /harddisk/var/ipfire/main/gpl_accepted");
553 /* Copy restore file from cdrom */
554 if (unattended
&& (strlen(restore_file
) > 0)) {
555 fprintf(flog
, "unattended: Copy restore file\n");
556 snprintf(commandstring
, STRING_SIZE
,
557 "cp /cdrom/%s /harddisk/var/ipfire/backup", restore_file
);
558 mysystem(commandstring
);
561 mysystem("umount /cdrom");
562 snprintf(commandstring
, STRING_SIZE
, "/usr/bin/eject /dev/%s", sourcedrive
);
563 mysystem(commandstring
);
566 sprintf(message
, ctr
[TR_CONGRATULATIONS_LONG
],
568 newtWinMessage(ctr
[TR_CONGRATULATIONS
], ctr
[TR_PRESS_OK_TO_REBOOT
], 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
)
584 fprintf(flog
, "Entering unattended setup\n");
585 if (unattended_setup(unattendedkv
)) {
586 snprintf(commandstring
, STRING_SIZE
, "/bin/sleep 10");
587 runcommandwithstatus(commandstring
, "Unattended installation finished, system will reboot");
589 errorbox("Unattended setup failed.");
599 // Remove Setup autorun after boot
600 if (system("rm -f /harddisk/etc/rc.d/rcsysinit.d/S75firstsetup"))
601 printf("Unable to disable setup autorun.\n");
604 if (system("/bin/umount /harddisk/proc"))
605 printf("Unable to umount /harddisk/proc.\n");
615 snprintf(commandstring
, STRING_SIZE
, "/bin/swapoff %s2", hdparams
.devnode_part
);
620 system("/bin/umount /harddisk/proc >/dev/null 2>&1");
621 system("/bin/umount /harddisk/dev >/dev/null 2>&1");
622 system("/bin/umount /harddisk/sys >/dev/null 2>&1");
624 system("/bin/umount /harddisk/var >/dev/null 2>&1");
625 system("/bin/umount /harddisk/boot >/dev/null 2>&1");
626 system("/bin/umount /harddisk >/dev/null 2>&1");