home *** CD-ROM | disk | FTP | other *** search
/ PC Plus SuperCD (UK) 1999 May / pcp151c.iso / misc / src / install / latemethods.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-08-11  |  24.8 KB  |  937 lines

  1. #include <alloca.h>
  2. #include <errno.h>
  3. #include <fcntl.h>
  4. #include <newt.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <sys/mount.h>
  9. #include <sys/mtio.h>
  10. #include <unistd.h>
  11.  
  12. #include "hd.h"
  13. #include "fs.h"
  14. #include "ftp.h"
  15. #include "install.h"
  16. #include "intl.h"
  17. #include "log.h"
  18. #include "methods.h"
  19. #include "net.h"
  20. #include "scsi.h"
  21. #include "windows.h"
  22.  
  23. struct ftpinfo {
  24.     char * address;
  25.     char * login;
  26.     char * password;
  27.     char * prefix;
  28.     char * proxy;
  29.     int sock;
  30.     struct pkgSet ps;
  31. };
  32.  
  33. struct hdinfo {
  34.     char * device;
  35.     char * type;
  36.     char * dir;
  37. };
  38.  
  39. struct tapeCatalogEntry {
  40.     char * filename;
  41.     int size;
  42. };
  43.  
  44. struct tapeinfo {
  45.     int fd;
  46.     int offset;
  47.     int curr;
  48.     int catalogEntries;
  49.     struct tapeCatalogEntry * catalog;
  50. };
  51.  
  52. /* This was split into two pieces to keep the initial install program small */
  53.  
  54. static int ftpinstStartTransfer(struct ftpinfo * fi, char * filename);
  55. static int ftpinstFinishTransfer(struct ftpinfo * fi);
  56. static int ftpinstGetMappedFile(struct installMethod * method, char * name, 
  57.                         char ** realName);
  58. static int imageGetFile(struct installMethod * method, char * name, 
  59.             char ** realName);
  60. static int singleimageSetSymlinks(struct installMethod * method, 
  61.                             struct partitionTable table,
  62.                             struct netInfo * netc, 
  63.                   struct intfInfo * intf,
  64.                   struct driversLoaded ** dl);
  65. static int hdSetup(struct installMethod * method, struct partitionTable table,
  66.                struct netInfo * netc, struct intfInfo * intf,
  67.                struct driversLoaded ** dl);
  68. static int hdPrepareMedia(struct installMethod * method,
  69.                 struct fstab * fstab);
  70. static int hdGetPackageSet(struct installMethod * method,
  71.                  struct pkgSet * ps);
  72. static int hdGetComponentSet(struct installMethod * method,
  73.                    struct pkgSet * ps,
  74.                    struct componentSet * cs);
  75. static int ftpSetup(struct installMethod * method, struct partitionTable table,
  76.                 struct netInfo * netc, struct intfInfo * intf,
  77.                 struct driversLoaded ** dl);
  78. static int ftpGetPackageSet(struct installMethod * method,
  79.                  struct pkgSet * ps);
  80. static int ftpGetComponentSet(struct installMethod * method,
  81.                    struct pkgSet * ps,
  82.                    struct componentSet * cs);
  83. static int imageGetPackageSet(struct installMethod * method,
  84.                   struct pkgSet * ps);
  85. static int imageGetComponentSet(struct installMethod * method,
  86.                  struct pkgSet * ps,
  87.                  struct componentSet * cs);
  88. static inline int fileInBase(char * name);
  89.  
  90. #ifdef __i386__
  91. static int smbSetup(struct installMethod * method, struct partitionTable table,
  92.                struct netInfo * netc, struct intfInfo * intf,
  93.                struct driversLoaded ** dl);
  94. static int smbGetSetup(char ** hostptr, char ** dirptr, char ** acctptr,
  95.             char ** pwptr);
  96. static int smbGetPackageSet(struct installMethod * method,
  97.                  struct pkgSet * ps);
  98. static int smbGetComponentSet(struct installMethod * method,
  99.                    struct pkgSet * ps,
  100.                    struct componentSet * cs);
  101. #endif
  102.  
  103. static struct installMethod methods[] = {
  104.     { "Local CDROM",         "cdrom", 0, NULL, singleimageSetSymlinks, 
  105.         imageGetFile, 
  106.         imageGetPackageSet, imageGetComponentSet, NULL, NULL },
  107.     { "NFS image",         "nfs", 0, NULL, singleimageSetSymlinks, 
  108.         imageGetFile, 
  109.         imageGetPackageSet, imageGetComponentSet, NULL, NULL },
  110.     { "hard drive",        "hd",  0, NULL, hdSetup, imageGetFile,
  111.         hdGetPackageSet, hdGetComponentSet, hdPrepareMedia, NULL },
  112.     { "FTP",            "ftp", 1, NULL, ftpSetup, ftpinstGetMappedFile,
  113.         ftpGetPackageSet, ftpGetComponentSet, NULL, NULL },
  114. #ifdef __i386__
  115.     { "SMB image",         "smb", 0, NULL, smbSetup, 
  116.         imageGetFile, 
  117.         smbGetPackageSet, smbGetComponentSet, NULL, NULL },
  118. #endif
  119. } ;
  120. static int numMethods = sizeof(methods) / sizeof(struct installMethod);
  121.  
  122. struct installMethod * findInstallMethod(char * argptr) {
  123.     int i;
  124.  
  125.     for (i = 0; i < numMethods; i++) 
  126.     if (!strcmp(argptr, methods[i].abbrev)) return (methods + i);
  127.  
  128.     return NULL;
  129. }
  130.  
  131. static inline int fileInBase(char * name) {
  132.     if (!strcmp(name, "hdlist") || !strcmp(name, "rpmconvert"))
  133.     return 1;
  134.     if (!strncmp(name, "install", 7) && !strcmp(name + 8, ".tr"))
  135.     return 1;
  136.     return 0;
  137. }
  138.  
  139. static int imageGetFile(struct installMethod * method, char * name, 
  140.             char ** realName) {
  141.     static char buf[300];
  142.  
  143.     if (fileInBase(name))
  144.     strcpy(buf, "/tmp/rhimage/RedHat/base/");
  145.     else
  146.     strcpy(buf, "/tmp/rhimage/RedHat/RPMS/");
  147.  
  148.     strcat(buf, name);
  149.     *realName = buf;
  150.  
  151.     return 0;
  152. }
  153.  
  154. static int hdSetup(struct installMethod * method, struct partitionTable table,
  155.                struct netInfo * netc, struct intfInfo * intf,
  156.                struct driversLoaded ** dl) {
  157.     newtComponent okay, cancel, form, text, listbox, label, answer, dirEntry;
  158.     newtGrid partGrid, buttons, entryGrid, grid;
  159.     int numParts;
  160.     int i;
  161.     char * type;
  162.     char * dir;
  163.     char * dest;
  164.     char * defaultDevice;
  165.     char * defaultDir;
  166.     char * reflowedText;
  167.     int width, height;
  168.     struct partition * part = NULL;
  169.     int done = 0;
  170.     struct hdinfo * hdi;
  171.     int rc;
  172.  
  173.     if (method->data) {
  174.     hdi = method->data;
  175.     defaultDir = strdup(hdi->dir);
  176.     defaultDevice = hdi->device;
  177.     } else {
  178.     defaultDir = strdup("/");
  179.     defaultDevice = "";
  180.     }
  181.  
  182.     while (!done) {
  183.     reflowedText = newtReflowText(_("What partition and directory on that "
  184.                     "partition hold the RedHat/RPMS and "
  185.                     "RedHat/base directories?"),
  186.                     62, 5, 5, &width, &height);
  187.     text = newtTextbox(-1, -1, width, height, NEWT_TEXTBOX_WRAP);
  188.     newtTextboxSetText(text, reflowedText);
  189.     free(reflowedText);
  190.  
  191.     addPartitionListbox(table, 4, PART_EXT2 | PART_DOS | PART_FAT32, 
  192.                 NULL, &numParts, &partGrid, &listbox);
  193.  
  194.      buttons = newtButtonBar(_("Ok"), &okay, _("Cancel"), &cancel, NULL);
  195.  
  196.     for (i = 0; i < table.count; i++) {
  197.         if (!strcmp(table.parts[i].device, defaultDevice)) {
  198.         newtListboxSetCurrentByKey(listbox, table.parts + i);
  199.         }
  200.     }
  201.  
  202.     label = newtLabel(-1, -1, _("Directory holding Red Hat:"));
  203.     dirEntry = newtEntry(28, 11, defaultDir, 28, &dir, NEWT_ENTRY_SCROLL);
  204.  
  205.     entryGrid = newtGridHStacked(NEWT_GRID_COMPONENT, label,
  206.                      NEWT_GRID_COMPONENT, dirEntry,
  207.                      NEWT_GRID_EMPTY);
  208.  
  209.     grid = newtCreateGrid(1, 4);
  210.     newtGridSetField(grid, 0, 0, NEWT_GRID_COMPONENT, text,
  211.              0, 0, 0, 1, 0, 0);
  212.     newtGridSetField(grid, 0, 1, NEWT_GRID_SUBGRID, partGrid,
  213.              0, 0, 0, 1, 0, 0);
  214.     newtGridSetField(grid, 0, 2, NEWT_GRID_SUBGRID, entryGrid,
  215.              0, 0, 0, 1, 0, 0);
  216.     newtGridSetField(grid, 0, 3, NEWT_GRID_SUBGRID, buttons,
  217.              0, 0, 0, 0, 0, NEWT_GRID_FLAG_GROWX);
  218.  
  219.     newtGridWrappedWindow(grid, _("Select Partition"));
  220.  
  221.     form = newtForm(NULL, NULL, 0);
  222.     newtGridAddComponentsToForm(grid, form, 1);
  223.     newtGridFree(grid, 1);
  224.  
  225.     answer = newtRunForm(form);
  226.  
  227.     if (answer != cancel) {
  228.         part = newtListboxGetCurrent(listbox);
  229.     }
  230.  
  231.     dir = strdup(dir);
  232.  
  233.     newtFormDestroy(form);
  234.     newtPopWindow();
  235.  
  236.     if (answer == cancel) return INST_CANCEL;
  237.  
  238.     free(defaultDir);
  239.     defaultDir = dir;
  240.     defaultDevice = part->device;
  241.  
  242.     switch (part->type) {
  243.       case PART_EXT2:    type = "ext2";         break;
  244.       case PART_DOS:    type = "vfat";         break;
  245.       case PART_FAT32:    type = "vfat";         break;
  246.       default:    continue;
  247.     }
  248.  
  249.     if (!strcmp(type, "vfat")) {
  250.         if ((rc = loadFilesystem("vfat", "vfat", dl))) return rc;
  251.     }
  252.  
  253.     if (doMount(part->device, "/tmp/hdimage", type, 1, 0))
  254.         continue;
  255.  
  256.     unlink("/tmp/rhimage");
  257.     
  258.     /* the physical device is mounted on /tmp/hdimage, but all
  259.        access are through /tmp/rhimage which points to the RedHat
  260.        directory in /tmp/hdimage */
  261.  
  262.     dest = alloca(strlen(dir) + 20);
  263.     sprintf(dest, "/tmp/hdimage/%s", dir);
  264.  
  265.     if (symlink(dest, "/tmp/rhimage")) {
  266.         newtWinMessage(_("Error"), _("Ok"), 
  267.                _("Failed to create /tmp/rhimage symlink: %s"), 
  268.                strerror(errno));
  269.         umount("/tmp/hdimage");
  270.         continue;
  271.     } 
  272.  
  273.     if (access("/tmp/rhimage/RedHat/base/hdlist", R_OK)) {
  274.         newtWinMessage(_("Error"), _("Ok"), 
  275.             _("Device %s does not appear to contain "
  276.               "a Red Hat installation tree."), part->device);
  277.         umount("/tmp/hdimage");
  278.         continue;
  279.     } 
  280.  
  281.     if (method->data) {
  282.         hdi = method->data;
  283.         free(hdi->dir);
  284.     }
  285.     
  286.     hdi = malloc(sizeof(*hdi));
  287.     hdi->device = part->device;
  288.     hdi->type = type;
  289.     hdi->dir = strdup(dir);
  290.     method->data = hdi;
  291.  
  292.     done = 1; 
  293.  
  294.     umount("/tmp/hdimage");
  295.     }
  296.  
  297.     return 0;
  298. }
  299.  
  300. static int hdGetPackageSet(struct installMethod * method,
  301.                  struct pkgSet * ps) {
  302.     struct hdinfo * hdi = method->data;
  303.     int rc;
  304.  
  305.     if (doMount(hdi->device, "/tmp/hdimage", hdi->type, 1, 0))
  306.     return INST_ERROR;
  307.  
  308.     rc = psUsingDirectory("/tmp/rhimage/RedHat/RPMS", ps);
  309.     
  310.     umount("/tmp/hdimage");
  311.  
  312.     return rc;
  313. }
  314.  
  315. static int hdGetComponentSet(struct installMethod * method,
  316.                    struct pkgSet * ps,
  317.                    struct componentSet * cs) {
  318.     struct hdinfo * hdi = method->data;
  319.     int rc;
  320.  
  321.     if (doMount(hdi->device, "/tmp/hdimage", hdi->type, 1, 0))
  322.     return INST_ERROR;
  323.  
  324.     rc = psReadComponentsFile("/tmp/rhimage/RedHat/base/comps", ps, cs);
  325.     
  326.     umount("/tmp/hdimage");
  327.  
  328.     return rc;
  329. }
  330.  
  331. static int hdPrepareMedia(struct installMethod * method,
  332.                 struct fstab * fstab) {
  333.     struct hdinfo * hdi = method->data;
  334.     int i;
  335.     char * buf;
  336.  
  337.     for (i = 0; i < fstab->numEntries; i++) {
  338.     if (fstab->entries[i].isMounted &&
  339.         !strcmp(fstab->entries[i].device, hdi->device)) break;
  340.     }
  341.  
  342.     if (i < fstab->numEntries) {
  343.     logMessage("device %s is already mounted -- using symlink",
  344.             fstab->entries[i].device);
  345.     buf = alloca(strlen(fstab->entries[i].mntpoint) + 10);
  346.  
  347.     sprintf(buf, "/mnt/%s", fstab->entries[i].mntpoint);
  348.     
  349.     rmdir("/tmp/hdimage");
  350.     if (symlink(buf, "/tmp/hdimage")) {
  351.         logMessage("failed to create symlink %s: %s\n", 
  352.             buf, strerror(errno));
  353.         newtWinMessage(_("Error"), _("Ok"), 
  354.                _("Failed to create symlink for package source."));
  355.         return INST_ERROR;
  356.     }
  357.     } else {
  358.     logMessage("mounting device which contains packages");
  359.     if (doMount(hdi->device, "/tmp/hdimage", hdi->type, 1, 0))
  360.         return INST_ERROR;
  361.     }
  362.  
  363.     return 0;
  364. }
  365.  
  366. static int imageGetPackageSet(struct installMethod * method,
  367.                   struct pkgSet * ps) {
  368.     return psFromHeaderListFile("/tmp/rhimage/RedHat/base/hdlist", ps);
  369. }
  370.  
  371. static int imageGetComponentSet(struct installMethod * method,
  372.                     struct pkgSet * ps,
  373.                     struct componentSet * cs) {
  374.     return psReadComponentsFile("/tmp/rhimage/RedHat/base/comps", ps, cs);
  375. }
  376.  
  377. static int singleimageSetSymlinks(struct installMethod * method, 
  378.                             struct partitionTable table,
  379.                             struct netInfo * netc, 
  380.                   struct intfInfo * intf,
  381.                   struct driversLoaded ** dl) {
  382.     logMessage("making symlink from /tmp/rhimage to image");
  383.     symlink("rhimage", "/tmp/image");
  384.     return 0;
  385. }
  386.  
  387. /* returns a socket file descriptor, a ftpFinishTransfer() must occur after 
  388.    this call */
  389. static int ftpinstStartTransfer(struct ftpinfo * fi, char * filename) {
  390.     char * buf;
  391.     newtComponent form;
  392.     int fd;
  393.  
  394.     logMessage("ftping %s to a fd", filename);
  395.  
  396.     newtCenteredWindow(60, 3, _("Retrieving"));
  397.  
  398.     buf = alloca(strlen(fi->prefix) + strlen(filename) + 30);
  399.     sprintf(buf, "%s %s...", _("Retrieving"), filename);
  400.     form = newtForm(NULL, NULL, 0);
  401.     newtFormAddComponent(form, newtLabel(1, 1, buf));
  402.  
  403.     newtDrawForm(form);
  404.     newtRefresh();
  405.  
  406.     strcpy(buf, fi->prefix);
  407.     strcat(buf, "/RedHat/");
  408.     strcat(buf, filename);
  409.     fd = ftpGetFileDesc(fi->sock, buf);
  410.  
  411.     return fd;
  412. }
  413.  
  414. static int ftpinstFinishTransfer(struct ftpinfo * fi) {
  415.     newtPopWindow();
  416.  
  417.     return ftpGetFileDone(fi->sock);
  418. }
  419.  
  420. static int ftpinstGetFile(struct ftpinfo * fi, char * filename, char * dest) {
  421.     char * buf;
  422.     newtComponent form;
  423.     int fd, rc;
  424.  
  425.     logMessage("ftping %s as %s", filename, dest);
  426.  
  427.     newtCenteredWindow(60, 3, _("Retrieving"));
  428.  
  429.     buf = alloca(strlen(fi->prefix) + strlen(filename) + 30);
  430.     sprintf(buf, "%s %s...", _("Retrieving"), filename);
  431.     form = newtForm(NULL, NULL, 0);
  432.     newtFormAddComponent(form, newtLabel(1, 1, buf));
  433.  
  434.     newtDrawForm(form);
  435.     newtRefresh();
  436.  
  437.     fd = open(dest, O_WRONLY | O_CREAT, 0644);
  438.     if (fd < 0) {
  439.     newtWinMessage(_("Error"), _("Ok"), _("open of %s failed: %s\n"), 
  440.             dest, strerror(errno));
  441.     return INST_ERROR;
  442.     }
  443.  
  444.     strcpy(buf, fi->prefix);
  445.     strcat(buf, "/RedHat/");
  446.     strcat(buf, filename);
  447.     rc = ftpGetFile(fi->sock, buf, fd);
  448.  
  449.     close(fd);
  450.  
  451.     newtFormDestroy(form);
  452.     newtPopWindow();
  453.  
  454.     if (rc) {
  455.     newtWinMessage("ftp", _("Ok"), _("I cannot get file %s: %s\n"), buf,
  456.             ftpStrerror(rc));
  457.     return INST_ERROR;
  458.     }
  459.  
  460.     return 0;
  461. }
  462.  
  463. static int ftpMainSetupPanel(struct ftpinfo * fi, char * doSecondarySetup) {
  464.     newtComponent form, okay, cancel, siteEntry, dirEntry, answer, text, cb;
  465.     char * site, * dir;
  466.     char * reflowedText;
  467.     int width, height;
  468.     newtGrid entryGrid, buttons, grid;
  469.  
  470.     if (fi->address) {
  471.     site = fi->address;
  472.     dir = fi->prefix;
  473.     } else {
  474.     site = "";
  475.     dir = "";
  476.     }
  477.  
  478.     if (fi->login || fi->password || fi->login)
  479.     *doSecondarySetup = '*';
  480.     else
  481.     *doSecondarySetup = ' ';
  482.  
  483.     buttons = newtButtonBar(_("Ok"), &okay, _("Back"), &cancel, NULL);
  484.  
  485.     reflowedText = newtReflowText(
  486.     _("Please enter the following information:\n"
  487.       "\n"
  488.       "    o the name or IP number of your FTP server\n" 
  489.       "    o the directory on that server containing\n" 
  490.       "      Red Hat Linux for your architecure\n"), 
  491.     47, 5, 5, &width, &height);
  492.     text = newtTextbox(-1, -1, width, height, NEWT_TEXTBOX_WRAP);
  493.     newtTextboxSetText(text, reflowedText);
  494.     free(reflowedText);
  495.  
  496.     siteEntry = newtEntry(22, 8, site, 24, &site, NEWT_ENTRY_SCROLL);
  497.     dirEntry = newtEntry(22, 9, dir, 24, &dir, NEWT_ENTRY_SCROLL);
  498.  
  499.     entryGrid = newtCreateGrid(2, 2);
  500.     newtGridSetField(entryGrid, 0, 0, NEWT_GRID_COMPONENT,
  501.              newtLabel(-1, -1, _("FTP site name:")),
  502.              0, 0, 1, 0, NEWT_ANCHOR_LEFT, 0);
  503.     newtGridSetField(entryGrid, 0, 1, NEWT_GRID_COMPONENT,
  504.              newtLabel(-1, -1, _("Red Hat directory:")),
  505.              0, 0, 1, 0, NEWT_ANCHOR_LEFT, 0);
  506.     newtGridSetField(entryGrid, 1, 0, NEWT_GRID_COMPONENT, siteEntry,
  507.              0, 0, 0, 0, 0, 0);
  508.     newtGridSetField(entryGrid, 1, 1, NEWT_GRID_COMPONENT, dirEntry,
  509.              0, 0, 0, 0, 0, 0);
  510.  
  511.     cb = newtCheckbox(3, 11, _("Use non-anonymous ftp or a proxy server"),
  512.             *doSecondarySetup, NULL, doSecondarySetup);
  513.  
  514.     grid = newtCreateGrid(1, 4);
  515.     newtGridSetField(grid, 0, 0, NEWT_GRID_COMPONENT, text,
  516.              0, 0, 0, 1, 0, 0);
  517.     newtGridSetField(grid, 0, 1, NEWT_GRID_SUBGRID, entryGrid,
  518.              0, 0, 0, 1, 0, 0);
  519.     newtGridSetField(grid, 0, 2, NEWT_GRID_COMPONENT, cb,
  520.              0, 0, 0, 1, NEWT_ANCHOR_LEFT, 0);
  521.     newtGridSetField(grid, 0, 3, NEWT_GRID_SUBGRID, buttons,
  522.              0, 0, 0, 0, 0, NEWT_GRID_FLAG_GROWX);
  523.  
  524.     newtGridWrappedWindow(grid, _("FTP Setup"));
  525.  
  526.     form = newtForm(NULL, NULL, 0);
  527.     newtGridAddComponentsToForm(grid, form, 1);    
  528.  
  529.     answer = newtRunForm(form);
  530.     if (answer == cancel) {
  531.     newtFormDestroy(form);
  532.     newtPopWindow();
  533.     
  534.     return INST_CANCEL;
  535.     }
  536.  
  537.     if (fi->address) free(fi->address);
  538.     fi->address = strdup(site);
  539.  
  540.     if (fi->prefix) free(fi->prefix);
  541.     fi->prefix = strdup(dir);
  542.  
  543.     newtFormDestroy(form);
  544.     newtPopWindow();
  545.  
  546.     return 0;
  547. }
  548.  
  549. static int ftpSecondarySetupPanel(struct ftpinfo * fi) {
  550.     newtComponent form, okay, cancel, answer, text, accountEntry;
  551.     newtComponent passwordEntry, proxyEntry;
  552.     char * account, * password, * proxy;
  553.     newtGrid buttons, entryGrid, grid;
  554.     char * reflowedText;
  555.     int width, height;
  556.  
  557.     reflowedText = newtReflowText(
  558.     _("If you are using non anonymous ftp, enter the account name and "
  559.       "password you wish to use below. If you are using an FTP proxy "
  560.       "enter the name of the FTP proxy server to use."),
  561.     47, 5, 5, &width, &height);
  562.     text = newtTextbox(-1, -1, width, height, NEWT_TEXTBOX_WRAP);
  563.     newtTextboxSetText(text, reflowedText);
  564.     free(reflowedText);
  565.  
  566.     accountEntry = newtEntry(-1, -1, fi->login, 24, &account, 
  567.                  NEWT_ENTRY_SCROLL);
  568.     passwordEntry = newtEntry(-1, -1, NULL, 24, &password, 
  569.                 NEWT_ENTRY_SCROLL | NEWT_ENTRY_HIDDEN);
  570.     proxyEntry = newtEntry(-1, -1, fi->proxy, 24, &proxy, NEWT_ENTRY_SCROLL);
  571.  
  572.     entryGrid = newtCreateGrid(2, 3);
  573.     newtGridSetField(entryGrid, 0, 0, NEWT_GRID_COMPONENT,
  574.              newtLabel(-1, -1, _("Account name:")),
  575.              0, 0, 1, 0, NEWT_ANCHOR_LEFT, 0);
  576.     newtGridSetField(entryGrid, 0, 1, NEWT_GRID_COMPONENT,
  577.              newtLabel(-1, -1, _("Password:")),
  578.              0, 0, 1, 0, NEWT_ANCHOR_LEFT, 0);
  579.     newtGridSetField(entryGrid, 0, 2, NEWT_GRID_COMPONENT,
  580.              newtLabel(-1, -1, _("FTP Proxy:")),
  581.              0, 1, 1, 0, NEWT_ANCHOR_LEFT, 0);
  582.     newtGridSetField(entryGrid, 1, 0, NEWT_GRID_COMPONENT, accountEntry,
  583.              0, 0, 0, 0, 0, 0);
  584.     newtGridSetField(entryGrid, 1, 1, NEWT_GRID_COMPONENT, passwordEntry,
  585.              0, 0, 0, 0, 0, 0);
  586.     newtGridSetField(entryGrid, 1, 2, NEWT_GRID_COMPONENT, proxyEntry,
  587.              0, 1, 0, 0, 0, 0);
  588.  
  589.     buttons = newtButtonBar(_("Ok"), &okay, _("Cancel"), &cancel, NULL);
  590.  
  591.     grid = newtCreateGrid(1, 3);
  592.     newtGridSetField(grid, 0, 0, NEWT_GRID_COMPONENT, text, 0, 0, 0, 0, 0, 0);
  593.     newtGridSetField(grid, 0, 1, NEWT_GRID_SUBGRID, entryGrid, 
  594.              0, 1, 0, 0, 0, 0);
  595.     newtGridSetField(grid, 0, 2, NEWT_GRID_SUBGRID, buttons, 
  596.              0, 1, 0, 0, 0, NEWT_GRID_FLAG_GROWX);
  597.  
  598.     newtGridWrappedWindow(grid, "Further FTP Setup");
  599.  
  600.     form = newtForm(NULL, NULL, 0);
  601.     newtGridAddComponentsToForm(grid, form, 1);
  602.     newtGridFree(grid, 1);
  603.  
  604.     answer = newtRunForm(form);
  605.     if (answer == cancel) {
  606.     newtFormDestroy(form);
  607.     newtPopWindow();
  608.     
  609.     return INST_CANCEL;
  610.     }
  611.  
  612.     if (fi->login) free(fi->login);
  613.     if (strlen(account))
  614.     fi->login = strdup(account);
  615.     else
  616.     fi->login = NULL;
  617.  
  618.     if (fi->password) free(fi->password);
  619.     if (strlen(password))
  620.     fi->password = strdup(password);
  621.     else
  622.     fi->password = NULL;
  623.  
  624.     if (fi->proxy) free(fi->proxy);
  625.     if (strlen(proxy))
  626.     fi->proxy = strdup(proxy);
  627.     else
  628.     fi->proxy = NULL;
  629.  
  630.     newtFormDestroy(form);
  631.     newtPopWindow();
  632.  
  633.     return 0;
  634. }
  635.  
  636. static int ftpSetup(struct installMethod * method, struct partitionTable table,
  637.                 struct netInfo * netc, struct intfInfo * intf,
  638.                 struct driversLoaded ** dl) {
  639.     struct ftpinfo fi;
  640.     enum { FTP_SETUP_NET, FTP_SETUP_FTP1, FTP_SETUP_FTP2, FTP_SETUP_CHECK, 
  641.         FTP_SETUP_DONE } step = FTP_SETUP_NET;
  642.     int rc, fd;
  643.     char doMore;
  644.  
  645.     memset(&fi, 0, sizeof(fi));
  646.  
  647.     if (method->data)
  648.     memcpy(&fi, method->data, sizeof(fi));
  649.     else
  650.     memset(&fi, 0, sizeof(fi));
  651.  
  652.     while (step != FTP_SETUP_DONE) {
  653.     switch (step) {
  654.  
  655.       case FTP_SETUP_NET:
  656.         rc = bringUpNetworking(intf, netc, dl, 1);
  657.         if (rc) return rc;
  658.         step = FTP_SETUP_FTP1;
  659.         break;
  660.  
  661.       case FTP_SETUP_FTP1:
  662.         rc = ftpMainSetupPanel(&fi, &doMore);
  663.         if (rc == INST_ERROR) 
  664.         return rc;
  665.         else if (rc)
  666.         step = FTP_SETUP_NET;
  667.         else if (doMore == ' ')
  668.         step = FTP_SETUP_CHECK;
  669.         else 
  670.         step = FTP_SETUP_FTP2;
  671.         break;
  672.  
  673.       case FTP_SETUP_FTP2:
  674.         rc = ftpSecondarySetupPanel(&fi);
  675.         if (rc == INST_ERROR) 
  676.         return rc;
  677.         else if (rc)
  678.         step = FTP_SETUP_FTP1;
  679.         else
  680.         step = FTP_SETUP_CHECK;
  681.         break;
  682.  
  683.       case FTP_SETUP_CHECK:
  684.         if ((fi.sock = ftpOpen(fi.address, fi.login, 
  685.                    fi.password ? fi.password : "rhinstall@", 
  686.                    fi.proxy, -1)) < 0) {
  687.         newtWinMessage(_("ftp"), _("Ok"), 
  688.                 _("I cannot log into machine: %s\n"),
  689.                 ftpStrerror(fi.sock));
  690.         step = FTP_SETUP_FTP1;
  691.         break;
  692.         }
  693.  
  694.         
  695.         fd = ftpinstStartTransfer(&fi, "base/hdlist");
  696.         if (fd < 0) {
  697.         newtPopWindow();
  698.         ftpClose(fi.sock);
  699.         step = FTP_SETUP_FTP1;
  700.         break;
  701.         }
  702.  
  703.         if (psFromHeaderListDesc(fd, &fi.ps, 1)) {
  704.         ftpClose(fi.sock);
  705.         step = FTP_SETUP_FTP1;
  706.         break;
  707.         }
  708.  
  709.         ftpinstFinishTransfer(&fi);
  710.  
  711.         if (ftpinstGetFile(&fi, "base/comps", "/tmp/comps")) {
  712.         ftpClose(fi.sock);
  713.         step = FTP_SETUP_FTP1;
  714.         break;
  715.         }
  716.         
  717.         step = FTP_SETUP_DONE;
  718.         break;
  719.  
  720.       case FTP_SETUP_DONE:
  721.         break;
  722.     }
  723.     }
  724.  
  725.     if (method->data) free(method->data);
  726.     method->data = malloc(sizeof(fi));
  727.     memcpy(method->data, &fi, sizeof(fi));
  728.  
  729.     return 0;
  730. }
  731.  
  732. static int ftpGetPackageSet(struct installMethod * method,
  733.                  struct pkgSet * ps) {
  734.     struct ftpinfo * fi = method->data;
  735.  
  736.     *ps = fi->ps;
  737.     return 0;
  738. }
  739.  
  740. static int ftpGetComponentSet(struct installMethod * method,
  741.                    struct pkgSet * ps,
  742.                    struct componentSet * cs) {
  743.     return psReadComponentsFile("/tmp/comps", ps, cs);
  744. }
  745.  
  746. static int ftpinstGetMappedFile(struct installMethod * method, char * name, 
  747.                         char ** realName) {
  748.     static char sbuf[300];
  749.     char * buf;
  750.     int rc;
  751.     struct ftpinfo * fi = method->data;
  752.     int tries;
  753.  
  754.     if (access("/mnt/var/tmp", X_OK))
  755.     strcpy(sbuf, "/tmp/");
  756.     else
  757.     strcpy(sbuf, "/mnt/var/tmp/");
  758.  
  759.     strcat(sbuf, name);
  760.     *realName = sbuf;
  761.  
  762.     buf = alloca(strlen(name) + 30);
  763.     if (fileInBase(name))
  764.     strcpy(buf, "base/");
  765.     else
  766.     strcpy(buf, "RPMS/");
  767.     strcat(buf, name);
  768.  
  769.     rc = ftpinstGetFile(fi, buf, *realName);
  770.     if (!rc) return 0;
  771.  
  772.     tries = 5;
  773.     while (rc) {
  774.     /* Try again, and relogin */
  775.     ftpClose(fi->sock);
  776.  
  777.     if ((fi->sock = ftpOpen(fi->address, fi->login, 
  778.                 fi->password ? fi->password : "rhinstall@", 
  779.                 fi->proxy, -1)) 
  780.             < 0) {
  781.         newtWinMessage(_("ftp"), _("Ok"), _("I cannot log into machine: %s\n"),
  782.                 ftpStrerror(fi->sock));
  783.         free(fi);
  784.         return INST_ERROR;
  785.     }
  786.  
  787.     if (!--tries) {
  788.         rc = newtWinChoice(_("ftp"), _("Yes"), _("No"),
  789.             _("I'm having trouble getting %s. Should I keep trying?"));
  790.         if (rc == 1) return INST_ERROR;
  791.         rc = 1, tries = 5;
  792.     }
  793.     }
  794.  
  795.     return 0;
  796. }
  797.  
  798. #ifdef __i386__
  799. static int smbSetup(struct installMethod * method, struct partitionTable table,
  800.                struct netInfo * netc, struct intfInfo * intf,
  801.                struct driversLoaded ** dl) {
  802.     char * host = NULL, * dir = NULL, * acct = NULL, * pass = NULL;
  803.     char * buf;
  804.     static int moduleLoaded = 0;
  805.     enum { SMB_STEP_NET, SMB_STEP_INFO, SMB_STEP_MOUNT, SMB_STEP_DONE }
  806.         step = SMB_STEP_NET;
  807.     int rc;
  808.  
  809.     while (step != SMB_STEP_DONE) {
  810.     switch (step) {
  811.       case SMB_STEP_NET:
  812.         rc = bringUpNetworking(intf, netc, dl, 1);
  813.         if (rc) return rc;
  814.         step = SMB_STEP_INFO;
  815.         break;
  816.  
  817.       case SMB_STEP_INFO:
  818.         rc = smbGetSetup(&host, &dir, &acct, &pass);
  819.         if (rc == INST_CANCEL)
  820.         step = SMB_STEP_NET;
  821.         else if (rc == INST_ERROR)
  822.         return INST_ERROR;
  823.         else
  824.         step = SMB_STEP_MOUNT;
  825.         break;
  826.  
  827.       case SMB_STEP_MOUNT:
  828.         if (!strlen(host) || !strlen(dir))
  829.         rc = INST_ERROR;
  830.         else {
  831.         buf = malloc(strlen(host) + strlen(dir) + 10);
  832.         strcpy(buf, host);
  833.         strcat(buf, ":");
  834.         strcat(buf, dir);
  835.  
  836.         if (!moduleLoaded) {
  837.             rc = loadModule("smbfs", DRIVER_FS, DRIVER_MINOR_NONE, dl);
  838.             if (rc) return rc;
  839.             moduleLoaded = 1;
  840.         }
  841.  
  842.         rc = doPwMount(buf, "/tmp/rhimage", "smb", 1, 0, acct, pass);
  843.  
  844.         free(buf);
  845.         }
  846.  
  847.         if (rc) {
  848.         step = SMB_STEP_INFO;
  849.         newtWinMessage("Error", "Ok", 
  850.             "I could not mount that directory from the server");
  851.         } else {
  852.             if (access("/tmp/rhimage/RedHat", R_OK)) {
  853.             step = SMB_STEP_INFO;
  854.             newtWinMessage(_("Error"), _("Ok"), 
  855.                  _("That directory does not seem "
  856.                    "to contain a Red Hat installation tree."));
  857.             umount("/tmp/rhimage");
  858.         } else
  859.             step = SMB_STEP_DONE;
  860.         }
  861.  
  862.         break;
  863.  
  864.       case SMB_STEP_DONE:
  865.         break;
  866.     }
  867.     }
  868.  
  869.     free(host);
  870.     free(dir);
  871.  
  872.     return 0;
  873. }
  874.  
  875. static int smbGetSetup(char ** finalHostptr, char ** finalDirptr, 
  876.             char ** finalAcctptr, char ** finalPwptr) {
  877.     char * host = *finalHostptr;
  878.     char * dir = *finalDirptr;
  879.     char * acct = *finalAcctptr;
  880.     char * pass = *finalPwptr;
  881.     int result;
  882.     struct newtWinEntry entries[] = {
  883.     { NULL, &host, NEWT_ENTRY_SCROLL },
  884.     { NULL, &dir, NEWT_ENTRY_SCROLL },
  885.     { NULL, &acct, NEWT_ENTRY_SCROLL },
  886.     { NULL, &pass, NEWT_ENTRY_SCROLL },
  887.     { NULL, NULL, 0 } };
  888.  
  889.     entries[0].text = _("SMB server name  :");
  890.     entries[1].text = _("Share volume     :");
  891.     entries[2].text = _("Account name     :");
  892.     entries[3].text = _("Password         :");
  893.  
  894.     result = newtWinEntries(_("SMB Setup"), 
  895.         _("Please enter the following information:\n"
  896.           "\n"
  897.           "    o the name or IP number of your SMB server\n"
  898.           "    o the volume to share which contains\n"
  899.           "      Red Hat Linux for your architecture"),
  900.         50, 5, 5, 24, entries, _("Ok"), _("Cancel"), NULL);
  901.  
  902.     if (result == 2) {
  903.         free(host);
  904.         free(dir);
  905.         free(acct);
  906.         free(pass);
  907.     
  908.     return INST_CANCEL;
  909.     }
  910.  
  911.     if (*finalHostptr) free(*finalHostptr);
  912.     if (*finalDirptr) free(*finalDirptr);
  913.     if (*finalAcctptr) free(*finalAcctptr);
  914.     if (*finalPwptr) free(*finalPwptr);
  915.  
  916.     *finalHostptr = host;
  917.     *finalDirptr = dir;
  918.     *finalAcctptr = acct;
  919.     *finalPwptr = pass;
  920.  
  921.     return 0;
  922. }
  923.  
  924. static int smbGetPackageSet(struct installMethod * method,
  925.                  struct pkgSet * ps) {
  926.     return psUsingDirectory("/tmp/rhimage/RedHat/RPMS", ps);
  927. }
  928.  
  929. static int smbGetComponentSet(struct installMethod * method,
  930.                    struct pkgSet * ps,
  931.                    struct componentSet * cs) {
  932.     return psReadComponentsFile("/tmp/rhimage/RedHat/base/comps", ps, cs);
  933. }
  934.  
  935.  
  936. #endif
  937.