home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 13 / CDA13.ISO / MISC / SRC / INSTALL / LILO.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-12-23  |  11.9 KB  |  481 lines

  1. #include <alloca.h>
  2. #include <newt.h>
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include <stdlib.h>
  6. #include <sys/stat.h>
  7. #include <unistd.h>
  8.  
  9. #include "devices.h"
  10. #include "install.h"
  11. #include "lilo.h"
  12. #include "log.h"
  13. #include "run.h"
  14. #include "windows.h"
  15.  
  16. #ifdef __i386__
  17. static char * kernelPath = "/boot/vmlinuz";
  18. #elif __sparc__
  19. static char * kernelPath = "/boot/vmlinux.gz";
  20. #else
  21. #error unsupported architecture
  22. #endif
  23.  
  24. static int mkinitrd(char * kernelVersion) {
  25.     char * argv[] = { "/sbin/mkinitrd", "/boot/initrd", "--ifneeded", 
  26.             kernelVersion, NULL };
  27.     int rc;
  28.     static alreadyHappened = 0;
  29.  
  30.     #ifdef __sparc__
  31.     return 0;
  32.     #endif
  33.  
  34.     if (alreadyHappened) return 0;
  35.  
  36.     if (!access("/mnt/boot/initrd", X_OK)) {
  37.     logMessage("/mnt/boot/initrd exists -- moving to "
  38.             "/mnt/boot/initrd.orig");
  39.     rename("/mnt/boot/initrd", "/mnt/boot/initrd.orig");
  40.     }
  41.  
  42.     if (loadModule("loop", DRIVER_OTHER, NULL)) return INST_ERROR;
  43.  
  44.     winStatus(32, 3, "LILO", "Creating initial ramdisk...");
  45.     rc = runProgramRoot(RUN_LOG, "/mnt", "/sbin/mkinitrd", argv);
  46.     newtPopWindow();
  47.  
  48.     removeModule("loop");
  49.  
  50.     if (rc) {
  51.     unlink("/mnt/boot/initrd");
  52.     } else {
  53.     alreadyHappened = 1;
  54.     }
  55.  
  56.     return rc;
  57. }
  58.  
  59. #define SKIP_LILO 1000
  60.  
  61. static int liloWhere(char * hdName, char * rootDevice, char ** where) {
  62.     newtComponent form, okay, listbox, cancel, answer, skip;
  63.     char * format = "/dev/%-7s    %s";
  64.     char buf[200];
  65.     void * which;
  66.  
  67.     #ifdef __sparc__
  68.     newtOpenWindow(12, 6, 55, 11, "Silo Installation");
  69.     #else
  70.     newtOpenWindow(12, 6, 55, 11, "Lilo Installation");
  71.     #endif
  72.  
  73.     form = newtForm(NULL, NULL, 0);
  74.     newtFormAddComponent(form, 
  75.         newtLabel(1, 1, "Where do you want to install "
  76.                 "the bootloader?"));
  77.  
  78.     listbox = newtListbox(2, 3, 3, NEWT_LISTBOX_RETURNEXIT);
  79.     sprintf(buf, format, hdName, 
  80.             "Master Boot Record");
  81.     newtListboxAddEntry(listbox, buf, (void *) 1);
  82.     sprintf(buf, format, rootDevice, 
  83.             "First sector of root partition");
  84.     newtListboxAddEntry(listbox, buf, (void *) 2);
  85.     sprintf(buf, format, "fd0", 
  86.             "First sector of a floppy disk");
  87.     newtListboxAddEntry(listbox, buf, (void *) 3);
  88.  
  89.     okay = newtButton(6, 7, "Ok");
  90.     skip = newtButton(22, 7, "Skip");
  91.     cancel = newtButton(38, 7, "Cancel");
  92.     newtFormAddComponents(form, listbox, okay, skip, cancel, NULL);
  93.  
  94.     answer = newtRunForm(form);
  95.  
  96.     which = newtListboxGetCurrent(listbox);
  97.     
  98.     newtFormDestroy(form);
  99.     newtPopWindow();
  100.  
  101.     if (answer == cancel) return INST_CANCEL;
  102.     if (answer == skip) return SKIP_LILO;
  103.  
  104.     switch ((int) which) {
  105.       case 1:         *where = hdName; break;
  106.       case 2:         *where = rootDevice; break;
  107.       case 3:         *where = "fd0"; break;
  108.     }
  109.  
  110.     return 0;
  111. }
  112.  
  113. static void editBootLabel(struct partition * item) {
  114.     newtComponent form, entry, okay, cancel, clear, answer;
  115.     char buf[50];
  116.     char * entryValue;
  117.  
  118.     newtOpenWindow(10, 7, 50, 10, "Edit Boot Label");
  119.  
  120.     form = newtForm(NULL, NULL, 0);
  121.  
  122.     strcpy(buf,"Device      : /dev/");
  123.     strcat(buf, item->device);
  124.     newtFormAddComponent(form, newtLabel(1, 1, buf));
  125.     newtFormAddComponent(form, newtLabel(1, 3, "Boot label :"));
  126.  
  127.     entry = newtEntry(17, 3, item->bootLabel, 20, &entryValue, 
  128.               NEWT_ENTRY_SCROLL | NEWT_ENTRY_RETURNEXIT);
  129.  
  130.     okay = newtButton(5, 6, "Ok");
  131.     clear = newtButton(20, 6, "Clear");
  132.     cancel = newtButton(35, 6, "Cancel");
  133.  
  134.     newtFormAddComponents(form, entry, okay, clear, cancel, NULL);
  135.  
  136.     do {
  137.     answer = newtRunForm(form);
  138.  
  139.     if (answer == clear)
  140.         newtEntrySet(entry, "", 1);
  141.     } while (answer == clear);
  142.  
  143.     if (answer != cancel) {
  144.     if (item->bootLabel) free(item->bootLabel);
  145.  
  146.     if (strlen(entryValue))
  147.         item->bootLabel = strdup(entryValue);
  148.     else
  149.         item->bootLabel = NULL;
  150.     }
  151.  
  152.     newtPopWindow();
  153. }        
  154.  
  155. static int doinstallLilo(char * prefix, char * dev, struct partitionTable table,
  156.              char * append, char * kernelVersion) {
  157.     char filename[100];
  158.     FILE * f;
  159.     char * argv[] = { "/mnt/sbin/lilo", "-r", "/mnt", NULL };
  160.     int i;
  161.     int rc;
  162.     struct stat sb;
  163.     int useInitrd = 0;
  164.     struct partition * root = NULL;
  165.  
  166.     if (mkinitrd(kernelVersion))
  167.     return INST_ERROR;
  168.  
  169.     if (!stat("/mnt/boot/initrd", &sb))
  170.     useInitrd = 1;
  171.  
  172.     #ifdef __sparc__
  173.     sprintf(filename, "%s/silo.conf", prefix);
  174.     #else
  175.     sprintf(filename, "%s/lilo.conf", prefix);
  176.     #endif
  177.  
  178.     /* why not? */
  179.     rename("/mnt/etc/lilo.conf", "/mnt/etc/lilo.conf.orig");
  180.     rename("/mnt/etc/silo.conf", "/mnt/etc/silo.conf.orig");
  181.     
  182.     f = fopen(filename, "w");
  183.     if (!f) {
  184.     errorWindow("cannot create [ls]ilo config file: %s");
  185.     return INST_ERROR;
  186.     }
  187.  
  188.     logMessage("writing [sl]ilo config to %s", filename);
  189.  
  190.     for (i = 0; i < table.count; i++) {
  191.     if (table.parts[i].bootLabel && 
  192.         table.parts[i].type == PART_EXT2) {
  193.         root = table.parts + i;
  194.     }
  195.     }
  196.  
  197.     if (!root) {
  198.     errorWindow("No ext2 partition is bootable");
  199.     return INST_ERROR;
  200.     }
  201.  
  202.     #ifdef __i386__
  203.     fprintf(f, "boot=/dev/%s\n", dev);
  204.     fprintf(f, "map=/boot/map\n");
  205.     fprintf(f, "install=/boot/boot.b\n");
  206.     fprintf(f, "prompt\n");
  207.     fprintf(f, "timeout=50\n");
  208.     #elif __sparc__
  209.     fprintf(f, "timeout=50\n");
  210.     fprintf(f, "partition=%s\n", root->device + 3);
  211.     fprintf(f, "root=/dev/%s\n", root->device);
  212.     #else
  213.     #error "unsupported architecture";
  214.     #endif
  215.  
  216.     for (i = 0; i < table.count; i++) {
  217.     if (table.parts[i].bootLabel) {
  218.         if (table.parts[i].type == PART_EXT2) {
  219.         fprintf(f, "image=%s\n", kernelPath);
  220.         fprintf(f, "\tlabel=%s\n", table.parts[i].bootLabel);
  221.         fprintf(f, "\troot=/dev/%s\n", table.parts[i].device);
  222.         if (useInitrd)
  223.             fprintf(f, "\tinitrd=/boot/initrd\n");
  224.         if (append) fprintf(f, "\tappend=\"%s\"\n", append);
  225.         fprintf(f, "\tread-only\n");
  226.         } else {
  227.         fprintf(f, "other=/dev/%s\n", table.parts[i].device);
  228.         fprintf(f, "\tlabel=%s\n", table.parts[i].bootLabel);
  229.         fprintf(f, "\ttable=/dev/%.3s\n", table.parts[i].device);
  230.         }
  231.     }
  232.     }
  233.  
  234.     fclose(f);
  235.  
  236.     winStatus(35, 3, "Running", "Installing boot loader...");
  237.  
  238.     #ifdef __i386__
  239.     rc = runProgram(RUN_LOG, "/mnt/sbin/lilo", argv);
  240.     #elif __sparc__ 
  241.     rc = runProgram(RUN_LOG, "/mnt/sbin/silo", argv);
  242.     #else
  243.     #error unsupported architectures
  244.     #endif
  245.  
  246.     newtPopWindow();
  247.  
  248.     if (rc)
  249.     return INST_ERROR;
  250.  
  251.     return 0;
  252. }
  253.  
  254. static int getBootLabels(struct partitionTable table, struct fstab fstab) {
  255.     newtComponent f, okay, text, listbox, label, cancel, edit, answer;
  256.     char buf[80];
  257.     int i, j;
  258.     int foundDos = 0;
  259.     int mustAsk = 0;
  260.     int * map;
  261.     struct partition * curr;
  262.     int * currNum;
  263.     int count;
  264.  
  265.     f = newtForm(NULL, NULL, 0);
  266.     text = newtTextbox(1, 1, 60, 4, NEWT_TEXTBOX_WRAP);
  267.     newtTextboxSetText(text, 
  268.                "The boot manager Red Hat uses can boot other " 
  269.                        "operating systems as well. You need to tell me " 
  270.                        "what partitions you would like to be able to boot " 
  271.                        "and what label you want to use for each of them.");
  272.  
  273.  
  274.     sprintf(buf, "%-10s  %-25s %-18s", "Device", "Partition type", 
  275.             "Boot label");
  276.     label = newtLabel(1, 6, buf);
  277.  
  278.     listbox = newtListbox(1, 7, 7, NEWT_LISTBOX_RETURNEXIT);
  279.     map = alloca(sizeof(int) * table.count);
  280.     
  281.     for (i = 0, count = 0; i < table.count; i++) {
  282.     if (table.parts[i].type != PART_SWAP && 
  283.         table.parts[i].type != PART_IGNORE &&
  284.         (table.parts[i].type != PART_DOS || !foundDos)) {
  285.  
  286.         if (table.parts[i].type == PART_DOS) {
  287.         table.parts[i].bootLabel = strdup("dos");
  288.         foundDos = 1;
  289.         }
  290.  
  291.         if (table.parts[i].type == PART_EXT2) {
  292.         for (j = 0; j < fstab.numEntries; j++) {
  293.             if (!strcmp(table.parts[i].device, fstab.entries[j].device))
  294.             break;
  295.         }
  296.  
  297.         if (j < fstab.numEntries && !table.parts[i].bootLabel) 
  298.             continue;
  299.         }
  300.  
  301.         if (!table.parts[i].bootLabel ||
  302.         strcmp(table.parts[i].bootLabel, "linux")) mustAsk = 1;
  303.  
  304.         sprintf(buf, "/dev/%-5s  %-25s %-18s", table.parts[i].device, 
  305.             table.parts[i].tagName, table.parts[i].bootLabel ? 
  306.             table.parts[i].bootLabel : "");
  307.         map[count] = i;
  308.         newtListboxAddEntry(listbox, buf, map + count++);
  309.     } 
  310.     }
  311.  
  312.     newtFormAddComponents(f, text, label, listbox, NULL);
  313.  
  314.     if (!mustAsk) {
  315.     newtFormDestroy(f);
  316.     return 0;
  317.     }
  318.  
  319.     newtOpenWindow(8, 2, 64, 19, "Bootable Partitions");
  320.  
  321.     okay = newtButton(8, 15, "Ok");
  322.     edit = newtButton(26, 15, "Edit");
  323.     cancel = newtButton(44, 15, "Cancel");
  324.  
  325.     newtFormAddComponents(f, okay, edit, cancel, NULL);
  326.  
  327.     do { 
  328.     answer = newtRunForm(f);
  329.     if (answer == edit || answer == listbox) {
  330.         currNum = newtListboxGetCurrent(listbox);
  331.         curr = table.parts + *currNum;
  332.         editBootLabel(curr);
  333.         sprintf(buf, "/dev/%-5s  %-25s %-18s", curr->device, 
  334.             curr->tagName, 
  335.             curr->bootLabel ? curr->bootLabel : "");
  336.  
  337.         newtListboxSetEntry(listbox, currNum - map, buf);
  338.     }
  339.     } while (answer == edit || answer == listbox);
  340.  
  341.     newtFormDestroy(f);
  342.     newtPopWindow();
  343.  
  344.     if (answer == cancel)
  345.     return INST_CANCEL;
  346.     else
  347.     return 0;
  348. }
  349.  
  350. static int getAppendLine(char ** line) {
  351.     newtComponent form, text, entry, okay, cancel, answer;
  352.     char * result = NULL;
  353.  
  354.     #ifdef __sparc__
  355.     newtOpenWindow(12, 5, 55, 13, "Silo Installation");
  356.     #else
  357.     newtOpenWindow(12, 5, 55, 13, "Lilo Installation");
  358.     #endif
  359.  
  360.     form = newtForm(NULL, NULL, 0);
  361.     text = newtTextbox(1, 1, 53, 5, NEWT_TEXTBOX_WRAP);
  362.     newtTextboxSetText(text, 
  363.                "A few systems will need to pass special options "
  364.                "to the kernel at boot time for the system to function "
  365.                "properly. If you need to pass boot options to the "
  366.                "kernel, enter them now. If you don't need any or "
  367.                "aren't sure, leave this blank.");
  368.  
  369.     entry = newtEntry(1, 7, *line, 48, &result, 
  370.             NEWT_ENTRY_SCROLL | NEWT_ENTRY_RETURNEXIT);
  371.  
  372.     okay = newtButton(12, 9, "Ok");
  373.     cancel = newtButton(35, 9, "Cancel");
  374.  
  375.     newtFormAddComponents(form, text, entry, okay, cancel, NULL);
  376.     newtFormSetCurrent(form, okay);
  377.  
  378.     answer = newtRunForm(form);
  379.  
  380.     newtPopWindow();
  381.  
  382.     if (answer == cancel) {
  383.     newtFormDestroy(form);
  384.     return INST_CANCEL;
  385.     }
  386.  
  387.     if (!strlen(result)) 
  388.     *line = NULL;
  389.     else 
  390.     *line = strdup(result);
  391.  
  392.     newtFormDestroy(form);
  393.  
  394.     return 0;
  395. }
  396.  
  397. #define LILO_WHERE 2
  398. #define LILO_LABELS 3
  399. #define LILO_INSTALL 4
  400. #define LILO_APPEND 5
  401. #define LILO_DONE 20
  402.     
  403. int installLilo(char * prefix, struct partitionTable table, 
  404.             struct fstab fstab, char * kernelVersion) {
  405.     char * rootDevice;
  406.     char * hdName;
  407.     char * where;
  408.     char * append = NULL;
  409.     char * chptr = NULL;
  410.     int i;
  411.     int rc;
  412.     int stage = LILO_WHERE;
  413.  
  414.     hdName = alloca(4);
  415.     strncpy(hdName, table.parts[0].device, 3);
  416.     hdName[3] = '\0';
  417.     
  418.     for (i = 0; i < fstab.numEntries; i++) {
  419.     if (!strcmp(fstab.entries[i].mntpoint, "/")) break;
  420.     }
  421.  
  422.     rootDevice = fstab.entries[i].device;
  423.  
  424.     for (i = 0; i < table.count; i++) {
  425.     if (!strcmp(table.parts[i].device, rootDevice)) {
  426.         table.parts[i].bootLabel = strdup("linux");
  427.         break;
  428.     }
  429.     }
  430.  
  431.     while (stage != LILO_DONE) {
  432.     switch (stage) {
  433.       case LILO_WHERE:
  434.         rc = liloWhere(hdName, rootDevice, &where);
  435.             if (rc == SKIP_LILO ) return 0;
  436.         if (rc) return rc;
  437.         stage = LILO_APPEND;
  438.         break;
  439.  
  440.       case LILO_APPEND:
  441.         chptr = append;
  442.         rc = getAppendLine(&chptr);
  443.  
  444.         if (rc == INST_ERROR) return INST_ERROR;
  445.         if (rc == INST_CANCEL)
  446.         stage = LILO_WHERE;
  447.         else {
  448.         stage = LILO_INSTALL;
  449.  
  450.         if (append) free(append);
  451.         if (chptr) {
  452.             append = alloca(strlen(chptr) + 1);
  453.             strcpy(append, chptr);
  454.             free(chptr);
  455.         } else {
  456.             append = NULL;
  457.         }
  458.         }
  459.  
  460.         break;
  461.  
  462.       case LILO_LABELS:
  463.         rc = getBootLabels(table, fstab);
  464.         if (rc == INST_ERROR) return INST_ERROR;
  465.         if (rc == INST_CANCEL)
  466.         stage = LILO_APPEND;
  467.         else
  468.         stage = LILO_INSTALL;
  469.         break;
  470.  
  471.       case LILO_INSTALL:
  472.         rc = doinstallLilo(prefix, where, table, append, kernelVersion);
  473.         if (rc == INST_ERROR) return INST_ERROR;
  474.         stage = LILO_DONE;
  475.         break;
  476.     }
  477.     }
  478.  
  479.     return 0;
  480. }
  481.