示例#1
0
static char *newKickstartLocation(const char *origLocation) {
    const char *location;
    char *retval = NULL;
    newtComponent f, okay, cancel, answer, locationEntry;
    newtGrid grid, buttons;

    startNewt();

    locationEntry = newtEntry(-1, -1, NULL, 60, &location, NEWT_FLAG_SCROLL);
    newtEntrySet(locationEntry, origLocation, 1);

    /* button bar at the bottom of the window */
    buttons = newtButtonBar(_("OK"), &okay, _("Cancel"), &cancel, NULL);

    grid = newtCreateGrid(1, 3);

    newtGridSetField(grid, 0, 0, NEWT_GRID_COMPONENT,
                     newtTextboxReflowed(-1, -1, _("Unable to download the kickstart file.  Please modify the kickstart parameter below or press Cancel to proceed as an interactive installation."), 60, 0, 0, 0),
                     0, 0, 0, 0, NEWT_ANCHOR_LEFT, 0);
    newtGridSetField(grid, 0, 1, NEWT_GRID_COMPONENT, locationEntry,
                     0, 1, 0, 0, NEWT_ANCHOR_LEFT, 0);
    newtGridSetField(grid, 0, 2, NEWT_GRID_SUBGRID, buttons,
                     0, 1, 0, 0, 0, NEWT_GRID_FLAG_GROWX);

    f = newtForm(NULL, NULL, 0);
    newtGridAddComponentsToForm(grid, f, 1);
    newtGridWrappedWindow(grid, _("Error downloading kickstart file"));
    newtGridFree(grid, 1);

    /* run the form */
    answer = newtRunForm(f);

    if (answer != cancel)
        retval = strdup(location);

    newtFormDestroy(f);
    newtPopWindow();

    return retval;
}
示例#2
0
int urlSecondarySetupPanel(struct iurlinfo * ui, urlprotocol protocol) {
    newtComponent form, okay, cancel, answer, text, accountEntry = NULL;
    newtComponent passwordEntry = NULL, proxyEntry = NULL;
    newtComponent proxyPortEntry = NULL;
    char * account, * password, * proxy, * proxyPort;
    newtGrid buttons, entryGrid, grid;
    char * reflowedText = NULL;
    int width, height;

    if (protocol == URL_METHOD_FTP) {
        reflowedText = newtReflowText(
        _("If you are using non anonymous ftp, enter the account name and "
          "password you wish to use below."),
        47, 5, 5, &width, &height);
    } else {
        reflowedText = newtReflowText(
        _("If you are using a HTTP proxy server "
          "enter the name of the HTTP proxy server to use."),
        47, 5, 5, &width, &height);
    }
    text = newtTextbox(-1, -1, width, height, NEWT_TEXTBOX_WRAP);
    newtTextboxSetText(text, reflowedText);
    free(reflowedText);

    if (protocol == URL_METHOD_FTP) {
        accountEntry = newtEntry(-1, -1, NULL, 24, (const char **) &account, 
                                 NEWT_FLAG_SCROLL);
        passwordEntry = newtEntry(-1, -1, NULL, 24, (const char **) &password, 
                                  NEWT_FLAG_SCROLL | NEWT_FLAG_PASSWORD);
    }
    proxyEntry = newtEntry(-1, -1, ui->proxy, 24, (const char **) &proxy, 
                           NEWT_ENTRY_SCROLL);
    proxyPortEntry = newtEntry(-1, -1, ui->proxyPort, 6, 
                               (const char **) &proxyPort, NEWT_FLAG_SCROLL);

    entryGrid = newtCreateGrid(2, 4);
    if (protocol == URL_METHOD_FTP) {
        newtGridSetField(entryGrid, 0, 0, NEWT_GRID_COMPONENT,
                     newtLabel(-1, -1, _("Account name:")),
                     0, 0, 2, 0, NEWT_ANCHOR_LEFT, 0);
        newtGridSetField(entryGrid, 0, 1, NEWT_GRID_COMPONENT,
                     newtLabel(-1, -1, _("Password:"******"OK"), &okay, _("Back"), &cancel, NULL);

    grid = newtCreateGrid(1, 3);
    newtGridSetField(grid, 0, 0, NEWT_GRID_COMPONENT, text, 0, 0, 0, 0, 0, 0);
    newtGridSetField(grid, 0, 1, NEWT_GRID_SUBGRID, entryGrid, 
                     0, 1, 0, 0, 0, 0);
    newtGridSetField(grid, 0, 2, NEWT_GRID_SUBGRID, buttons, 
                     0, 1, 0, 0, 0, NEWT_GRID_FLAG_GROWX);

    if (protocol == URL_METHOD_FTP) {
        newtGridWrappedWindow(grid, _("Further FTP Setup"));
    } else {
        if (protocol == URL_METHOD_HTTP)
            newtGridWrappedWindow(grid, _("Further HTTP Setup"));
    }

    form = newtForm(NULL, NULL, 0);
    newtGridAddComponentsToForm(grid, form, 1);
    newtGridFree(grid, 1);

    answer = newtRunForm(form);
    if (answer == cancel) {
        newtFormDestroy(form);
        newtPopWindow();
        
        return LOADER_BACK;
    }
 
    if (protocol == URL_METHOD_FTP) {
        if (ui->login) free(ui->login);
        if (strlen(account))
            ui->login = strdup(account);
        else
            ui->login = NULL;
        
        if (ui->password) free(ui->password);
        if (strlen(password))
            ui->password = strdup(password);
        else
            ui->password = NULL;
    }
    
    newtFormDestroy(form);
    newtPopWindow();

    return 0;
}
示例#3
0
int urlMainSetupPanel(struct iurlinfo * ui, urlprotocol protocol,
                      char * doSecondarySetup) {
    newtComponent form, okay, cancel, siteEntry, dirEntry;
    newtComponent answer, text;
    newtComponent cb = NULL;
    char * site, * dir;
    char * reflowedText = NULL;
    int width, height;
    newtGrid entryGrid, buttons, grid;
    char * chptr;
    char * buf = NULL;

    if (ui->address) {
        site = ui->address;
        dir = ui->prefix;
    } else {
        site = "";
        dir = "";
    }

    if (ui->login || ui->password || ui->proxy || ui->proxyPort)
        *doSecondarySetup = '*';
    else
        *doSecondarySetup = ' ';

    buttons = newtButtonBar(_("OK"), &okay, _("Back"), &cancel, NULL);
    
    switch (protocol) {
    case URL_METHOD_FTP:
        buf = sdupprintf(_(netServerPrompt), _("FTP"), getProductName());
        reflowedText = newtReflowText(buf, 47, 5, 5, &width, &height);
        free(buf);
        break;
    case URL_METHOD_HTTP:
        buf = sdupprintf(_(netServerPrompt), _("Web"), getProductName());
        reflowedText = newtReflowText(buf, 47, 5, 5, &width, &height);
        free(buf);
        break;

#ifdef ROCKS
    case URL_METHOD_HTTPS:
        buf = sdupprintf(_(netServerPrompt), "Secure Web", getProductName());
        reflowedText = newtReflowText(buf, 47, 5, 5, &width, &height);
        free(buf);
        break;
#endif /* ROCKS */
    }
    text = newtTextbox(-1, -1, width, height, NEWT_TEXTBOX_WRAP);
    newtTextboxSetText(text, reflowedText);
    free(reflowedText);

    siteEntry = newtEntry(22, 8, site, 24, (const char **) &site, 
                          NEWT_ENTRY_SCROLL);
    dirEntry = newtEntry(22, 9, dir, 24, (const char **) &dir, 
                         NEWT_ENTRY_SCROLL);

    entryGrid = newtCreateGrid(2, 2);
    newtGridSetField(entryGrid, 0, 0, NEWT_GRID_COMPONENT,
                     newtLabel(-1, -1, (protocol == URL_METHOD_FTP) ?
                                        _("FTP site name:") :
                                        _("Web site name:")),
                     0, 0, 1, 0, NEWT_ANCHOR_LEFT, 0);
    newtGridSetField(entryGrid, 0, 1, NEWT_GRID_COMPONENT,
                     newtLabel(-1, -1, 
                               sdupprintf(_("%s directory:"), 
                                          getProductName())),
                     0, 0, 1, 0, NEWT_ANCHOR_LEFT, 0);
    newtGridSetField(entryGrid, 1, 0, NEWT_GRID_COMPONENT, siteEntry,
                     0, 0, 0, 0, 0, 0);
    newtGridSetField(entryGrid, 1, 1, NEWT_GRID_COMPONENT, dirEntry,
                     0, 0, 0, 0, 0, 0);

    grid = newtCreateGrid(1, 4);
    newtGridSetField(grid, 0, 0, NEWT_GRID_COMPONENT, text,
                     0, 0, 0, 1, 0, 0);
    newtGridSetField(grid, 0, 1, NEWT_GRID_SUBGRID, entryGrid,
                     0, 0, 0, 1, 0, 0);

    if (protocol == URL_METHOD_FTP) {
        cb = newtCheckbox(3, 11, _("Use non-anonymous ftp"),
                          *doSecondarySetup, NULL, doSecondarySetup);
        newtGridSetField(grid, 0, 2, NEWT_GRID_COMPONENT, cb,
                         0, 0, 0, 1, NEWT_ANCHOR_LEFT, 0);
    }
        
    newtGridSetField(grid, 0, 3, NEWT_GRID_SUBGRID, buttons,
                     0, 0, 0, 0, 0, NEWT_GRID_FLAG_GROWX);

    newtGridWrappedWindow(grid, (protocol == URL_METHOD_FTP) ? _("FTP Setup") :
                          _("HTTP Setup"));

    form = newtForm(NULL, NULL, 0);
    newtGridAddComponentsToForm(grid, form, 1);    

    do {
        answer = newtRunForm(form);
        if (answer != cancel) {
            if (!strlen(site)) {
                newtWinMessage(_("Error"), _("OK"),
                               _("You must enter a server name."));
                continue;
            }
            if (!strlen(dir)) {
                newtWinMessage(_("Error"), _("OK"),
                               _("You must enter a directory."));
                continue;
            }

            if (!addrToIp(site)) {
                newtWinMessage(_("Unknown Host"), _("OK"),
                        _("%s is not a valid hostname."), site);
                continue;
            }
        }

        break;
    } while (1);
    
    if (answer == cancel) {
        newtFormDestroy(form);
        newtPopWindow();
        
        return LOADER_BACK;
    }

    if (ui->address) free(ui->address);
    ui->address = strdup(site);

    if (ui->prefix) free(ui->prefix);

    /* add a slash at the start of the dir if it is missing */
    if (*dir != '/') {
        if (asprintf(&(ui->prefix), "/%s", dir) == -1)
            ui->prefix = strdup(dir);
    } else {
        ui->prefix = strdup(dir);
    }

    /* Get rid of trailing /'s */
    chptr = ui->prefix + strlen(ui->prefix) - 1;
    while (chptr > ui->prefix && *chptr == '/') chptr--;
    chptr++;
    *chptr = '\0';

    if (*doSecondarySetup != '*') {
        if (ui->login)
            free(ui->login);
        if (ui->password)
            free(ui->password);
        if (ui->proxy)
            free(ui->proxy);
        if (ui->proxyPort)
            free(ui->proxyPort);
        ui->login = ui->password = ui->proxy = ui->proxyPort = NULL;
    }

    ui->protocol = protocol;

    newtFormDestroy(form);
    newtPopWindow();

    return 0;
}
示例#4
0
/* Browse through a directory structure looking for a file.
 * Returns the full path to the file.
 *
 * Parameters:
 * title: Title for newt dialog window
 * dirname: Directory to use for root of browsing.  NOTE: you cannot go
 *          up above this root.
 * filterfunc: An (optional)  function to filter out files based on whatever
 *             criteria you want.  Returns 1 if it passes, 0 if not.
 *             Function should take arguments of the directory name and
 *             the dirent for the file.
 */
char * newt_select_file(char * title, char * text, char * dirname,
                        int (*filterfunc)(char *, struct dirent *)) {
    char ** files;
    char * fn = NULL;
    int i, done = 0;
    char * topdir = dirname;
    char * dir = malloc(PATH_MAX);
    char * path = NULL;
    newtGrid grid, buttons;
    newtComponent f, tb, listbox, ok, cancel;
    struct stat sb;
    struct newtExitStruct es;

    dir = realpath(dirname, dir);

    do {
        files = get_file_list(dir, filterfunc);

        f = newtForm(NULL, NULL, 0);
        grid = newtCreateGrid(1, 4);

        tb = newtTextboxReflowed(-1, -1, text, 60, 0, 10, 0);

        listbox = newtListbox(12, 65, 10,
                              NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);

        newtListboxSetWidth(listbox, 55);
        buttons = newtButtonBar(_("OK"), &ok, _("Cancel"), &cancel, NULL);
        newtGridSetField(grid, 0, 0, NEWT_GRID_COMPONENT, tb,
                         0, 0, 0, 1, 0, 0);
        newtGridSetField(grid, 0, 1, NEWT_GRID_COMPONENT, listbox,
                         0, 0, 0, 1, 0, 0);
        newtGridSetField(grid, 0, 3, NEWT_GRID_SUBGRID, buttons,
                         0, 0, 0, 0, 0, NEWT_GRID_FLAG_GROWX);

        /* if this isn't our topdir, we want to let them go up a dir */
        if (strcmp(topdir, dir))
            newtListboxAppendEntry(listbox, "../", "..");

        for (i = 0; (files[i] != NULL); i++) {
            if ((files[i] == NULL) || (strlen(files[i]) == 0)) continue;
            path = malloc(strlen(files[i]) + strlen(dir) + 2);
            sprintf(path, "%s/%s", dir, files[i]);
            stat(path, &sb);
            free(path);
            if (S_ISDIR(sb.st_mode)) {
                char *dir = malloc(strlen(files[i]) + 2);
                sprintf(dir, "%s/", files[i]);
                newtListboxAppendEntry(listbox, dir, files[i]);
            } else {
                newtListboxAppendEntry(listbox, files[i], files[i]);
            }
        }

        newtGridWrappedWindow(grid, title);
        newtGridAddComponentsToForm(grid, f, 1);
        newtFormRun(f, &es);

        if (es.reason  == NEWT_EXIT_COMPONENT && es.u.co == cancel) {
            fn = NULL;
            done = -1;
        } else {
            fn = (char *) newtListboxGetCurrent(listbox);
            path = malloc(strlen(fn) + strlen(dir) + 2);
            sprintf(path, "%s/%s", dir, fn);

            stat(path, &sb);
            if (!S_ISDIR(sb.st_mode)) {
                fn = path;
                done = 1;
            } else {
                dir = realpath(path, dir);
                free(path);
            }
        }

        newtGridFree(grid, 1);
        newtFormDestroy(f);
        newtPopWindow();
    } while (done == 0);

    return fn;
}
示例#5
0
static int getManualModuleArgs(struct moduleInfo * mod, char *** moduleArgs) {
    newtGrid grid, buttons;
    newtComponent text, f, ok, back, entry;
    struct newtExitStruct es;
    int done = 0, i;
    char * buf;
    char *argsEntry = "";

    if (*moduleArgs) {
        for (i = 0; (*moduleArgs)[i]; i++)
            argsEntry = strcat(argsEntry, (*moduleArgs)[i]);
    }

    f = newtForm(NULL, NULL, 0);
    if (asprintf(&buf,
                 _("Please enter any parameters which you wish to pass "
                   "to the %s module separated by spaces.  If you don't "
                   "know what parameters to supply, skip this screen "
                   "by pressing the \"OK\" button."), mod->moduleName) == -1) {
        logMessage(CRITICAL, "%s: %d: %m", __func__, __LINE__);
        abort();
    }

    text = newtTextboxReflowed(-1, -1, buf, 60, 0, 10, 0);
    entry = newtEntry(-1, -1, argsEntry, 50, (const char **) &argsEntry, 
                      NEWT_ENTRY_SCROLL);
    
    newtFormAddHotKey(f, NEWT_KEY_F12);
    
    buttons = newtButtonBar(_("OK"), &ok, _("Back"), &back, NULL);
    
    grid = newtCreateGrid(1, 3);
    newtGridSetField(grid, 0, 0, NEWT_GRID_COMPONENT, text,
                     0, 0, 0, 1, 0, 0);
    newtGridSetField(grid, 0, 1, NEWT_GRID_COMPONENT, entry, 
                     0, 0, 0, 1, 0, 0);
    newtGridSetField(grid, 0, 2, NEWT_GRID_SUBGRID, buttons,
                     0, 0, 0, 0, 0, NEWT_GRID_FLAG_GROWX);
    
    newtGridWrappedWindow(grid, _("Enter Module Parameters"));
    newtGridAddComponentsToForm(grid, f, 1);
    
    do {
        newtFormRun(f, &es);

        if (es.reason  == NEWT_EXIT_COMPONENT && es.u.co == back) {
            done = -1;
        } else {
            done = 1;
        }
    } while (done == 0);

    free(buf);
    newtGridFree(grid, 1);

    if (done == -1) {
        newtFormDestroy(f);
        newtPopWindow();

        return LOADER_BACK;
    }
    logMessage(INFO, "specified args of %s for %s", argsEntry, mod->moduleName);

    if (strlen(argsEntry) > 0) {
        int numAlloced = 5;
        char * start;
        char * end;

        i = 0;

        *moduleArgs = malloc((numAlloced + 1) * sizeof(*moduleArgs));
        start = argsEntry;
        while (start && *start) {
            end = start;
            while (!isspace(*end) && *end) end++;
            *end = '\0';
            (*moduleArgs)[i++] = strdup(start);
            start = end + 1;
            *end = ' ';
            start = strchr(end, ' ');
            if (start) start++;

            if (i >= numAlloced) {
                numAlloced += 5;
                *moduleArgs = realloc(*moduleArgs, 
                                      sizeof(*moduleArgs) * (numAlloced + 1));
            }
        }
        (*moduleArgs)[i] = NULL;
    }

    newtFormDestroy(f);
    newtPopWindow();

    return LOADER_OK;
}
示例#6
0
/* setup hard drive based install from a partition with a filesystem and
 * ISO images on that filesystem
 */
char * mountHardDrive(struct installMethod * method,
		      char * location, struct loaderData_s * loaderData) {
    int rc;
    int i;

    newtComponent listbox, label, dirEntry, form, okay, back, text;
    struct newtExitStruct es;
    newtGrid entryGrid, grid, buttons;

    int done = 0;
    char * dir = strdup("");
    char * tmpDir;
    char * url = NULL;
    char * buf, *substr;
    int numPartitions;

    char **partition_list;
    char *selpart;
    char *kspartition = NULL, *ksdirectory = NULL;

    /* handle kickstart/stage2= data first if available */
    if (loaderData->method == METHOD_HD && loaderData->stage2Data) {
        kspartition = ((struct hdInstallData *)loaderData->stage2Data)->partition;
        ksdirectory = ((struct hdInstallData *)loaderData->stage2Data)->directory;
        logMessage(INFO, "partition is %s, dir is %s", kspartition, ksdirectory);

        /* if exist, duplicate */
        if (kspartition)
            kspartition = strdup(kspartition);
        if (ksdirectory) {
            ksdirectory = strdup(ksdirectory);
        } else {
            ksdirectory = strdup("/images/install.img");
        }

        if (!kspartition || !ksdirectory) {
            logMessage(ERROR, "missing partition or directory specification");
            loaderData->method = -1;

            if (loaderData->inferredStage2)
                loaderData->invalidRepoParam = 1;
        } else {
            /* if we start with /dev, strip it (#121486) */
            char *kspart = kspartition;
            if (!strncmp(kspart, "/dev/", 5))
                kspart = kspart + 5;

            url = setupIsoImages(kspart, ksdirectory, location);
            if (!url) {
                logMessage(ERROR, "unable to find %s installation images on hd",
                           getProductName());
                loaderData->method = -1;

                if (loaderData->inferredStage2)
                    loaderData->invalidRepoParam = 1;
            } else {
                free(kspartition);
                free(ksdirectory);
                return url;
            }
        }
    } else {
        kspartition = NULL;
        ksdirectory = NULL;
    }

    /* if we're here its either because this is interactive, or the */
    /* hd kickstart directive was faulty and we have to prompt for  */
    /* location of harddrive image                                  */

    partition_list = NULL;
    while (!done) {
        /* if we're doing another pass free this up first */
        if (partition_list)
            freePartitionsList(partition_list);

        partition_list = getPartitionsList(NULL);
        numPartitions = lenPartitionsList(partition_list);

        /* no partitions found, try to load a device driver disk for storage */
        if (!numPartitions) {
            rc = newtWinChoice(_("Hard Drives"), _("Yes"), _("Back"),
                               _("You don't seem to have any hard drives on "
                                 "your system! Would you like to configure "
                                 "additional devices?"));
            if (rc == 2) {
                loaderData->stage2Data = NULL;
                return NULL;
            }

            rc = loadDriverFromMedia(DEVICE_DISK, loaderData, 0, 0);
            continue;
        }

        /* now find out which partition has the stage2 image */
        checked_asprintf(&buf, _("What partition and directory on that "
                                 "partition holds the installation image "
                                 "for %s?  If you don't see the disk drive "
                                 "you're using listed here, press F2 to "
                                 "configure additional devices."),
                         getProductName());

        text = newtTextboxReflowed(-1, -1, buf, 62, 5, 5, 0);
        free(buf);

        listbox = newtListbox(-1, -1, numPartitions > 5 ? 5 : numPartitions,
                              NEWT_FLAG_RETURNEXIT | 
                              (numPartitions > 5 ? NEWT_FLAG_SCROLL : 0));

        for (i = 0; i < numPartitions; i++)
            newtListboxAppendEntry(listbox,partition_list[i],partition_list[i]);

        /* if we had ks data around use it to prime entry, then get rid of it*/
        if (kspartition) {
            newtListboxSetCurrentByKey(listbox, kspartition);
            free(kspartition);
            kspartition = NULL;
        }

        label = newtLabel(-1, -1, _("Directory holding image:"));

        dirEntry = newtEntry(28, 11, dir, 28, (const char **) &tmpDir,
                             NEWT_ENTRY_SCROLL);

        /* if we had ks data around use it to prime entry, then get rid of it*/
        if (ksdirectory) {
            newtEntrySet(dirEntry, ksdirectory, 1);
            free(ksdirectory);
            ksdirectory = NULL;
        }

        entryGrid = newtGridHStacked(NEWT_GRID_COMPONENT, label,
                                     NEWT_GRID_COMPONENT, dirEntry,
                                     NEWT_GRID_EMPTY);

        buttons = newtButtonBar(_("OK"), &okay, _("Back"), &back, NULL);

        grid = newtCreateGrid(1, 4);
        newtGridSetField(grid, 0, 0, NEWT_GRID_COMPONENT, text,
                         0, 0, 0, 1, 0, 0);
        newtGridSetField(grid, 0, 1, NEWT_GRID_COMPONENT, listbox,
                         0, 0, 0, 1, 0, 0);
        newtGridSetField(grid, 0, 2, NEWT_GRID_SUBGRID, entryGrid,
                         0, 0, 0, 1, 0, 0);
        newtGridSetField(grid, 0, 3, NEWT_GRID_SUBGRID, buttons,
                         0, 0, 0, 0, 0, NEWT_GRID_FLAG_GROWX);

        newtGridWrappedWindow(grid, _("Select Partition"));

        form = newtForm(NULL, NULL, 0);
        newtFormAddHotKey(form, NEWT_KEY_F2);
        newtFormAddHotKey(form, NEWT_KEY_F12);

        newtGridAddComponentsToForm(grid, form, 1);
        newtGridFree(grid, 1);

        newtFormRun(form, &es);

        selpart = newtListboxGetCurrent(listbox);

        free(dir);
        if (tmpDir && *tmpDir) {
            /* Protect from form free. */
            dir = strdup(tmpDir);
        } else  {
            dir = strdup("");
        }

        newtFormDestroy(form);
        newtPopWindow();

        if (es.reason == NEWT_EXIT_COMPONENT && es.u.co == back) {
            loaderData->stage2Data = NULL;
            return NULL;
        } else if (es.reason == NEWT_EXIT_HOTKEY && es.u.key == NEWT_KEY_F2) {
            rc = loadDriverFromMedia(DEVICE_DISK, loaderData, 0, 0);
            continue;
        }

        logMessage(INFO, "partition %s selected", selpart);

        /* If the user-provided URL points at a repo instead of a stage2
         * image, fix that up now.
         */
        substr = strstr(dir, ".img");
        if (!substr || (substr && *(substr+4) != '\0')) {
            checked_asprintf(&dir, "%s/images/install.img", dir);
        }

        loaderData->invalidRepoParam = 1;

        url = setupIsoImages(selpart, dir, location);
        if (!url) {
            newtWinMessage(_("Error"), _("OK"), 
                           _("Device %s does not appear to contain "
                             "an installation image."), selpart, getProductName());
            continue;
        }

        done = 1; 
    }

    free(dir);

    return url;
}