Add externs to avoid multiple definitions, and then add missing definitions.
[rrq/maintain_lilo.git] / src / lilo.c
1 /* lilo.c  -  LILO command-line parameter processing
2  * 
3  * Copyright 1992-1998 Werner Almesberger
4  * Copyright 1999-2007 John Coffman
5  * Copyright 2009-2015 Joachim Wiedorn
6  * All rights reserved.
7  * 
8  * Licensed under the terms contained in the file 'COPYING'
9  * in the source directory.
10  */
11
12 #define _GNU_SOURCE
13 #include <stdlib.h>
14 #include <unistd.h>
15 #include <stdio.h>
16 #include <string.h>
17 #include <ctype.h>
18 #include <fcntl.h>
19 #include <errno.h>
20 #include <time.h>
21 #include <limits.h>
22 #include <dirent.h>
23 /*#include <asm/page.h>*/
24
25 #include "config.h"
26 #include "lilo.h"
27 #include "common.h"
28 #include "cfg.h"
29
30 #if !__MSDOS__
31 #include "raid.h"
32 #include "boot.h"
33 #include "device.h"
34 #include "flags.i"
35 #include "geometry.h"
36 #endif /* !__MSDOS__ */
37 #include "map.h"
38 #if !__MSDOS__
39 #include "bsect.h"
40 #include "identify.h"
41 #include "partition.h"
42 #include "probe.h"
43 #include "temp.h"
44 #include "loader.h"
45 #include "md-int.h"
46 #include "edit.h"
47 #endif /* !__MSDOS__ */
48
49
50 char *config_file;              /* actual name of the config file */
51 int config_read;                /* readable by other than root */
52 FILE *errstd;
53
54 static void configuration(void)
55 {
56 #if VERSION_MINOR>=50 && !__MSDOS__
57 {
58                 printf(
59                 "-DBOOT_PARAMS_1=%d -DBOOT_PARAMS_2=%d  PATH_MAX=%d"
60                   "\n"
61                   ,
62                   (int)sizeof(BOOT_PARAMS_1),
63                   (int)sizeof(BOOT_PARAMS_2),
64                   PATH_MAX
65                      );
66 }
67 {
68 #include "bitmap.h"
69         RGB pal[16];
70         RGB2 pal2[16];
71         
72         printf("\nBMFH=%d BMH=%d BMH2=%d RGB=%d(%d) RGB2=%d(%d) LH=%d\n",
73         (int)sizeof(BITMAPFILEHEADER),
74         (int)sizeof(BITMAPHEADER),
75         (int)sizeof(BITMAPHEADER2),
76         (int)sizeof(RGB),
77         (int)sizeof(pal),
78         (int)sizeof(RGB2),
79         (int)sizeof(pal2),
80         (int)sizeof(BITMAPLILOHEADER) );
81         printf("\nBPB=%d BP_DOS=%d\n",
82                 (int)sizeof(BIOS_PARAMETER_BLOCK),
83                 (int)sizeof(BOOT_PARAMS_DOS)
84                   );
85 }
86 #ifdef LCF_FIRST6
87         printf("\nSECTOR_ADDR6=%d\n", (int)sizeof(SECTOR_ADDR6));
88 #endif
89
90 #endif /* VERSION_MINOR>=50 && !__MSDOS__ */
91
92 #if !__MSDOS__
93 {
94   unsigned int j;
95   if (verbose>=5) {
96     if (crc(First.data,First.size)) {
97         j = crc(First.data,First.size-4);
98         brev(j);
99         printf("1=0x%x\n", j);
100     }
101     if (crc(Second.data,Second.size)) {
102         j = crc(Second.data,Second.size-4);
103         brev(j);
104         printf("2=0x%x\n", j);
105     }
106     if (crc(Third.data,Third.size)) {
107         j = crc(Third.data,Third.size-4);
108         brev(j);
109         printf("3=0x%x\n", j);
110     }
111     if (crc(Bitmap.data,Bitmap.size)) {
112         j = crc(Bitmap.data,Bitmap.size-4);
113         brev(j);
114         printf("B=0x%x\n", j);
115     }
116     if (crc(Chain.data,Chain.size)) {
117         j = crc(Chain.data,Chain.size-4);
118         brev(j);
119         printf("C=0x%x\n", j);
120     }
121     if (crc(Mbr.data,Mbr.size)) {
122         j = crc(Mbr.data,Mbr.size-4);
123         brev(j);
124         printf("M=0x%x\n", j);
125     }
126     if (crc(Mbr2.data,Mbr2.size)) {
127         j = crc(Mbr2.data,Mbr2.size-4);
128         brev(j);
129         printf("N=0x%x\n\n", j);
130     }
131   }
132 }
133
134 #if BETA_TEST
135 {
136     int i, j, k=0;
137 extern int has_partitions_beta(dev_t dev);      /* defined in geometry.c */
138
139
140     printf("\n");
141     for (i=0; i<256; i++) {
142         if ( has_partitions_beta(MKDEV(i,0)) != has_partitions(MKDEV(i,0)) ) {
143             printf("Major device = %d is not configured.\n", i);
144             k ++;
145         }
146     }
147     printf("%sk = %d (should be 0)\n\n", k?"ERROR: ":"", k);
148     for (i=0, j=0; i<40960; i+=17) {
149         dev_t dev;
150         int major, minor;
151         for (k=0; k<81920; k+=19) {
152             dev = MKDEV(i,k);
153             major = MAJOR(dev);
154             minor = MINOR(dev);
155             if (major != i  ||  minor != k) {
156                 printf("ERROR: (%d,%d) -> (%d,%d)\n",
157                     i, k, major, minor);
158                 j++;
159             }
160         }
161     }
162     if (j==0) printf("MKDEV check passed\n");
163 }
164 #endif
165
166 #if VERSION_MINOR>=50
167 {
168         dev_t dev; int i;
169         BOOT_VOLID x;
170         BOOT_SECTOR b;
171         dev = 0xFFF0;
172         i = dev;
173         printf("dev_t is %ssigned size=%d  i=%08X\n", i==0xFFF0 ? "un" : "", (int)sizeof(dev_t), i);
174         printf("size of BOOT_VOLID = %d   BOOT_SECTOR = %d\n", (int)sizeof(x), (int)sizeof(b));
175         printf("Size of MENUTABLE = %d\n", (int)sizeof(MENUTABLE));
176 }
177 #endif
178                 printf("\nCFLAGS = " CFLAGS "\n");
179 #if defined(LCF_DEVMAPPER) && defined(HAS_LIBDEVMAPPER_H)
180                 printf("With");
181 #else
182                 printf("Without");
183 #endif
184                 printf(" device-mapper\n");
185                 printf("\nglibc version %d.%d\n", __GLIBC__, __GLIBC_MINOR__);
186                 printf("Kernel Headers included from  %d.%d.%d\n",
187                         LINUX_VERSION_CODE>>16,
188                         LINUX_VERSION_CODE>>8 & 255,
189                         LINUX_VERSION_CODE & 255);
190                 printf("Maximum Major Device = %d\n", MAJOR(~0UL));
191 #endif /* !__MSDOS__ */
192                 printf("MAX_IMAGES = %d\t\tc=%d, s=%d, i=%d, "
193                                 "l=%d, ll=%d, f=%d, d=%d, ld=%d\n",
194                         MAX_IMAGES, (int)sizeof(char),
195                         (int)sizeof(short), (int)sizeof(int),
196                         (int)sizeof(int32_t), (int)sizeof(
197 #if !__MSDOS__
198                         int64_t),
199 #else
200                         int32_t),
201 #endif /* !__MSDOS__ */
202                         (int)sizeof(float), (int)sizeof(double),
203                         (int)sizeof(long double)
204                         );
205                 printf("IMAGE_DESCR = %d   DESCR_SECTORS = %d\n\n",
206                         (int)sizeof(IMAGE_DESCR), (int)sizeof(DESCR_SECTORS));
207 }
208
209 #if !__MSDOS__
210
211 static void show_other(int fd)
212 {
213     BOOT_SECTOR buf[SETUPSECS-1];
214     const unsigned char *drvmap;
215     const unsigned char *prtmap;
216
217     if (read(fd,buf,sizeof(buf)) != sizeof(buf))
218         die("Read on map file failed (access conflict ?) 1");
219     if (!strncmp(buf[0].par_c.signature-4,"LILO",4)) {
220         printf("    Pre-21 signature (0x%02x,0x%02x,0x%02x,0x%02x)\n",
221           buf[0].par_c.signature[0],buf[0].par_c.signature[1],
222           buf[0].par_c.signature[2],buf[0].par_c.signature[3]);
223         return;
224     }
225     if (strncmp(buf[0].par_c.signature,"LILO",4)) {
226         printf("    Bad signature (0x%02x,0x%02x,0x%02x,0x%02x)\n",
227           buf[0].par_c.signature[0],buf[0].par_c.signature[1],
228           buf[0].par_c.signature[2],buf[0].par_c.signature[3]);
229         return;
230     }
231     drvmap = ((unsigned char *) buf+buf[0].par_c.drvmap);
232     prtmap = drvmap+2*(DRVMAP_SIZE+1);
233     while (drvmap[0] && drvmap[1]) {
234         if (drvmap[0]==0xFF && drvmap[1]==0xFF) {
235             if (drvmap[3]==0xFF) printf("    Master-Boot:  This BIOS drive will always appear as 0x80 (or 0x00)\n");
236             else printf("    Boot-As:  This BIOS drive will always appear as 0x%02X\n", drvmap[3]);
237             drvmap += 4;
238         } else {
239             printf("    BIOS drive 0x%02X is mapped to 0x%02X\n",drvmap[0],
240                                                 drvmap[1]);
241             drvmap += 2;
242         }
243     }
244     /* fix VERY old bug -- offset of 0 in PT is okay */
245     while (prtmap[0] /*** && prtmap[1] ***/ ) {
246         printf("    BIOS drive 0x%02x, offset 0x%x: 0x%02x -> 0x%02x\n",
247           prtmap[0],prtmap[1]+PART_TABLE_OFFSET,prtmap[2],prtmap[3]);
248         prtmap += 4;
249     }
250 }
251 #endif /* !__MSDOS__ */
252
253 static void show_images(char *map_file)
254 {
255 #if !__MSDOS__
256     DESCR_SECTORS descrs;
257     BOOT_SECTOR boot;
258     MENUTABLE menu;
259     BOOT_PARAMS_2 param2;
260     GEOMETRY geo;
261     SECTOR_ADDR addr[4];
262     char buffer[SECTOR_SIZE];
263 #else /* __MSDOS */
264 static DESCR_SECTORS descrs;
265 static char buffer[SECTOR_SIZE];
266 #endif /*__MSDOS__ */
267     char *name;
268     int fd,image;
269     int tsecs;
270     int tlinear, tlba32;
271     unsigned short flags;
272     time_t Time;
273
274 #if !__MSDOS__
275     fd = geo_open(&geo,map_file,O_RDONLY);
276 #else  /* __MSDOS__ */
277     if ((fd = open(map_file,O_RDONLY))<=0)
278         die("Cannot open map file: %s", map_file);
279 #endif /* __MSDOS__ */
280     if (read(fd,buffer,SECTOR_SIZE) != SECTOR_SIZE)
281         die("read cmdline %s: %s",map_file,strerror(errno));
282     if (read(fd,(char*)&descrs,sizeof(descrs)) != sizeof(descrs))
283         die("read descrs %s: %s",map_file,strerror(errno));
284 #if !__MSDOS__
285     if (lseek(fd, SECTOR_SIZE, SEEK_CUR) <= 0)  /* skip zero sector */
286         die("lseek over zero sector %s: %s",map_file,strerror(errno));
287     if (read(fd,(char*)&param2,sizeof(param2)) != sizeof(param2))
288         die("read second params %s: %s",map_file,strerror(errno));
289     if (lseek(fd, - sizeof(menu), SEEK_END) <= 0)
290         die("lseek keytable %s: %s",map_file,strerror(errno));
291     if (read(fd,(char*)&menu,sizeof(menu)) != sizeof(menu))
292         die("read keytable %s: %s",map_file,strerror(errno));
293     tlba32  = (descrs.d.descr[0].start.device & LBA32_FLAG) != 0;
294     tlinear = !tlba32 && (descrs.d.descr[0].start.device & LINEAR_FLAG);
295     if (tlinear != linear  ||  tlba32 != lba32) {
296         printf("Warning: mapfile created with %s option\n",
297                tlinear?"linear":tlba32?"lba32":"no linear/lba32");
298         linear = tlinear;  lba32 = tlba32;
299     }
300     if (verbose) {
301         bsect_read(cfg_get_strg(cf_options,"boot"),&boot);
302 #if 1
303         if (boot.par_1.cli != 0xFA) {   /* relocation happened */
304             int len, offset=0;
305             if (boot.sector[0] == 0xEB)         /* jmp short */
306                 offset = boot.sector[1]+2;
307             else if (boot.sector[0] == 0xE9)    /* jmp near */
308                 offset = *(short*)&boot.sector[1] + 3;
309             else die("Cannot undo boot sector relocation.");
310             len = SECTOR_SIZE - offset;
311             memmove(&boot, &boot.sector[offset], len);
312             if (boot.par_1.cli != 0xFA)
313                 die("Cannot recognize boot sector.");
314         }
315 #endif
316 #if 1
317         Time = boot.par_1.map_stamp;
318         printf("Installed:  %s\n", ctime(&Time));
319 #else
320         printf("Installed:  %s\n", ctime((time_t*)&boot.par_1.map_stamp));
321 #endif
322         printf("Global settings:\n");
323         tsecs = (param2.delay*2197+3999)/4000;
324         printf("  Delay before booting: %d.%d seconds\n",tsecs/10,tsecs % 10);
325         if (param2.timeout == 0xffff) printf("  No command-line timeout\n");
326         else {
327             tsecs = (param2.timeout*2197+3999)/4000;
328             printf("  Command-line timeout: %d.%d seconds\n",tsecs/10,
329               tsecs % 10);
330         }
331         printf("  %snattended booting\n", param2.flag2&FLAG2_UNATTENDED ? "U" : "No u");
332         printf("  %sPC/AT keyboard hardware prescence check\n", param2.flag2&FLAG2_NOKBD ? "" : "No ");
333         if (boot.par_1.prompt & FLAG_PROMPT) printf("  Always enter boot prompt\n");
334         else printf("  Enter boot prompt only on demand\n");
335         printf("  Boot-time BIOS data%s saved\n",
336                 boot.par_1.prompt & FLAG_NOBD ? " NOT" : "");
337         printf("  Boot-time BIOS data auto-suppress write%s bypassed\n",
338                 boot.par_1.prompt & FLAG_BD_OKAY ? "" : " NOT");
339         printf("  Large memory (>15M) is%s used to load initial ramdisk\n", 
340                 boot.par_1.prompt & FLAG_LARGEMEM ? "" : " NOT");
341         printf("  %sRAID installation\n",
342                 boot.par_1.prompt & FLAG_RAID ? "" : "Non-");
343         printf("  Boot device %s be used for the Map file\n",
344                 boot.par_1.prompt & FLAG_MAP_ON_BOOT ? "WILL" : "will not");
345         if (!param2.port) printf("  Serial line access is disabled\n");
346         else printf("  Boot prompt can be accessed from COM%d\n",
347               param2.port);
348         if (!param2.msg_len) printf("  No message for boot prompt\n");
349         else if (!cfg_get_strg(cf_options,"bitmap"))
350             printf("  Boot prompt message is %d bytes\n",param2.msg_len);
351         else printf("  Bitmap file is %d paragraphs (%d bytes)\n",
352                         param2.msg_len, 16*param2.msg_len);
353 /* 22.6.2 begin */
354         if (*(unsigned short *) buffer != DC_MAGIC /* || !buffer[2] */)
355 /* 22.6.2 end */
356             printf("  No default boot command line\n");
357         else printf("  Default boot command line: \"%s\"\n",buffer+2);
358         if (verbose>=3) {
359             printf("Serial numbers %08X\n", menu.serial_no[0]);
360         }
361         printf("Images:\n");
362     }
363 /* 22.7 begin */
364     else        /* verbose==0 */
365 #endif /* !__MSDOS__ */
366     {
367         if (*(unsigned short *) buffer == DC_MAGIC)
368             printf("Default boot command line: \"%s\"\n",buffer+2);
369     }
370 /* 22.7 end */
371     for (image = 0; image < MAX_IMAGES; image++) {
372         if (*(name = descrs.d.descr[image].name)) {
373 #if __MSDOS__
374             printf("%s\n", name
375 #else /* !__MSDOS__ */
376             printf("%s%-" SA(MAX_IMAGE_NAME) "s %s%s%s",verbose > 0 ? "  " : "",name,
377               image ? "" : "*",
378 #ifdef LCF_VIRTUAL
379               descrs.d.descr[image].flags & FLAG_VMDEFAULT ? "@" :
380 #endif
381               "",
382 #ifdef LCF_NOKEYBOARD
383               descrs.d.descr[image].flags & FLAG_NOKBDEFAULT ? "&" :
384 #endif
385               ""
386 #endif /* !__MSDOS__ */
387               );
388 #if !__MSDOS__
389             if (verbose >= 2) {
390                 if (descrs.d.descr[image].start.device & (LINEAR_FLAG|LBA32_FLAG)) {
391                    unsigned int sector;
392                    sector = (descrs.d.descr[image].start.device & LBA32_FLAG)
393                       && (descrs.d.descr[image].start.device & LBA32_NOCOUNT)
394                         ? descrs.d.descr[image].start.num_sect : 0;
395                    sector = (sector<<8)+descrs.d.descr[image].start.head;
396                    sector = (sector<<8)+descrs.d.descr[image].start.track;
397                    sector = (sector<<8)+descrs.d.descr[image].start.sector;
398                    printf(" <dev=0x%02x,%s=%d>",
399                      descrs.d.descr[image].start.device&DEV_MASK,
400                      descrs.d.descr[image].start.device&LBA32_FLAG ? "lba32" : "linear",
401                      sector);
402                 }
403                 else { /*  CHS addressing */
404                     printf(" <dev=0x%02x,hd=%d,cyl=%d,sct=%d>",
405                       descrs.d.descr[image].start.device,
406                       descrs.d.descr[image].start.head,
407                       descrs.d.descr[image].start.track,
408                       descrs.d.descr[image].start.sector);
409                 }
410             }
411             printf("\n");
412             if (verbose >= 1) {
413                 flags = descrs.d.descr[image].flags;
414 #ifdef LCF_VIRTUAL
415                 if (flags & FLAG_VMDISABLE)
416                     printf("    Virtual Boot is disabled\n");
417                 if (flags & FLAG_VMWARN)
418                     printf("    Warn on Virtual boot\n");
419 #endif          
420 #ifdef LCF_NOKEYBOARD
421                 if (flags & FLAG_NOKBDISABLE)
422                     printf("    NoKeyboard Boot is disabled\n");
423 #endif          
424                 if ( !(flags & FLAG_PASSWORD) )
425                     printf("    No password\n");
426                 else printf("    Password is required for %s\n",flags &
427                       FLAG_RESTR ? "specifying options" : "booting this image");
428                 printf("    Boot command-line %s be locked\n",flags &
429                   FLAG_LOCK ? "WILL" : "won't");
430                 printf("    %single-key activation\n",flags & FLAG_SINGLE ?
431                   "S" : "No s");
432                 if (flags & FLAG_KERNEL) {
433 #ifdef NORMAL_VGA
434                     if (!(flags & FLAG_VGA))
435                        printf("    VGA mode is taken from boot image\n");
436                     else {
437                         printf("    VGA mode: ");
438                         switch (descrs.d.descr[image].vga_mode) {
439                             case NORMAL_VGA:
440                                 printf("NORMAL\n");
441                                 break;
442                             case EXTENDED_VGA:
443                                 printf("EXTENDED\n");
444                                 break;
445                             case ASK_VGA:
446                                 printf("ASK\n");
447                                 break;
448                             default:
449                                 printf("%d (0x%04x)\n",
450                                   descrs.d.descr[image].vga_mode,
451                                   descrs.d.descr[image].vga_mode);
452                         }
453                     }
454 #endif
455                     if (!(flags & FLAG_LOADHI))
456                         printf("    Kernel is loaded \"low\"\n");
457                     else printf("    Kernel is loaded \"high\"\n");
458                     if (!*(unsigned int *) descrs.d.descr[image].rd_size)
459                         printf("    No initial RAM disk\n");
460                     else printf("    Initial RAM disk is %d bytes\n",
461                           *(unsigned int *) descrs.d.descr[image].rd_size);
462                     if (flags & FLAG_TOOBIG)
463                         printf("       and is too big to fit between 4M-15M\n");
464                 }
465                 if (!geo_find(&geo,descrs.d.descr[image].start)) {
466                     printf("    Map sector not found\n");
467                     continue;
468                 }
469                 if (read(fd,addr,4*sizeof(SECTOR_ADDR)) !=
470                   4*sizeof(SECTOR_ADDR))
471                         die("Read on map file failed (access conflict ?) 2");
472                 if (!geo_find(&geo,addr[0]))
473                     printf("    Fallback sector not found\n");
474                 else {
475                     if (read(fd,buffer,SECTOR_SIZE) != SECTOR_SIZE)
476                         die("Read on map file failed (access conflict ?) 3");
477                     if (*(unsigned short *) buffer != DC_MAGIC)
478                         printf("    No fallback\n");
479                     else printf("    Fallback: \"%s\"\n",buffer+2);
480                 }
481 #define OTHER 0
482 #if OTHER
483                 if (flags & FLAG_KERNEL)
484 #endif
485                     if (!geo_find(&geo,addr[1]))
486                         printf("    Options sector not found\n");
487                     else {
488                         if (read(fd,buffer,SECTOR_SIZE) != SECTOR_SIZE)
489                             die("Read on map file failed (access conflict ?) 4");
490                         if (*buffer) printf("    Options: \"%s\"\n",buffer);
491                         else printf("    No options\n");
492                     }
493 #if OTHER
494                 else {
495 #else
496                 if (!(flags & FLAG_KERNEL)) {
497 #endif
498                     if (geo_find(&geo,addr[3])) show_other(fd);
499                     else printf("    Image data not found\n");
500                 }
501             }
502 #endif /*  !__MSDOS__ */
503         } /* if */
504     } /* for */
505 #undef OTHER
506     (void) close(fd);
507 #if !__MSDOS__
508     if (descrs.l.checksum ==
509           crc32(descrs.sector, sizeof(descrs.l.sector), CRC_POLY1) )
510 #endif /* !__MSDOS__ */
511                 exit(0);
512 #if !__MSDOS__
513     fflush(stdout);
514     fprintf(errstd,"Checksum error\n");
515     exit(1);
516 #endif /* !__MSDOS__ */
517 }
518
519
520 static void usage(char *name)
521 {
522     char *here;
523
524 #if !__MSDOS__
525     here = strrchr(name,'/');
526 #else /* __MSDOS__ */
527     here = strrchr(name,'\\');
528 #endif /* __MSDOS__ */
529     if (here) name = here+1;
530     fprintf(errstd,"usage: %s [ -C config_file ] -q [ -m map_file ] "
531       "[ -v N | -v ... ]\n",name);
532 #if !__MSDOS__
533     fprintf(errstd,"%7s%s [ -C config_file ] [ -b boot_device ] [ -c ] "
534       "[ -g | -l | -L ]\n","",name);
535     fprintf(errstd,"%12s[ -F ] [ -i boot_loader ] [ -m map_file ] [ -d delay ]\n","");
536     fprintf(errstd,"%12s[ -v N | -v ... ] [ -t ] [ -s save_file | -S save_file ]\n",
537       "");
538     fprintf(errstd,"%12s[ -p ][ -P fix | -P ignore ] [ -r root_dir ] [ -w | -w+ ]\n","");
539 #endif /* !__MSDOS__ */
540     fprintf(errstd,"%7s%s [ -C config_file ] [ -m map_file ] "
541       "-R [ word ... ]\n","",name);
542 #if !__MSDOS__
543     fprintf(errstd,"%7s%s [ -C config_file ] -I name [ options ]\n","",name);
544     fprintf(errstd,"%7s%s [ -C config_file ] [ -s save_file ] "
545       "-u | -U [ boot_device ]\n","",name);
546     fprintf(errstd,"%7s%s -H\t\t\t\tinstall only to active discs (RAID-1)\n", "", name);
547     fprintf(errstd,"%7s%s -A /dev/XXX [ N ]\t\tinquire/activate a partition\n","",name);
548     fprintf(errstd,"%7s%s -M /dev/XXX [ mbr | ext ]\tinstall master boot record\n","",name);
549     fprintf(errstd,"%7s%s -T help \t\t\tlist additional options\n", "", name);
550     fprintf(errstd,"%7s%s -X\t\t\t\tinternal compile-time options\n", "", name);
551 #endif /* !__MSDOS__ */
552     fprintf(errstd,"%7s%s -V [ -v ]\t\t\tversion information\n\n","",name);
553     exit(1);
554 }
555
556
557 int main(int argc,char **argv)
558 {
559     char *name,*reboot_arg,*ident_opt,*new_root;
560     char *tell_param, *uninst_dev, *param, *act1, *act2, ch;
561 static char *bitmap_file;
562     int more,version,uninstall,validate,activate,instmbr,geom;
563     int fd, temp=0, tell_early=0;
564     int raid_offset;
565 #if !__MSDOS__
566     struct stat st;
567 #endif /* !__MSDOS__ */
568
569     errstd = stderr;
570 #if VERSION_MINOR>=50
571     if (sizeof(MENUTABLE)!=256) die("MENUTABLE is not 256 bytes (common.h)");
572 #if !__MSDOS__
573     cfg_alpha_check();
574 #endif /* !__MSDOS__ */
575 #endif
576     config_file = DFL_CONFIG;
577     act1 = act2 = tell_param = 
578             reboot_arg = identify = ident_opt = new_root = uninst_dev = NULL;
579     do_md_install = zflag =
580             version = uninstall = validate = activate = instmbr = 0;
581     verbose = -1;
582 #if !__MSDOS__
583     name = *argv;
584 #else  /* __MSDOS__ */
585     name = "lilo";
586 #endif /* __MSDOS__ */
587     argc--;
588
589 #if !__MSDOS__    
590     if (atexit( (void(*)(void)) sync)) die("atexit(sync)");
591     if (atexit( (void(*)(void)) purge)) die("atexit(purge)");
592 #endif /* !__MSDOS__ */
593     
594     cfg_init(cf_options);
595     while (argc && **++argv == '-') {
596         argc--;
597       /* first those options with a mandatory parameter */
598       /* Notably absent are "RuUvw" */
599         if (strchr("AbBCdDEfiImMPrsSTxZ", ch=(*argv)[1])) {
600             if ((*argv)[2]) param = (*argv)+2;
601             else {
602                 param = *++argv;
603                 if(argc-- <= 0) usage(name);
604             }
605         } else { 
606             param = NULL;
607             if (strchr("cFglLpqtVXz", ch)       /* those with no args */
608                 && (*argv)[2]) usage(name);
609         }
610 #if 0
611 fprintf(errstd,"argc=%d, *argv=%s, ch=%c param=%s\n", argc, *argv, ch, param);
612 #endif
613         switch (ch) {
614 #if !__MSDOS__
615             case 'A':
616                 activate = 1;
617                 act1 = param;
618                 if (argc && argv[1][0] != '-') {
619                     act2 = *++argv;
620                     argc--;
621                 }
622                 break;
623             case 'b':
624                 cfg_set(cf_options,"boot",param,NULL);
625                 break;
626             case 'B':
627                 cfg_set(cf_options,"bitmap",param,NULL);
628                 break;
629             case 'c':
630                 cfg_set(cf_options,"compact",NULL,NULL);
631                 compact = 1;
632                 break;
633 #endif /* !__MSDOS */
634             case 'C':
635                 config_file = param;
636                 break;
637 #if !__MSDOS__
638             case 'd':
639                 cfg_set(cf_options,"delay",param,NULL);
640                 break;
641             case 'D':
642                 cfg_set(cf_options,"default",param,NULL);
643                 break;
644             case 'E':
645                 eflag=1;
646                 bitmap_file = param;
647                 break;
648             case 'f':
649                 cfg_set(cf_options,"disktab",param,NULL);
650                 break;
651             case 'F':
652                 force_fs=1;
653                 break;
654             case 'g':
655                 geometric |= AD_GEOMETRIC;
656                 break;
657             case 'H':
658                 force_raid=1;
659                 break;
660             case 'i':
661                 cfg_set(cf_options,"install",param,NULL);
662                 break;
663             case 'I':
664                 identify = param;
665                 if (argc && *argv[1] != '-') {
666                     ident_opt = *++argv;
667                     argc--;
668                 } else {
669                     ident_opt = "i";
670                 }
671                 break;
672             case 'l':
673                 geometric |= AD_LINEAR;
674                 break;
675             case 'L':
676                 geometric |= AD_LBA32;
677                 break;
678 #endif /* !__MSDOS__ */
679             case 'm':
680                 cfg_set(cf_options,"map",param,NULL);
681                 break;
682 #if !__MSDOS__
683             case 'M':
684                 instmbr = 1;
685                 act1 = param;
686 #if !defined LCF_BUILTIN        || 1
687                 if (argc && argv[1][0] != '-') {
688                     act2 = *++argv;
689                     argc--;
690                 }
691 #endif
692                 break;
693             case 'p':
694                 passw = 1;      /* force re-gen of password file */
695                 break;
696             case 'P':
697                 if ((act1=strchr(param,'='))) {
698                     *act1++ = 0;        /* null terminate */
699                     cfg_set(cf_options,param,act1,NULL);
700                 }
701                 else if (!strcasecmp(param,"fix"))
702                     cfg_set(cf_options,"fix-table",NULL,NULL);
703                 else if (!strcasecmp(param,"ignore"))
704                     cfg_set(cf_options,"ignore-table",NULL,NULL);
705                 else if (!strcasecmp(param,"x"))
706                     extended_pt = 1;
707                 else
708                     cfg_set(cf_options,param,NULL,NULL);
709                 break;
710 #endif /* !__MSDOS__ */
711             case 'q':
712                 query = 1;
713                 break;
714 #if !__MSDOS__
715             case 'r':
716                 new_root = param;
717                 break;
718 #endif /* !__MSDOS__ */
719             case 'R':
720                 if (*(param = (*argv)+2)) argc++;
721                 else if (argc) param = *++argv;
722                 else reboot_arg = "";
723
724                 while (argc) {
725                         if (!reboot_arg)
726                             *(reboot_arg = alloc(strlen(param)+1)) = 0;
727                         else {
728                             param = *++argv;
729                             strcat(reboot_arg = ralloc(reboot_arg,
730                                 strlen(reboot_arg)+strlen(param)+2)," ");
731                         }
732                         strcat(reboot_arg, param);
733                         argc--;
734                     }
735                 break;
736 #if !__MSDOS__
737             case 's':
738                 cfg_set(cf_options,"backup",param,NULL);
739                 break;
740             case 'S':
741                 cfg_set(cf_options,"force-backup",param,NULL);
742                 break;
743             case 't':
744                 test = 1;
745                 break;
746             case 'T':
747                 tell_param = param;
748                 break;
749             case 'u':
750                 validate = 1;
751                 /* fall through */
752             case 'U':   /* argument to -u or -U is optional */
753                 uninstall = 1;
754                 if ((*argv)[2]) param = (*argv)+2;
755                 else if (argc && argv[1][0] != '-') {
756                     param = *++argv;
757                     argc--;
758                 }
759                 uninst_dev = param;
760                 break;
761 #endif /* !__MSDOS__ */
762             case 'v':
763                 if ((*argv)[2]) param = (*argv)+2;
764                 else if (argc && argv[1][0]>='0' && argv[1][0]<='9') {
765                     param = *++argv;
766                     argc--;
767                 }
768                 if (param)
769                     verbose = to_number(param);
770                 else
771                     if (verbose<0) verbose = 1;
772                     else verbose++;
773                 if (verbose) errstd = stdout;
774                 break;
775             case 'V':
776                 version = 1;
777                 break;
778 #if !__MSDOS__
779             case 'w':
780                 cfg_set(cf_options,"nowarn",NULL,NULL);
781                 nowarn = 1;
782                 if ( (*argv)[2] == '+' ) nowarn = -1;
783                 break;
784             case 'x':
785                 cfg_set(cf_options,RAID_EXTRA_BOOT,param,NULL);
786                 break;
787 #endif /* !__MSDOS__ */
788             case 'X':
789                 configuration();
790                 exit(0);
791 #if !__MSDOS__
792             case 'z':
793                 zflag++;        /* force zero of MBR 8-byte area */
794                 break;
795             case 'Z':
796                 cfg_set(cf_options,"bios-passes-dl",param,NULL);
797                 break;
798 #endif /* !__MSDOS__ */
799             default:
800                 usage(name);
801         }
802     }
803     if (argc) usage(name);
804 #if !__MSDOS__
805     if (!new_root) new_root = getenv("ROOT");
806     if (new_root && *new_root) {
807         pp_fd = fopen(PARTITIONS, "r");
808         if (chroot(new_root) < 0) die("chroot %s: %s",new_root,strerror(errno));
809         if (chdir("/dev") < 0)
810                 warn("root at %s has no /dev directory", new_root);
811         if (chdir("/") < 0) die("chdir /: %s",strerror(errno));
812     }
813     if (atexit(temp_remove)) die("atexit() failed");
814     if (version+activate+instmbr+(tell_param!=NULL) > 1) usage(name);
815     if (activate) do_activate(act1, act2);
816 #endif /* !__MSDOS__ */
817
818     if (verbose > 0 || version) {
819         printf("LILO version %d.%d%s", VERSION_MAJOR, VERSION_MINOR, VERSION_EDIT);
820         if (test)
821           printf(" (test mode)\n");
822         else
823           printf(" (released %s)\n", VERSION_DATE);
824         if (version && verbose<=0) {
825           /* exit if user asks for version and no verbose */
826           return 0;
827         }
828         printf("  * Copyright (C) 1992-1998 Werner Almesberger  (until v20)\n"
829                "  * Copyright (C) 1999-2007 John Coffman  (until v22)\n"
830                "  * Copyright (C) 2009-2015 Joachim Wiedorn  (since v23)\n"
831                "This program comes with ABSOLUTELY NO WARRANTY. This is free software \n"
832                "distributed under the BSD License (3-clause). Details can be found in \n"
833                "the file COPYING, which is distributed with this software.\n"
834         );
835         if (verbose>0) {
836 #if !__MSDOS__
837   #include <sys/utsname.h>
838           struct utsname buf;
839           if (verbose>=2 && uname(&buf)==0) {
840             printf("Running %s kernel %s on %s\n",
841               buf.sysname, buf.release, buf.machine);
842           }
843 #endif
844         }
845         printf("\n");
846         if (version) {
847             if (verbose>=2) configuration();
848             return 0;
849         }
850     }
851
852     if (verbose > 0) errstd = stdout;
853 #if !__MSDOS__
854     preload_types();
855     if (geometric & (geometric-1))
856         die ("Only one of '-g', '-l', or '-L' may be specified");
857
858     if (tell_param) tell_early = strcasecmp(tell_param, "chrul")
859                                 && strcasecmp(tell_param, "ebda");
860     if (eflag) do_bitmap_edit(bitmap_file);
861     if (tell_param && tell_early) probe_tell(tell_param);
862     if (instmbr) do_install_mbr(act1, act2);
863 #endif /* !__MSDOS__ */    
864
865     fd = cfg_open(config_file);
866     more = fd<0 ? 0 : cfg_parse(cf_options);
867     
868 #if !__MSDOS__
869     temp = cfg_get_flag(cf_options,"nowarn");
870     if (nowarn < 0) nowarn = 0;
871     else nowarn = temp;
872 /* All warnings appear if very verbose modes used */
873     if (verbose>=3) nowarn = 0;
874 #endif /* !__MSDOS__ */
875
876     if (verbose>=6) printf("main: cfg_parse returns %d\n", more);
877
878 #if !__MSDOS__
879     if (tell_param && !tell_early) probe_tell(tell_param);
880
881     if (fstat(fd,&st) < 0)
882             die("fstat %s: %s", config_file, strerror(errno) );
883
884     if (S_ISREG(st.st_mode)) {
885         if (st.st_uid)
886             warn("%s should be owned by root", config_file);
887         else if (st.st_mode & (S_IWGRP | S_IWOTH))
888             warn("%s should be writable only for root", config_file);
889         config_read = !!(st.st_mode & (S_IRGRP | S_IROTH));
890     }
891
892     if (!cfg_get_flag(cf_options,"nodevcache"))  preload_dev_cache();
893     
894     if (verbose<0 && cfg_get_strg(cf_options,"verbose"))
895         verbose = to_number(cfg_get_strg(cf_options,"verbose"));
896     if (verbose<0) verbose = 0;
897     if (verbose) errstd = stdout;
898
899     compact = cfg_get_flag(cf_options,"compact");
900     geom = cfg_get_flag(cf_options,"geometric");
901     linear = cfg_get_flag(cf_options,"linear");
902     lba32  = cfg_get_flag(cf_options,"lba32");
903     
904     if (geom+linear+lba32 > 1)
905         die("May specify only one of GEOMETRIC, LINEAR or LBA32");
906     if (geometric) {
907         if (geom+linear+lba32 > 0)  
908             warn("Ignoring entry '%s'", geom ? "geometric" :
909                       linear ? "linear" : "lba32");
910         geom = linear = lba32 = 0;
911         if (geometric==AD_LBA32) lba32 = 1;
912         else if (geometric==AD_LINEAR) linear = 1;
913         else if (geometric==AD_GEOMETRIC) geom = 1;
914     }    
915     if (geom+linear+lba32 == 0) {
916         warn("LBA32 addressing assumed");
917         lba32 = 1;
918     }
919     if (linear) warn(
920         "LINEAR is deprecated in favor of LBA32:  LINEAR specifies 24-bit\n"
921         "  disk addresses below the 1024 cylinder limit; LBA32 specifies 32-bit disk\n"
922         "  addresses not subject to cylinder limits on systems with EDD-BIOS extensions;\n"
923         "  use LINEAR only if you are aware of its limitations.");
924     
925     if (identify) identify_image(identify,ident_opt);
926
927     if (uninstall)
928         bsect_uninstall(uninst_dev ? uninst_dev : cfg_get_strg(cf_options,
929               "boot"),cfg_get_strg(cf_options,"backup"),validate);
930 #endif /* !__MSDOS__ */
931
932     if (reboot_arg) {
933         map_patch_first(cfg_get_strg(cf_options,"map") ? cfg_get_strg(
934               cf_options,"map") : MAP_FILE, reboot_arg);
935         exit(0);
936     }
937
938 #if !__MSDOS__
939     if ( (param = cfg_get_strg(cf_options,"bios-passes-dl")) ) {
940         if (strchr("YyTt1", *param)) bios_passes_dl = DL_GOOD;
941         if (strchr("NnFf0", *param)) bios_passes_dl = DL_BAD;
942     }
943     if (bios_passes_dl == DL_NOT_SET)   check_bios();   /* in probe.c */
944
945     if (compact && (linear || lba32) && verbose>=4)
946         warn("COMPACT may conflict with %s on some "
947                 "systems", lba32 ? "LBA32" : "LINEAR");
948
949     geo_init(cfg_get_strg(cf_options,"disktab"));
950 #endif /* !__MSDOS__ */
951     if (query)
952         show_images(!cfg_get_strg(cf_options,"map") ? MAP_FILE :
953               cfg_get_strg(cf_options,"map"));
954
955 #if !__MSDOS__
956 /*************************************************/
957 /*  Doing a real install (may be test mode)      */
958 /*************************************************/
959
960 /* test for a RAID installation */
961         raid_offset = raid_setup();
962         if (verbose >= 2) {
963             printf("raid_setup returns offset = %08X  ndisk = %d\n", raid_offset, ndisk);
964             dump_serial_nos();    
965         }
966
967         if (verbose >=2 && do_md_install)
968             printf("raid flags: at bsect_open  0x%02X\n", raid_flags);
969
970         bsect_open(
971                 cfg_get_strg(cf_options,"boot"),
972                 cfg_get_strg(cf_options,"map") ?
973                         cfg_get_strg(cf_options,"map") : MAP_FILE,
974                 cfg_get_strg(cf_options,"install"),
975                 cfg_get_strg(cf_options,"delay") ?
976                         timer_number(cfg_get_strg(cf_options,"delay")) : 0,
977                 cfg_get_strg(cf_options,"timeout") ?
978                         timer_number(cfg_get_strg(cf_options,"timeout")) : -1,
979                 raid_offset );
980         if (more) {
981             cfg_init(cf_top);
982             if (cfg_parse(cf_top)) cfg_error("Syntax error");
983         }
984         
985         temp = bsect_number();
986         if (temp==0) die("No images have been defined.");
987         else if (temp<0) die("Default image doesn't exist.");
988
989 #ifdef LCF_VIRTUAL
990         check_vmdefault();
991 #endif
992 #ifdef LCF_NOKEYBOARD
993         check_nokbdefault();
994 #endif
995         check_fallback();
996         check_unattended();
997         
998         if (verbose>=2) dump_serial_nos();
999         if (do_md_install) raid_final();
1000         else if (!test) {
1001             char *cp;
1002             
1003             if (verbose) printf("Writing boot sector.\n");
1004
1005             cp = cfg_get_strg(cf_options,"force-backup");
1006             if (cp) bsect_update(cp,1,0);
1007             else bsect_update(cfg_get_strg(cf_options,"backup"),0,0);
1008
1009         } 
1010         else {
1011             bsect_cancel();
1012             if (passw)
1013                 printf("The password crc file has *NOT* been updated.\n");
1014
1015             printf("The boot sector and the map file have *NOT* been "
1016               "altered.\n");
1017         }
1018         if (verbose>=4) dump_serial_nos();
1019         if (warnings) {
1020             if (warnings>1)
1021                 printf("%d warnings were ", warnings);
1022             else printf("One warning was ");
1023             printf("%sed.\n", nowarn ? "suppress" : "issu");
1024         }
1025 #else  /* __MSDOS__ */
1026         die("No option switches specified:  -q, -R, or -V");
1027 #endif /* __MSDOS__ */
1028         
1029     return 0;
1030 }