#include #include #include #include #include #include #include #include #include #include #include #include #include "hash.h" #include "install.h" #include "intl.h" #include "kickstart.h" #include "log.h" #include "pkgs.h" #include "windows.h" #define FILENAME_TAG 1000000 static int selectPackagesByGroup(struct pkgSet * psp); static int selectPackagesWindow(struct pkgSet * psp, char * group, unsigned int * kSelected); static int skipPackage(char * name); static int selectComponents(struct componentSet * csp, struct pkgSet * psp, int * doIndividual); static int strptrCmp(const void * a, const void * b); static void showPackageInfo(Header h); static int queryIndividual(int * result); char * skipList[] = { "XFree86-8514", "XFree86-AGX", "XFree86-Mach32", "XFree86-Mach64", "XFree86-Mach8", "XFree86-Mono", "XFree86-P9000", "XFree86-S3", "XFree86-S3V", "XFree86-SVGA", "XFree86-VGA16", "XFree86-W32", "XFree86-I128", "metroess", "metrotmpl", NULL }; static int strptrCmp(const void * a, const void * b) { const char * const * one = a; const char * const * two = b; return strcmp(*one, *two); } int pkgCompare(void * first, void * second) { struct packageInfo ** a = first; struct packageInfo ** b = second; /* put packages w/o names at the end */ if (!(*a)->name) return 1; if (!(*b)->name) return -1; return strcasecmp((*a)->name, (*b)->name); }; int psUsingDirectory(char * dirname, struct pkgSet * psp) { DIR * dir; struct dirent * ent; int fd, rc, isSource; Header h; int packagesAlloced; struct pkgSet ps; int count, type; unsigned int * sizeptr; char * name, * group; char * filename; ps.numPackages = 0; packagesAlloced = 5; ps.packages = malloc(sizeof(*ps.packages) * packagesAlloced); logMessage("scanning %s for packages", dirname); dir = opendir(dirname); if (!dir) { errorWindow("error opening directory"); return INST_ERROR; } errno = 0; ent = readdir(dir); if (errno) { free(ps.packages); errorWindow("error reading from directory"); closedir(dir); return INST_ERROR; } filename = alloca(strlen(dirname) + 500); winStatus(33, 3, "Running", "Scanning available packages..."); while (ent) { if (!(ent->d_name[0] == '.' && (ent->d_name[1] == '\0' || ((ent->d_name[1] == '.') && (ent->d_name[2] == '\0'))))) { sprintf(filename, "%s/%s", dirname, ent->d_name); fd = open(filename, O_RDONLY); if (fd < 0) { logMessage("failed to open %s: %s", filename, strerror(errno)); } else { rc = rpmReadPackageHeader(fd, &h, &isSource, NULL, NULL); close(fd); if (rc) { logMessage("failed to rpmReadPackageHeader %s:", ent->d_name); } else { if (ps.numPackages == packagesAlloced) { packagesAlloced += 5; ps.packages = realloc(ps.packages, sizeof(*ps.packages) * packagesAlloced); } ps.packages[ps.numPackages] = malloc(sizeof(struct packageInfo)); ps.packages[ps.numPackages]->h = h; ps.packages[ps.numPackages]->selected = 0; ps.packages[ps.numPackages]->data = strdup(ent->d_name); headerGetEntry(h, RPMTAG_NAME, &type, (void **) &name, &count); if (headerGetEntry(h, RPMTAG_SIZE, &type, (void **) &sizeptr, &count)) ps.packages[ps.numPackages]->size = *sizeptr; else ps.packages[ps.numPackages]->size = 0; if (skipPackage(name)) ps.packages[ps.numPackages]->inmenu = 0; else ps.packages[ps.numPackages]->inmenu = 1; if (!headerGetEntry(h, RPMTAG_GROUP, &type, (void **) &group, &count)) { group = "(unknown group)"; } else if (!strlen(group)) { group = "(unknown group)"; } ps.packages[ps.numPackages]->name = name; ps.packages[ps.numPackages]->group = group; ps.numPackages++; } } } errno = 0; ent = readdir(dir); if (errno) { newtPopWindow(); errorWindow("error reading from directory (2): %s"); free(ps.packages); closedir(dir); return INST_ERROR; } } *psp = ps; qsort(ps.packages, ps.numPackages, sizeof(*ps.packages), (void *) pkgCompare); closedir(dir); newtPopWindow(); return 0; } int psReadComponentsFile(char * filespec, struct pkgSet * psp, struct componentSet * csp) { FILE * f; char buf[255]; int inComp; int line = 0; char * start; char * chptr; int compsAlloced; int packagesAlloced = 0; struct componentSet cs; struct component * currcomp = NULL; struct packageInfo packkey, ** pack; struct packageInfo * keyaddr = &packkey; int i; int baseNum = 0; f = fopen(filespec, "r"); if (!f) { errorWindow(_("Cannot open components file: %s")); return INST_ERROR; } /* get the version number */ line++; if (!fgets(buf, sizeof(buf), f)) { errorWindow(_("Cannot read components file: %s")); fclose(f); return INST_ERROR; } if (strcmp(buf, "0\n") && strcmp(buf, "0.1\n")) { newtWinMessage(_("Error"), _("Ok"), _("Comps file is not version 0.1 as expected")); fclose(f); return INST_ERROR; } compsAlloced = 5; cs.numComponents = 0; cs.comps = malloc(sizeof(*cs.comps) * compsAlloced); cs.base = NULL; inComp = 0; while (fgets(buf, sizeof(buf), f)) { line++; /* remove any trailing '\n', leave chptr at the end of the string */ chptr = buf + strlen(buf) - 1; if (*chptr == '\n') *chptr = '\0'; else chptr++; /* strip leading spaces */ start = buf; while (*start && isspace(*start)) start++; /* empty string */ if (!*start) continue; /* comment */ if (*start == '#') continue; if (!inComp) { /* first digit must be a zero or a one */ if (*start != '0' && *start != '1') { newtWinMessage(_("Error"), _("Ok"), _("bad comps file at line %d"), line); continue; } if (compsAlloced == cs.numComponents) { compsAlloced += 5; cs.comps = realloc(cs.comps, sizeof(*cs.comps) * compsAlloced); } currcomp = cs.comps + cs.numComponents; currcomp->selected = (*start == '1'); currcomp->inmenu = 1; start++; while (*start && isspace(*start)) start++; if (!strncmp(start, "--hide ", 7)) { start += 7; while (*start && isspace(*start)) start++; currcomp->inmenu = 0; } if (!*start) { newtWinMessage(_("comps Error"), _("Ok"), _("missing component name at line %d"), line); continue; } currcomp->name = strdup(start); currcomp->ps.numPackages = 0; packagesAlloced = 5; currcomp->ps.packages = malloc( sizeof(struct packageInfo) * packagesAlloced); inComp = 1; } else { if (!strcmp(start, "end")) { inComp = 0; if (!strcasecmp(currcomp->name, "Base")) baseNum = cs.numComponents; cs.numComponents++; } else { packkey.name = start; pack = bsearch(&keyaddr, psp->packages, psp->numPackages, sizeof(*psp->packages), (void *) pkgCompare); if (!pack) { newtWinMessage(_("comps Error"), _("Ok"), _("package %s at line %d does not exist"), start, line); continue; } if (currcomp->ps.numPackages == packagesAlloced) { packagesAlloced += 5; currcomp->ps.packages = realloc(currcomp->ps.packages, sizeof(struct packageInfo) * packagesAlloced); } currcomp->ps.packages[currcomp->ps.numPackages] = *pack; currcomp->ps.numPackages++; } } } fclose(f); cs.base = cs.comps + baseNum; cs.base->inmenu = 0; cs.base->selected = 1; for (i = 0; i < cs.base->ps.numPackages; i++) { cs.base->ps.packages[i]->inmenu = 0; cs.base->ps.packages[i]->selected = 1; } *csp = cs; return 0; } struct packageCheckbox { newtComponent cb, sizeLabel; unsigned int * kSelected; unsigned int size; char state, lastState; }; static void sizeCallback(newtComponent co, struct packageCheckbox * cbi) { char sizeBuf[20]; if (cbi->state != cbi->lastState) { if (cbi->state == ' ') *cbi->kSelected -= cbi->size / 1024; else *cbi->kSelected += cbi->size / 1024; cbi->lastState = cbi->state; sprintf(sizeBuf, "%dM", *cbi->kSelected / 1024); newtLabelSetText(cbi->sizeLabel, sizeBuf); newtRefresh(); } } static int selectPackagesWindow(struct pkgSet * psp, char * group, unsigned int * kSelected) { newtComponent okay, form, checkList, sb, cancel, current, size, blank; struct packageCheckbox * cbs; int i, row, groupLength, rc; char val; struct newtExitStruct answer; int done = 0; char sizeBuf[20]; int exactMatch; newtGrid grid, buttons, subgrid, checkgrid; if (!group) { group = ""; groupLength = 0; } else groupLength = strlen(group); exactMatch = strchr(group, '/') ? 0 : 1; cbs = alloca(sizeof(*cbs) * psp->numPackages); newtPushHelpLine( _(" will show you a size and description of a package")); buttons = newtButtonBar(_("Ok"), &okay, _("Cancel"), &cancel, NULL); subgrid = newtCreateGrid(2, 1); sprintf(sizeBuf, "%dM", *kSelected / 1024); size = newtLabel(32, 10, sizeBuf); newtGridSetField(subgrid, 0, 0, NEWT_GRID_COMPONENT, newtLabel(-1, -1, _("Size of all selected packages:")), 0, 0, 0, 0, 0, 0); newtGridSetField(subgrid, 1, 0, NEWT_GRID_COMPONENT, size, 1, 0, 0, 0, 0, 0); sb = newtVerticalScrollbar(29, 0, 6, 9, 10); checkList = newtForm(sb, NULL, 0); newtFormSetBackground(checkList, NEWT_COLORSET_CHECKBOX); for (i = 0, row = 0; i < psp->numPackages; i++) { if (psp->packages[i]->inmenu && ((exactMatch && !strcmp(psp->packages[i]->group, group)) || (!exactMatch && strlen(psp->packages[i]->group) >= groupLength && !strncmp(psp->packages[i]->group, group, groupLength)))) { if (psp->packages[i]->selected) val = '*'; else val = ' '; cbs[i].cb = newtCheckbox(1, row++, psp->packages[i]->name, val, NULL, &cbs[i].state); newtComponentAddCallback(cbs[i].cb, (void *) sizeCallback, cbs + i); cbs[i].sizeLabel = size; cbs[i].lastState = cbs[i].state = val; cbs[i].size = psp->packages[i]->size; cbs[i].kSelected = kSelected; newtFormAddComponent(checkList, cbs[i].cb); } else { cbs[i].state = ' '; cbs[i].cb = NULL; } } checkgrid = newtCreateGrid(3, 1); newtGridSetField(checkgrid, 0, 0, NEWT_GRID_COMPONENT, checkList, 0, 0, 0, 0, 0, 0); if (row > 6) { blank = newtForm(NULL, NULL, 0); newtFormSetWidth(blank, 2); newtFormSetHeight(blank, 6); newtFormSetBackground(blank, NEWT_COLORSET_CHECKBOX); newtFormSetHeight(checkList, 6); newtGridSetField(checkgrid, 1, 0, NEWT_GRID_COMPONENT, blank, 0, 0, 0, 0, 0, 0); newtGridSetField(checkgrid, 2, 0, NEWT_GRID_COMPONENT, sb, 0, 0, 0, 0, 0, 0); } grid = newtCreateGrid(1, 4); newtGridSetField(grid, 0, 0, NEWT_GRID_COMPONENT, newtLabel(-1, -1, _("What packages should be installed?")), 0, 0, 0, 0, NEWT_ANCHOR_LEFT, 0); newtGridSetField(grid, 0, 1, NEWT_GRID_SUBGRID, checkgrid, 0, 1, 0, 0, 0, 0); newtGridSetField(grid, 0, 2, NEWT_GRID_SUBGRID, subgrid, 0, 1, 0, 0, NEWT_ANCHOR_LEFT, 0); newtGridSetField(grid, 0, 3, NEWT_GRID_SUBGRID, buttons, 0, 1, 0, 0, 0, NEWT_GRID_FLAG_GROWX); form = newtForm(NULL, NULL, 0); newtGridAddComponentsToForm(grid, form, 1); newtGridWrappedWindow(grid, _("Select Packages")); newtGridFree(grid, 1); newtFormAddHotKey(form, NEWT_KEY_F1); rc = 0; while (!done) { newtFormRun(form, &answer); if (answer.reason == NEWT_EXIT_HOTKEY) { if (answer.u.key == NEWT_KEY_F12) done = 1; else if (answer.u.key == NEWT_KEY_F1) { current = newtFormGetCurrent(checkList); for (i = 0; i < psp->numPackages; i++) { if (cbs[i].cb == current) { showPackageInfo(psp->packages[i]->h); break; } } } } else if (answer.reason == NEWT_EXIT_COMPONENT) { done = 1; if (answer.u.co == cancel) rc = INST_CANCEL; } } newtFormDestroy(form); newtPopWindow(); newtPopHelpLine(); if (rc) return rc; for (i = 0; i < psp->numPackages; i++) if (cbs[i].cb) if (cbs[i].state != ' ') psp->packages[i]->selected = 1; else psp->packages[i]->selected = 0; return 0; } #define SELECT_COMPONENTS 1 #define SELECT_PACKAGES 2 #define SELECT_VERIFY 3 #define SELECT_DONE 100 int psSelectPackages(struct pkgSet * psp, struct componentSet * csp, char * justComponent, int goForward, int isUpgrade) { int rc; int stage; static int doIndividual = 0; struct ksPackage * ksList; int ksListLength; int i, j, k; struct packageInfo key; struct packageInfo ** pack, * keyaddr = &key; if (justComponent) { /* first off, turn on the base packages */ for (k = 0; k < csp->base->ps.numPackages; k++) csp->base->ps.packages[k]->selected = 1; csp->base->selected = 1; for (j = 0; j < csp->numComponents; j++) if (!strcasecmp(justComponent, csp->comps[j].name)) break; if (j < csp->numComponents) { for (k = 0; k < csp->comps[j].ps.numPackages; k++) csp->comps[j].ps.packages[k]->selected = 1; return 0; } } if (kickstart) { ksGetPackageList(&ksList, &ksListLength); /*cjs added code cjs */ if (ksListLength) { /* first off, turn on the base packages */ for (k = 0; k < csp->base->ps.numPackages; k++) csp->base->ps.packages[k]->selected = 1; csp->base->selected = 1; for (i = 0; i < ksListLength; i++) { if (ksList[i].isComponent) { for (j = 0; j < csp->numComponents; j++) if (!strcasecmp(ksList[i].name, csp->comps[j].name)) break; if (j == csp->numComponents) { newtWinMessage(_("Kickstart Error"), _("Ok"), _("Component %s does not exist.\n"), ksList[i].name); } else { for (k = 0; k < csp->comps[j].ps.numPackages; k++) csp->comps[j].ps.packages[k]->selected = 1; } } else { key.name = ksList[i].name; pack = bsearch(&keyaddr, psp->packages, psp->numPackages, sizeof(*psp->packages), (void *) pkgCompare); if (!pack) { newtWinMessage(_("Kickstart Error"), _("Ok"), _("Package %s does not exist.\n"), key.name); } else { (*pack)->selected = 1; } } } rc = psVerifyDependencies(psp, 1); return 0; } else stage = SELECT_COMPONENTS; } else { if (!goForward && doIndividual) stage = SELECT_PACKAGES; else stage = SELECT_COMPONENTS; } while (stage != SELECT_DONE) { switch (stage) { case SELECT_COMPONENTS: if (isUpgrade) rc = queryIndividual(&doIndividual); else rc = selectComponents(csp, psp, &doIndividual); if (rc) return rc; if (doIndividual) stage = SELECT_PACKAGES; else stage = SELECT_VERIFY; break; case SELECT_PACKAGES: rc = selectPackagesByGroup(psp); if (rc == INST_CANCEL) stage = SELECT_COMPONENTS; else if (rc) return rc; else stage = SELECT_VERIFY; break; case SELECT_VERIFY: rc = psVerifyDependencies(psp, 0); if (rc == INST_ERROR) return rc; else if (rc) stage = SELECT_PACKAGES; else stage = SELECT_DONE; } } return 0; } int psVerifyDependencies(struct pkgSet * psp, int fixup) { rpmdb db = NULL; rpmDependencies rpmdeps; int i; struct rpmDependencyConflict * conflicts; struct packageInfo * package; int numConflicts, numProblems; newtComponent okay, form, textbox, info, cancel, answer; newtGrid grid, buttons; char * text, buf[80]; char selectPackages; char * reflowedText; int width, height; if (!access("/mnt/var/lib/rpm/packages.rpm", R_OK)) if (rpmdbOpen("/mnt", &db, O_RDWR | O_CREAT, 0644)) db = NULL; rpmdeps = rpmdepDependencies(db); for (i = 0; i < psp->numPackages; i++) { if (psp->packages[i]->selected) rpmdepAddPackage(rpmdeps, psp->packages[i]->h, psp->packages[i]); else rpmdepAvailablePackage(rpmdeps, psp->packages[i]->h, psp->packages[i]); } rpmdepCheck(rpmdeps, &conflicts, &numConflicts); rpmdepDone(rpmdeps); if (db) rpmdbClose(db); /* XXX This is a hack. rpmlib seems to have problems in the conflicts stuff */ numProblems = 0; for (i = 0; i < numConflicts; i++) { if (conflicts[i].sense == RPMDEP_SENSE_REQUIRES) numProblems++; } if (!numProblems) { return 0; } if (fixup) { for (i = 0; i < numConflicts; i++) { package = conflicts[i].suggestedPackage; if (package) package->selected = 1; } rpmdepFreeConflicts(conflicts, numConflicts); return 0; } text = malloc(80 * numConflicts); *text = '\0'; for (i = 0; i < numConflicts; i++) { /* HACK XXX */ if (conflicts[i].sense == RPMDEP_SENSE_CONFLICTS) continue; package = conflicts[i].suggestedPackage; if (package) sprintf(buf, "%-20s %-20s", conflicts[i].byName, package->name); else sprintf(buf, "%-20s %s", conflicts[i].byName, _("no suggestion")); if (i) strcat(text, "\n"); strcat(text, buf); } if (!kickstart) { form = newtForm(NULL, NULL, 0); reflowedText = newtReflowText( _("Some of the packages you have selected to install require " "packages you have not selected. If you just select Ok " "all of those required packages will be installed."), 45, 5, 5, &width, &height); info = newtTextbox(1, 1, width, height, NEWT_TEXTBOX_WRAP); newtTextboxSetText(info, reflowedText); free(reflowedText); sprintf(buf, "%-20s %-20s", _("Package"), _("Requirement")); buttons = newtButtonBar(_("Ok"), &okay, _("Back"), &cancel, NULL); textbox = newtTextbox(-1, -1, 45, 5, numProblems > 5 ? NEWT_FLAG_SCROLL : 0); newtTextboxSetText(textbox, text); grid = newtCreateGrid(1, 5); newtGridSetField(grid, 0, 0, NEWT_GRID_COMPONENT, info, 0, 0, 0, 0, 0, 0); newtGridSetField(grid, 0, 1, NEWT_GRID_COMPONENT, newtLabel(-1, -1, buf), 0, 1, 0, 0, NEWT_ANCHOR_LEFT, 0); newtGridSetField(grid, 0, 2, NEWT_GRID_COMPONENT, textbox, 0, 0, 0, 0, 0, 0); newtGridSetField(grid, 0, 3, NEWT_GRID_COMPONENT, newtCheckbox(-1, -1, _("Install packages to " "satisfy dependencies"), '*', NULL, &selectPackages), 0, 1, 0, 0, 0, 0); newtGridSetField(grid, 0, 4, NEWT_GRID_SUBGRID, buttons, 0, 1, 0, 0, 0, NEWT_GRID_FLAG_GROWX); newtGridAddComponentsToForm(grid, form, 1); newtFormSetCurrent(form, okay); newtGridWrappedWindow(grid, _("Unresolved Dependencies")); newtGridFree(grid, 1); answer = newtRunForm(form); newtFormDestroy(form); newtPopWindow(); if (answer == cancel) { free(conflicts); return INST_CANCEL; } } if (kickstart || selectPackages != ' ') { for (i = 0; i < numConflicts; i++) { package = conflicts[i].suggestedPackage; if (package) package->selected = 1; } } free(conflicts); return 0; } ; static int selectComponents(struct componentSet * csp, struct pkgSet * psp, int * doIndividual) { int i, j; newtComponent okay, form, checklist, checkbox, sb, cancel, answer, blank; newtGrid buttons, checkgrid, grid; char val, individualPackages, everything = ' '; char * states; int row; int numCols, numRows; newtGetScreenSize(&numCols, &numRows); individualPackages = *doIndividual ? '*' : ' '; states = alloca(sizeof(*states) * csp->numComponents); form = newtForm(NULL, NULL, 0); sb = newtVerticalScrollbar(-1, -1, numRows - 18, 9, 10); checklist = newtForm(sb, NULL, 0); newtFormSetHeight(checklist, numRows - 18); newtFormSetBackground(checklist, NEWT_COLORSET_CHECKBOX); for (i = 0, row = 0; i < csp->numComponents; i++) { if (csp->comps[i].inmenu) { if (csp->comps[i].selected) val = '*'; else val = ' '; checkbox = newtCheckbox(0, row++, csp->comps[i].name, val, NULL, &states[i]); newtFormAddComponent(checklist, checkbox); } else states[i] = ' '; } /* cjs checkbox = newtCheckbox(0, row++, _("Everything"), ' ', NULL, &everything); newtFormAddComponent(checklist, checkbox); cjs */ blank = newtForm(NULL, NULL, 0); newtFormSetHeight(blank, numRows - 18); newtFormSetWidth(blank, 2); newtFormSetBackground(blank, NEWT_COLORSET_CHECKBOX); checkgrid = newtGridHCloseStacked(NEWT_GRID_COMPONENT, checklist, NEWT_GRID_COMPONENT, blank, NEWT_GRID_COMPONENT, sb, NULL); checkbox = newtCheckbox(-1, -1, _("Select individual packages"), individualPackages, NULL, &individualPackages); buttons = newtButtonBar(_("Ok"), &okay, _("Back"), &cancel, NULL); grid = newtGridBasicWindow(newtLabel(-1, -1, _("Choose components to install:")), newtGridVStacked(NEWT_GRID_SUBGRID, checkgrid, NEWT_GRID_COMPONENT, checkbox, NULL), buttons); newtGridAddComponentsToForm(grid, form, 1); newtGridWrappedWindow(grid, _("Components to Install")); newtGridFree(grid, 1); answer = newtRunForm(form); newtFormDestroy(form); newtPopWindow(); if (answer == cancel) return INST_CANCEL; *doIndividual = (individualPackages != ' '); if (everything != ' ') { for (i = 0; i < psp->numPackages; i++) { for (j = 0; skipList[j]; j++) { if (!strcmp(psp->packages[i]->name, skipList[j])) break; } if (!skipList[j]) { psp->packages[i]->selected = 1; } } } for (i = 0; i < csp->numComponents; i++) { if (csp->comps[i].inmenu) { if (states[i] != ' ') csp->comps[i].selected = 1; else csp->comps[i].selected = 0; for (j = 0; j < csp->comps[i].ps.numPackages; j++) csp->comps[i].ps.packages[j]->selected |= csp->comps[i].selected; } } return 0; } void psFreeComponentSet(struct componentSet * csp) { int i; struct component * currcomp; currcomp = csp->comps; for (i = 0; i < csp->numComponents; i++, currcomp++) { free(currcomp->ps.packages); } free(csp->comps); } int psFromHeaderListDesc(int fd, struct pkgSet * psp, int noSeek) { struct pkgSet ps; int end = 0, type, count; unsigned int * sizeptr; Header h; int packagesAlloced; char * name, * group; int done = 0; ps.numPackages = 0; packagesAlloced = 5; ps.packages = malloc(sizeof(*ps.packages) * packagesAlloced); if (!noSeek) { count = lseek(fd, 0, SEEK_CUR); end = lseek(fd, 0, SEEK_END); lseek(fd, count, SEEK_SET); } while (!done) { h = headerRead(fd, HEADER_MAGIC_YES); if (!h && noSeek) { done = 1; } else if (!h) { newtWinMessage(_("Error"), _("Ok"), "error reading header at %d\n", (int) lseek(fd, 0, SEEK_CUR)); free(ps.packages); return INST_ERROR; } else { headerGetEntry(h, RPMTAG_NAME, &type, (void **) &name, &count); if (!headerGetEntry(h, RPMTAG_GROUP, &type, (void **) &group, &count)) { group = "(unknown group)"; } else if (!strlen(group)) group = "(unknown group)"; if (ps.numPackages == packagesAlloced) { packagesAlloced += 5; ps.packages = realloc(ps.packages, sizeof(*ps.packages) * packagesAlloced); } ps.packages[ps.numPackages] = malloc(sizeof(struct packageInfo)); ps.packages[ps.numPackages]->h = h; ps.packages[ps.numPackages]->selected = 0; if (headerGetEntry(h, RPMTAG_SIZE, &type, (void **) &sizeptr, &count)) ps.packages[ps.numPackages]->size = *sizeptr; else ps.packages[ps.numPackages]->size = 0; if (skipPackage(name)) ps.packages[ps.numPackages]->inmenu = 0; else ps.packages[ps.numPackages]->inmenu = 1; ps.packages[ps.numPackages]->name = name; ps.packages[ps.numPackages]->group = group; headerGetEntry(h, FILENAME_TAG, &type, (void **) &ps.packages[ps.numPackages]->data, &count); ps.numPackages++; } if (!noSeek) { if (end <= lseek(fd, 0, SEEK_CUR)) done = 1; } } logMessage("psFromHeaderListDesc read %d headers", ps.numPackages); *psp = ps; qsort(ps.packages, ps.numPackages, sizeof(*ps.packages), (void *) pkgCompare); return 0; } int psFromHeaderListFile(char * file, struct pkgSet * psp) { int fd, rc; fd = open(file, O_RDONLY, 0644); if (fd < 0) { errorWindow(_("error opening header file: %s")); return INST_ERROR; } rc = psFromHeaderListDesc(fd, psp, 0); close(fd); return rc; } static int skipPackage(char * name) { char ** item; for (item = skipList; *item; item++) { if (!strcmp(*item, name)) return 1; } return 0; } static int selectPackagesByGroup(struct pkgSet * psp) { newtComponent done, edit, form, listbox, back, answer; newtComponent sizeLabel; int i, row, numGroups; unsigned int kSelected = 0; int rc = 0; hashTable ht; htIterator iter; char buf[200], * chptr; char * group; char ** groupList; newtGrid grid, subgrid, sizegrid, buttons; ht = htNewTable(psp->numPackages); for (i = 0, row = 0; i < psp->numPackages; i++) { if (psp->packages[i]->inmenu) { group = psp->packages[i]->group; chptr = group; while (*chptr && *chptr != '/') chptr++; if (*chptr == '/') { chptr++; while (*chptr && *chptr != '/') chptr++; if (*chptr == '/') { strncpy(buf, group, chptr - group); buf[chptr - group] = '\0'; group = buf; } } } htAddToTable(ht, group); if (psp->packages[i]->selected) kSelected += (psp->packages[i]->size / 1024); } numGroups = htNumEntries(ht); groupList = alloca(sizeof(*groupList) * numGroups); htIterStart(&iter); i = 0; while (htIterGetNext(ht, &iter, &group)) { groupList[i] = alloca(strlen(group) + 1); strcpy(groupList[i], group); i++; } qsort(groupList, numGroups, sizeof(char *), strptrCmp); htFreeHashTable(ht); form = newtForm(NULL, NULL, 0); buttons = newtButtonBar(_("Done"), &done, _("Edit"), &edit, _("Back"), &back, NULL); sprintf(buf, "%dM", kSelected / 1024); while (strlen(buf) < 5) strcat(buf, " "); sizeLabel = newtLabel(-1, -1, buf); /* FIXME: this windo isn't quite right -- looks like some newt bugs */ sizegrid = newtCreateGrid(2, 1); newtGridSetField(sizegrid, 0, 0, NEWT_GRID_COMPONENT, newtLabel(-1, -1, _("Size:")), 0, 0, 0, 0, NEWT_ANCHOR_LEFT, 0); newtGridSetField(sizegrid, 1, 0, NEWT_GRID_COMPONENT, sizeLabel, 1, 0, 0, 0, NEWT_ANCHOR_LEFT, 0); subgrid = newtCreateGrid(2, 1); newtGridSetField(subgrid, 0, 0, NEWT_GRID_COMPONENT, newtLabel(-1, -1, _("Choose a group to examine:")), 0, 0, 0, 0, NEWT_ANCHOR_LEFT, 0); newtGridSetField(subgrid, 1, 0, NEWT_GRID_SUBGRID, sizegrid, 5, 0, 0, 0, NEWT_ANCHOR_LEFT, 0); listbox = newtListbox(3, 3, 6, NEWT_FLAG_RETURNEXIT | NEWT_FLAG_SCROLL); for (i = 0; i < numGroups; i++) newtListboxAddEntry(listbox, groupList[i], groupList[i]); grid = newtCreateGrid(1, 3); newtGridSetField(grid, 0, 0, NEWT_GRID_SUBGRID, subgrid, 0, 0, 0, 0, 0, 0); newtGridSetField(grid, 0, 1, NEWT_GRID_COMPONENT, listbox, 0, 1, 0, 0, 0, 0); newtGridSetField(grid, 0, 2, NEWT_GRID_SUBGRID, buttons, 0, 1, 0, 0, 0, NEWT_GRID_FLAG_GROWX); newtGridAddComponentsToForm(grid, form, 1); newtGridWrappedWindowAt(grid, _("Select Group"), 1, 2); newtGridFree(grid, 1); do { answer = newtRunForm(form); if ((answer == listbox) || (answer == edit)) { group = newtListboxGetCurrent(listbox); rc = selectPackagesWindow(psp, group, &kSelected); sprintf(buf, "%dM", kSelected / 1024); newtLabelSetText(sizeLabel, buf); } } while (((answer == listbox) || (answer == edit)) && rc != INST_ERROR); newtFormDestroy(form); newtPopWindow(); if (rc == INST_ERROR) return rc; if (answer == back) return INST_CANCEL; return 0; } static void showPackageInfo(Header h) { newtComponent form, textbox, okay; newtGrid subgrid, grid; char * name, * version, * description, * release; uint_32 * size; int type, count; char infostr[255]; char * buf, * from, * to; headerGetEntry(h, RPMTAG_NAME, &type, (void **) &name, &count); headerGetEntry(h, RPMTAG_VERSION, &type, (void **) &version, &count); headerGetEntry(h, RPMTAG_RELEASE, &type, (void **) &release, &count); if (!headerGetEntry(h, RPMTAG_SIZE, &type, (void **) &size, &count)) size = 0; if (!headerGetEntry(h, RPMTAG_DESCRIPTION, &type, (void **) &description, &count)) { if (!headerGetEntry(h, RPMTAG_SUMMARY, &type, (void **) &description, &count)) { description = _("(none available)"); } } subgrid = newtCreateGrid(2, 2); newtGridSetField(subgrid, 0, 0, NEWT_GRID_COMPONENT, newtLabel(-1, 1, _("Package:")), 0, 0, 0, 0, NEWT_ANCHOR_LEFT, 0); newtGridSetField(subgrid, 0, 1, NEWT_GRID_COMPONENT, newtLabel(-1, -1, _("Size :")), 0, 0, 0, 0, NEWT_ANCHOR_LEFT, 0); sprintf(infostr, "%s-%s-%s", name, version, release); newtGridSetField(subgrid, 1, 0, NEWT_GRID_COMPONENT, newtLabel(-1, -1, infostr), 1, 0, 0, 0, NEWT_ANCHOR_LEFT, 0); sprintf(infostr, "%d", *size); newtGridSetField(subgrid, 1, 1, NEWT_GRID_COMPONENT, newtLabel(-1, -1, infostr), 1, 0, 0, 0, NEWT_ANCHOR_LEFT, 0); to = buf = alloca(strlen(description) + 1); from = description; /* Rip out all '\n' that don't start new paragraphs */ while (*from) { if (*from == '\n') { if ((*(from + 1) && isspace(*(from + 1))) || (from > description && *(from - 1) == '\n')) *to++ = '\n'; else *to++ = ' '; } else *to++ = *from; from++; } *to = '\0'; textbox = newtTextbox(-1, -1, 43, 6, NEWT_TEXTBOX_WRAP | NEWT_TEXTBOX_SCROLL); newtTextboxSetText(textbox, buf); okay = newtButton(20, 11, _("Ok")); grid = newtCreateGrid(1, 3); newtGridSetField(grid, 0, 0, NEWT_GRID_SUBGRID, subgrid, 0, 0, 0, 0, NEWT_ANCHOR_LEFT, 0); newtGridSetField(grid, 0, 1, NEWT_GRID_COMPONENT, textbox, 0, 1, 0, 0, NEWT_ANCHOR_LEFT, 0); newtGridSetField(grid, 0, 2, NEWT_GRID_COMPONENT, okay, 0, 1, 0, 0, 0, 0); form = newtForm(NULL, NULL, 0); newtGridAddComponentsToForm(grid, form, 1); newtGridWrappedWindowAt(grid, name, 31, 6); newtGridFree(grid, 1); newtRunForm(form); newtFormDestroy(form); newtPopWindow(); } static int queryIndividual(int * result) { int rc = 0; *result = 0; rc = newtWinTernary(_("Upgrade Packages"), _("Yes"), _("No"), _("Back"), _("The packages you have installed, and any other packages which are " "needed to satisfy their dependencies, have been selected for " "installation. Would you like to customize the set of packages that " "will be upgraded?")); if (rc == 3) rc = INST_CANCEL; else if (rc == 2) { *result = 0; rc = 0; } else { *result = 1; rc = 0; } return rc; }