home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 1998 February
/
CHIP_2_98.iso
/
misc
/
src
/
install
/
pkgs.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-11-09
|
26KB
|
1,044 lines
#include <alloca.h>
#include <ctype.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <newt.h>
#include <rpmlib.h>
#include <header.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include "hash.h"
#include "install.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, unsigned int * kSelected);
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")) {
newtWinMessage("Error", "Ok", "Comps file is not version 0 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 (!*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;
struct packageCheckbox * cbs;
int i, row, groupLength, rc;
char val;
struct newtExitStruct answer;
int done = 0;
char sizeBuf[20];
int exactMatch;
if (!group) {
group = "";
groupLength = 0;
} else
groupLength = strlen(group);
exactMatch = strchr(group, '/') ? 0 : 1;
cbs = alloca(sizeof(*cbs) * psp->numPackages);
newtOpenWindow(22, 4, 40, 16, "Select Packages");
newtPushHelpLine("<F1> will show you a size and description of a package");
form = newtForm(NULL, NULL, 0);
okay = newtButton(6, 12, "Ok");
cancel = newtButton(21, 12, "Cancel");
newtFormAddComponent(form, newtLabel(1, 1,
"What packages should be installed?"));
newtFormAddComponent(form, newtLabel(1, 10,
"Size of all selected packages:"));
sprintf(sizeBuf, "%dM", *kSelected / 1024);
size = newtLabel(32, 10, sizeBuf);
newtFormAddComponent(form, size);
sb = newtVerticalScrollbar(32, 3, 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(6, 3 + 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;
}
}
if (row > 6) {
newtFormSetHeight(checkList, 6);
newtFormAddComponent(checkList, sb);
} else
newtFormSetWidth(checkList, 27);
newtFormAddComponents(form, checkList, okay, cancel, NULL);
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, kSelected);
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,
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 (kickstart) {
ksGetPackageList(&ksList, &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 {
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;
newtComponent okay, form, textbox, info, cancel, answer;
char * text, buf[80];
char selectPackages;
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);
if (!numConflicts) {
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++) {
package = conflicts[i].suggestedPackage;
if (package)
sprintf(buf, "%-20s %-20s", conflicts[i].byName,
package->name);
else
sprintf(buf, "%-20s (no suggestion)", conflicts[i].byName);
if (i) strcat(text, "\n");
strcat(text, buf);
}
if (!kickstart) {
newtCenteredWindow(50, 19, "Unresolved Dependencies");
form = newtForm(NULL, NULL, 0);
info = newtTextbox(1, 1, 45, 4, NEWT_TEXTBOX_WRAP);
newtTextboxSetText(info,
"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.");
sprintf(buf, "%-20s %-20s", "Package", "Requirement");
okay = newtButton(10, 15, "Ok");
cancel = newtButton(30, 15, "Cancel");
newtFormAddComponent(form, newtLabel(3, 6, buf));
textbox = newtTextbox(3, 7, 45, 5, NEWT_TEXTBOX_SCROLL);
newtTextboxSetText(textbox, text);
newtFormAddComponent(form,
newtCheckbox(3, 13, "Install packages to satisfy dependencies", '*',
NULL, &selectPackages));
newtFormAddComponents(form, info, textbox, okay, cancel, NULL);
newtFormSetCurrent(form, okay);
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;
char val, individualPackages, everything;
char * states;
int row;
individualPackages = *doIndividual ? '*' : ' ';
states = alloca(sizeof(*states) * csp->numComponents);
newtCenteredWindow(50, 19, "Components to Install");
form = newtForm(NULL, NULL, 0);
newtFormAddComponent(form, newtLabel(1, 1,
"Choose components to install:"));
/*newtFormAddComponent(form, newtLabel(36, 1, "Size:"));
size = newtLabel(1, 42,*/
sb = newtVerticalScrollbar(47, 3, 9, 9, 10);
checklist = newtForm(sb, NULL, 0);
newtFormSetHeight(checklist, 9);
newtFormSetBackground(checklist, NEWT_COLORSET_CHECKBOX);
newtFormAddComponent(checklist, sb);
for (i = 0, row = 0; i < csp->numComponents; i++) {
if (csp->comps[i].inmenu) {
if (csp->comps[i].selected)
val = '*';
else
val = ' ';
checkbox = newtCheckbox(6, 3 + row++, csp->comps[i].name, val,
NULL, &states[i]);
newtFormAddComponent(checklist, checkbox);
} else
states[i] = ' ';
}
checkbox = newtCheckbox(6, 3 + row++, "Everything", ' ',
NULL, &everything);
newtFormAddComponent(checklist, checkbox);
checkbox = newtCheckbox(10, 13, "Select individual packages",
individualPackages, NULL, &individualPackages);
okay = newtButton(10, 15, "Ok");
cancel = newtButton(30, 15, "Cancel");
newtFormAddComponents(form, checklist, checkbox, okay, cancel, NULL);
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 okay, form, listbox, cancel, 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;
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);
newtOpenWindow(4, 2, 45, 14, "Select Group");
form = newtForm(NULL, NULL, 0);
okay = newtButton(7, 10, "Ok");
cancel = newtButton(23, 10, "Cancel");
newtFormAddComponent(form, newtLabel(1, 1,
"Choose a group to examine:"));
newtFormAddComponent(form, newtLabel(33, 1,
"Size:"));
sprintf(buf, "%dM", kSelected / 1024);
sizeLabel = newtLabel(39, 1, buf);
newtFormAddComponent(form, sizeLabel);
listbox = newtListbox(3, 3, 6, NEWT_LISTBOX_RETURNEXIT);
for (i = 0; i < numGroups; i++) {
newtListboxAddEntry(listbox, groupList[i], groupList[i]);
}
newtFormAddComponents(form, listbox, okay, cancel, NULL);
do {
answer = newtRunForm(form);
if (answer == listbox) {
group = newtListboxGetCurrent(listbox);
rc = selectPackagesWindow(psp, group, &kSelected);
sprintf(buf, "%dM", kSelected / 1024);
newtLabelSetText(sizeLabel, buf);
}
} while (answer == listbox && rc != INST_ERROR);
newtFormDestroy(form);
newtPopWindow();
if (rc == INST_ERROR) return rc;
if (answer == cancel) return INST_CANCEL;
return 0;
}
static void showPackageInfo(Header h, unsigned int * kSelected) {
newtComponent form, textbox, okay;
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)";
}
}
newtOpenWindow(31, 6, 45, 15, name);
form = newtForm(NULL, NULL, 0);
newtFormAddComponent(form, newtLabel(1, 1, "Package:"));
newtFormAddComponent(form, newtLabel(1, 2, "Size :"));
sprintf(infostr, "%s-%s-%s", name, version, release);
newtFormAddComponent(form, newtLabel(10, 1, infostr));
sprintf(infostr, "%d", *size);
newtFormAddComponent(form, newtLabel(10, 2, infostr));
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, 4, 43, 6, NEWT_TEXTBOX_WRAP |
NEWT_TEXTBOX_SCROLL);
newtTextboxSetText(textbox, buf);
okay = newtButton(20, 11, "Ok");
newtFormAddComponents(form, textbox, okay, NULL);
newtRunForm(form);
newtFormDestroy(form);
newtPopWindow();
}
static int queryIndividual(int * result) {
int rc = 0;
*result = 0;
rc = newtWinTernary("Upgrade Packages", "Yes", "No", "Cancel",
"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;
}