Merge branch 'master' into next
[people/pmueller/ipfire-2.x.git] / src / install+setup / install / main.c
1 /* SmoothWall install program.
2  *
3  * This program is distributed under the terms of the GNU General Public
4  * Licence.  See the file COPYING for details.
5  *
6  * (c) Lawrence Manning, 2001
7  * Contains main entry point, and misc functions.6
8  * 
9  */
10
11 #include "install.h"
12 #define _GNU_SOURCE
13  
14 #define INST_FILECOUNT 8400
15 #define UNATTENDED_CONF "/cdrom/boot/unattended.conf"
16
17 #define EXT2 0
18 #define REISERFS 2
19 #define EXT3 1
20
21 FILE *flog = NULL;
22 char *mylog;
23
24 char **ctr;
25
26 extern char url[STRING_SIZE];
27
28 struct  nic  nics[20] = { { "" , "" , "" } }; // only defined for compile
29 struct knic knics[20] = { { "" , "" , "" , "" } }; // only defined for compile
30
31 extern char *en_tr[];
32 extern char *es_tr[];
33 extern char *de_tr[];
34 extern char *fr_tr[];
35
36 int main(int argc, char *argv[])
37 {
38         char *langnames[] = { "Deutsch", "English", "Français", "Español", NULL };
39         char *shortlangnames[] = { "de", "en", "fr", "es", NULL };
40         char **langtrs[] = { de_tr, en_tr, fr_tr, es_tr, NULL };
41         char hdletter;
42         char harddrive[30], sourcedrive[5];     /* Device holder. */
43         struct devparams hdparams, cdromparams; /* Params for CDROM and HD */
44         int rc = 0;
45         char commandstring[STRING_SIZE];
46         char mkfscommand[STRING_SIZE];
47         char *fstypes[] = { "ext2", "ext3", "ReiserFS", NULL };
48         int fstype = REISERFS;
49         int choice;
50         int i;
51         int found = 0;
52         int firstrun = 0;
53         char shortlangname[10];
54         char message[1000];
55         char title[STRING_SIZE];
56         int allok = 0;
57         int allok_fastexit=0;
58         int raid_disk = 0;
59         struct keyvalue *ethernetkv = initkeyvalues();
60         FILE *handle, *cmdfile;
61         char line[STRING_SIZE];
62         char string[STRING_SIZE];
63         long memory = 0, disk = 0, free;
64         long system_partition, boot_partition, root_partition, swap_file;
65         int scsi_disk = 0;
66         char *yesnoharddisk[3]; //      char *yesnoharddisk = { "NO", "YES", NULL };
67                 
68         int unattended = 0;
69         struct keyvalue *unattendedkv = initkeyvalues();
70         int hardyn = 0;
71         char restore_file[STRING_SIZE] = "";
72
73         setlocale (LC_ALL, "");
74         sethostname( SNAME , 10);
75
76         memset(&hdparams, 0, sizeof(struct devparams));
77         memset(&cdromparams, 0, sizeof(struct devparams));
78
79         /* Log file/terminal stuff. */
80         if (argc >= 2)
81         {               
82                 if (!(flog = fopen(argv[1], "w+")))
83                         return 0;
84         }
85         else
86                 return 0;
87         
88         mylog = argv[1];
89         
90         fprintf(flog, "Install program started.\n");
91                 
92         newtInit();
93         newtCls();
94
95         newtDrawRootText(14, 0, NAME " " VERSION " - " SLOGAN );
96         sprintf (title, "%s %s - %s", NAME, VERSION, SLOGAN);
97
98         if (! (cmdfile = fopen("/proc/cmdline", "r")))
99         {
100                 fprintf(flog, "Couldn't open commandline: /proc/cmdline\n");
101         } else {
102                 fgets(line, STRING_SIZE, cmdfile);
103                 
104                 // check if we have to make an unattended install
105                 if (strstr (line, "unattended") != NULL) {
106                     unattended = 1;
107                     runcommandwithstatus("/bin/sleep 10", "WARNING: Unattended installation will start in 10 seconds...");
108                 }               
109         }
110
111         // Load common modules
112         mysystem("/sbin/modprobe iso9660"); // CDROM
113         mysystem("/sbin/modprobe ext2"); // Boot patition
114         mysystem("/sbin/modprobe vfat"); // USB key
115         
116         /* German is the default */
117         for (choice = 0; langnames[choice]; choice++)
118         {
119                 if (strcmp(langnames[choice], "Deutsch") == 0)
120                         break;
121         }
122         if (!langnames[choice])
123                 goto EXIT;
124
125         if (!unattended) {
126             rc = newtWinMenu("Language selection", "Select the language you wish to use for the " NAME ".", 50, 5, 5, 8,
127                     langnames, &choice, "Ok", NULL);
128         }
129
130         ctr = langtrs[choice];
131         strcpy(shortlangname, shortlangnames[choice]);
132
133         newtPushHelpLine(ctr[TR_HELPLINE]);
134
135         sprintf(message, ctr[TR_WELCOME], NAME);
136         newtWinMessage(title, ctr[TR_OK], message);
137
138         switch (mysystem("/bin/mountsource.sh")) {
139             case 0:
140                                 break;
141             case 10:
142         errorbox(ctr[TR_NO_CDROM]);
143                 goto EXIT;
144         }
145
146         /* read source drive letter */
147         if ((handle = fopen("/tmp/source_device", "r")) == NULL) {
148                 errorbox(ctr[TR_ERROR_PROBING_CDROM]);
149                 goto EXIT;
150         }
151         fgets(sourcedrive, 5, handle);
152         fprintf(flog, "Source drive: %s\n", sourcedrive);
153         fclose(handle);
154         
155         i = 0;
156         while (found == 0) {
157                 i++;
158                 fprintf(flog, "Harddisk scan pass %i\n", i);
159
160                 switch (mysystem("/bin/mountdest.sh") % 255) {
161                         case 0: // Found IDE disk
162                                 scsi_disk = 0;
163                                 raid_disk = 0;
164                                 found = 1;
165                                 break;
166                         case 1: // Found SCSI disk
167                                 scsi_disk = 1;
168                                 raid_disk = 0;
169                                 found = 1;
170                                 break;
171                         case 2: // Found RAID disk
172                                 scsi_disk = 0;
173                                 raid_disk= 1;
174                                 found = 1;
175                                 break;
176                         case 10: // No harddisk found
177                                 if (firstrun == 1) {
178                                         errorbox(ctr[TR_NO_HARDDISK]);
179                                         goto EXIT;
180                                 }
181                                 // Do this if the kudzu-scan fails...
182                                 runcommandwithstatus("/bin/probehw.sh deep-scan", ctr[TR_PROBING_HARDWARE]);
183                                 firstrun = 1;
184                 }
185         }
186
187         if ((handle = fopen("/tmp/dest_device", "r")) == NULL) {
188                 errorbox(ctr[TR_NO_HARDDISK]);
189                 goto EXIT;
190         }
191         fgets(harddrive, 30, handle);
192         fclose(handle);
193                         
194         /* load unattended configuration */
195         if (unattended) {
196             fprintf(flog, "unattended: Reading unattended.conf\n");
197
198             (void) readkeyvalues(unattendedkv, UNATTENDED_CONF);
199             findkey(unattendedkv, "RESTORE_FILE", restore_file);            
200         }
201         
202         /* Make the hdparms struct and print the contents.
203            With USB-KEY install and SCSI disk, while installing, the disk
204            is named 'sdb,sdc,...' (following keys)
205            On reboot, it will become 'sda'
206            To avoid many test, all names are built in the struct.
207         */
208         sprintf(hdparams.devnode_disk, "/dev/%s", harddrive);
209         /* Address the partition or raid partition (eg dev/sda or /dev/sdap1 */
210         sprintf(hdparams.devnode_part, "/dev/%s%s", harddrive,raid_disk ? "p" : "");
211         /* Now the names after the machine is booted. Only scsi is affected
212            and we only install on the first scsi disk. */
213
214         fprintf(flog, "Destination drive: %s\n", hdparams.devnode_disk);
215         
216         sprintf(message, ctr[TR_PREPARE_HARDDISK], hdparams.devnode_disk);
217         if (unattended) {
218             hardyn = 1;
219         } else {
220                 yesnoharddisk[0] = ctr[TR_NO];
221                 yesnoharddisk[1] = ctr[TR_YES];
222                 yesnoharddisk[2] = NULL;
223         }
224
225         while (! hardyn) {
226                 rc = newtWinMenu(title, message,
227                                  50, 5, 5, 6, yesnoharddisk,
228                                  &hardyn, ctr[TR_OK],
229                                  ctr[TR_CANCEL], NULL);
230                 if (rc == 2)
231                         goto EXIT;
232         }
233         if (rc == 2)
234                 goto EXIT;
235
236         if (!unattended) {              
237                 sprintf(message, ctr[TR_CHOOSE_FILESYSTEM]);
238                 rc = newtWinMenu( ctr[TR_CHOOSE_FILESYSTEM], message,
239                         50, 5, 5, 6, fstypes, &fstype, ctr[TR_OK],
240                         ctr[TR_CANCEL], NULL);
241         } else {
242             rc = 1;
243             fstype = REISERFS;
244         }
245         if (rc == 2)
246                 goto EXIT;
247
248         /* Calculate amount of memory in machine */
249         if ((handle = fopen("/proc/meminfo", "r")))
250         {
251             while (fgets(line, STRING_SIZE-1, handle)) {
252                 if (sscanf (line, "MemTotal: %s kB", string)) {
253                     memory = atoi(string) / 1024 ;
254                 }
255             }
256             fclose(handle);
257         }
258
259         /* Partition, mkswp, mkfs.
260          * before partitioning, first determine the sizes of each
261          * partition.  In order to do that we need to know the size of
262          * the disk. 
263          */
264         /* Don't use mysystem here so we can redirect output */
265         sprintf(commandstring, "/sbin/sfdisk -s /dev/%s > /tmp/disksize 2> /dev/null", harddrive);
266         system(commandstring);
267
268         /* Calculate amount of disk space */
269         if ((handle = fopen("/tmp/disksize", "r"))) {
270                 fgets(line, STRING_SIZE-1, handle);
271                 if (sscanf (line, "%s", string)) {
272                         disk = atoi(string) / 1024;
273                 }
274                 fclose(handle);
275         }
276         
277         fprintf(flog, "Disksize = %ld, memory = %ld", disk, memory);
278         
279          /* Calculating Swap-Size dependend of Ram Size */
280         if (memory <= 256)
281                 swap_file = 128;
282         else if (memory <= 1024 && memory > 256)
283                 swap_file = 256;
284         else 
285                 swap_file = memory / 4;
286         
287   /* Calculating Root-Size dependend of Max Disk Space */
288   if ( disk < 756 )
289                 root_partition = 200;
290         else if ( disk >= 756 && disk <= 3072 )
291                 root_partition = 512;
292         else 
293                 root_partition = 2048;
294                 
295         
296   /* Calculating the amount of free space */
297         boot_partition = 20; /* in MB */
298         system_partition = disk - ( root_partition + swap_file + boot_partition );
299         
300         fprintf(flog, ", boot = %ld, swap = %ld, mylog = %ld, root = %ld\n",
301         boot_partition, swap_file, system_partition, root_partition);
302         rc = 0;
303
304         if ( (!unattended) && (((disk - (root_partition + swap_file + boot_partition)) < 256 ) && ((disk - (root_partition + boot_partition )) > 256)) ) {
305    rc = newtWinChoice(title, ctr[TR_OK], ctr[TR_CANCEL], ctr[TR_CONTINUE_NO_SWAP]);
306     if (rc == 1){
307       swap_file = 0;
308       system_partition = disk - ( root_partition + swap_file + boot_partition );
309       fprintf(flog, "Changing Swap Size to 0 MB.\n");
310     }
311     else if (rc == 2){
312     fprintf(flog, "Disk is too small.\n");
313     errorbox(ctr[TR_DISK_TOO_SMALL]);goto EXIT;
314     }
315   } 
316   else if (disk - (root_partition + swap_file + boot_partition) >= 256) {
317   
318   }
319   else {
320    fprintf(flog, "Disk is too small.\n");
321    errorbox(ctr[TR_DISK_TOO_SMALL]);goto EXIT;
322   }
323          
324         handle = fopen("/tmp/partitiontable", "w");
325
326         /* Make swapfile */
327   if (swap_file) {
328      fprintf(handle, ",%ld,L,*\n,%ld,S,\n,%ld,L,\n,,L,\n",
329      boot_partition, swap_file, root_partition);
330   } else {
331      fprintf(handle, ",%ld,L,*\n,0,0,\n,%ld,L,\n,,L,\n",
332      boot_partition, root_partition);
333   }
334
335         fclose(handle);
336
337         snprintf(commandstring, STRING_SIZE, "/sbin/sfdisk -L -uM %s < /tmp/partitiontable", hdparams.devnode_disk);
338         if (runcommandwithstatus(commandstring, ctr[TR_PARTITIONING_DISK]))
339         {
340                 errorbox(ctr[TR_UNABLE_TO_PARTITION]);
341                 goto EXIT;
342         }
343         
344         if (fstype == EXT2) {
345                 mysystem("/sbin/modprobe ext2");
346                 sprintf(mkfscommand, "/sbin/mke2fs -T ext2");
347         } else if (fstype == REISERFS) {
348                 mysystem("/sbin/modprobe reiserfs");
349                 sprintf(mkfscommand, "/sbin/mkreiserfs -f");
350         } else if (fstype == EXT3) {
351                 mysystem("/sbin/modprobe ext3");
352                 sprintf(mkfscommand, "/sbin/mke2fs -T ext3");
353         }
354
355         snprintf(commandstring, STRING_SIZE, "/sbin/mke2fs -T ext2 -I 128 %s1", hdparams.devnode_part);
356         if (runcommandwithstatus(commandstring, ctr[TR_MAKING_BOOT_FILESYSTEM]))
357         {
358                 errorbox(ctr[TR_UNABLE_TO_MAKE_BOOT_FILESYSTEM]);
359                 goto EXIT;
360         }
361
362         if (swap_file) {
363                 snprintf(commandstring, STRING_SIZE, "/sbin/mkswap %s2", hdparams.devnode_part);
364                 if (runcommandwithstatus(commandstring, ctr[TR_MAKING_SWAPSPACE]))
365                 {
366                         errorbox(ctr[TR_UNABLE_TO_MAKE_SWAPSPACE]);
367                         goto EXIT;
368                 }
369         }
370
371         snprintf(commandstring, STRING_SIZE, "%s %s3", mkfscommand, hdparams.devnode_part);
372         if (runcommandwithstatus(commandstring, ctr[TR_MAKING_ROOT_FILESYSTEM]))
373         {
374                 errorbox(ctr[TR_UNABLE_TO_MAKE_ROOT_FILESYSTEM]);
375                 goto EXIT;
376         }
377
378         snprintf(commandstring, STRING_SIZE, "%s %s4", mkfscommand, hdparams.devnode_part);     
379         if (runcommandwithstatus(commandstring, ctr[TR_MAKING_LOG_FILESYSTEM]))
380         {
381                 errorbox(ctr[TR_UNABLE_TO_MAKE_LOG_FILESYSTEM]);
382                 goto EXIT;
383         }
384
385         snprintf(commandstring, STRING_SIZE, "/bin/mount %s3 /harddisk", hdparams.devnode_part);
386         if (runcommandwithstatus(commandstring, ctr[TR_MOUNTING_ROOT_FILESYSTEM]))
387         {
388                 errorbox(ctr[TR_UNABLE_TO_MOUNT_ROOT_FILESYSTEM]);
389                 goto EXIT;
390         }
391
392         mkdir("/harddisk/boot", S_IRWXU|S_IRWXG|S_IRWXO);
393         mkdir("/harddisk/var", S_IRWXU|S_IRWXG|S_IRWXO);
394         mkdir("/harddisk/var/log", S_IRWXU|S_IRWXG|S_IRWXO);
395         
396         snprintf(commandstring, STRING_SIZE, "/bin/mount %s1 /harddisk/boot", hdparams.devnode_part);
397         if (runcommandwithstatus(commandstring, ctr[TR_MOUNTING_BOOT_FILESYSTEM]))
398         {
399                 errorbox(ctr[TR_UNABLE_TO_MOUNT_BOOT_FILESYSTEM]);
400                 goto EXIT;
401         }
402         if (swap_file) {
403                 snprintf(commandstring, STRING_SIZE, "/sbin/swapon %s2", hdparams.devnode_part);
404                 if (runcommandwithstatus(commandstring, ctr[TR_MOUNTING_SWAP_PARTITION]))
405                 {
406                         errorbox(ctr[TR_UNABLE_TO_MOUNT_SWAP_PARTITION]);
407                         goto EXIT;
408                 }
409         }
410         snprintf(commandstring, STRING_SIZE, "/bin/mount %s4 /harddisk/var", hdparams.devnode_part);
411         if (runcommandwithstatus(commandstring, ctr[TR_MOUNTING_LOG_FILESYSTEM]))
412         {
413                 errorbox(ctr[TR_UNABLE_TO_MOUNT_LOG_FILESYSTEM]);
414                 goto EXIT;
415         }
416
417         snprintf(commandstring, STRING_SIZE,
418                 "/bin/tar -C /harddisk  -xvf /cdrom/" SNAME "-" VERSION ".tlz --lzma 2>/dev/null");
419         
420         if (runcommandwithprogress(60, 4, title, commandstring, INST_FILECOUNT,
421                 ctr[TR_INSTALLING_FILES]))
422         {
423                 errorbox(ctr[TR_UNABLE_TO_INSTALL_FILES]);
424                 goto EXIT;
425         }
426         
427         /* Save language und local settings */
428         write_lang_configs(shortlangname);
429
430         /* Rename uname */
431         rename ("/harddisk/bin/uname.bak", "/harddisk/bin/uname");
432
433         /* mount proc filesystem */
434         mysystem("mkdir /harddisk/proc");
435         mysystem("/bin/mount --bind /proc /harddisk/proc");
436         mysystem("/bin/mount --bind /dev  /harddisk/dev");
437         mysystem("/bin/mount --bind /sys  /harddisk/sys");
438
439         /* Build cache lang file */
440         snprintf(commandstring, STRING_SIZE, "/usr/sbin/chroot /harddisk /usr/bin/perl -e \"require '" CONFIG_ROOT "/lang.pl'; &Lang::BuildCacheLang\"");
441         if (runcommandwithstatus(commandstring, ctr[TR_INSTALLING_LANG_CACHE]))
442         {
443                 errorbox(ctr[TR_UNABLE_TO_INSTALL_LANG_CACHE]);
444                 goto EXIT;
445         }
446
447         /* Update /etc/fstab */
448         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);
449         system(commandstring);
450         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);
451         system(commandstring);
452         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);
453         system(commandstring);
454         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);
455         system(commandstring);
456
457         if (fstype == EXT2) {
458                 replace("/harddisk/etc/fstab", "FSTYPE", "ext2");
459                 replace("/harddisk/boot/grub/grub.conf", "MOUNT", "ro");
460         } else if (fstype == REISERFS) {
461                 replace("/harddisk/etc/fstab", "FSTYPE", "reiserfs");
462                 replace("/harddisk/boot/grub/grub.conf", "MOUNT", "ro");
463         } else if (fstype == EXT3) {
464                 replace("/harddisk/etc/fstab", "FSTYPE", "ext3");
465                 NOJOURNAL:
466                 replace("/harddisk/boot/grub/grub.conf", "MOUNT", "ro");
467         }
468
469         replace("/harddisk/boot/grub/grub.conf", "KVER", KERNEL_VERSION);
470
471         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);
472         system(commandstring);
473
474         mysystem("ln -s grub.conf /harddisk/boot/grub/menu.lst");
475
476         system("/bin/sed -e 's#/harddisk#/#g' -e 's#//#/#g'  < /proc/mounts > /harddisk/etc/mtab");
477
478         snprintf(commandstring, STRING_SIZE, 
479                  "/usr/sbin/chroot /harddisk /usr/sbin/grub-install --no-floppy %s", hdparams.devnode_disk);
480         if (runcommandwithstatus(commandstring, ctr[TR_INSTALLING_GRUB])) {
481                 errorbox(ctr[TR_UNABLE_TO_INSTALL_GRUB]);
482                 goto EXIT;
483         }
484         
485         /* Copy restore file from cdrom */
486         if (unattended && (strlen(restore_file) > 0)) {
487                 fprintf(flog, "unattended: Copy restore file\n");
488                 snprintf(commandstring, STRING_SIZE, 
489                         "cp /cdrom/%s /harddisk/var/ipfire/backup", restore_file);
490                 mysystem(commandstring);
491         }
492         
493         mysystem("umount /cdrom");
494         snprintf(commandstring, STRING_SIZE, "/usr/bin/eject /dev/%s", sourcedrive);
495         mysystem(commandstring);
496
497         if (!unattended) {
498                 sprintf(message, ctr[TR_CONGRATULATIONS_LONG],
499                                 NAME, SNAME, NAME);
500                 newtWinMessage(ctr[TR_CONGRATULATIONS], ctr[TR_OK], message);
501         }
502
503         allok = 1;
504
505 EXIT:
506         fprintf(flog, "Install program ended.\n");      
507
508         if (!(allok))
509                 newtWinMessage(title, ctr[TR_OK], ctr[TR_PRESS_OK_TO_REBOOT]);  
510         
511         freekeyvalues(ethernetkv);
512
513         if (allok && !allok_fastexit)
514         {
515                 if (unattended) {
516                         fprintf(flog, "Entering unattended setup\n");
517                         if (unattended_setup(unattendedkv)) {
518                                 snprintf(commandstring, STRING_SIZE, "/bin/sleep 10");
519                                 runcommandwithstatus(commandstring, "Unattended installation finished, system will reboot");
520                         } else {
521                                 errorbox("Unattended setup failed.");
522                                 goto EXIT;
523                         }
524                 }
525
526                 fflush(flog);
527                 fclose(flog);
528                 newtFinished();
529
530 //              if (!unattended) {
531 //                      if (system("/usr/sbin/chroot /harddisk /usr/local/sbin/setup /dev/tty2 INSTALL"))
532 //                              printf("Unable to run setup.\n");
533 //              }
534
535                 if (system("/bin/umount /harddisk/proc"))
536                         printf("Unable to umount /harddisk/proc.\n"); 
537         } else {
538                 fflush(flog);
539                 fclose(flog);
540                 newtFinished();
541         }
542
543         fcloseall();
544
545         if (swap_file) {
546                 snprintf(commandstring, STRING_SIZE, "/bin/swapoff %s2", hdparams.devnode_part);
547         }
548
549         newtFinished();
550
551         system("/bin/umount /harddisk/proc");
552         system("/bin/umount /harddisk/dev");
553         system("/bin/umount /harddisk/sys");
554
555         system("/bin/umount /harddisk/var");
556         system("/bin/umount /harddisk/boot");
557         system("/bin/umount /harddisk");
558
559         if (!(allok))
560                 system("/etc/halt");
561
562         return 0;
563 }