Browse Source

partialy port to libdebian-installer 4, unfinished, unbuildable

r4547
keep-around/c8703c509368e1805e513d61f98a9d17d2cdd9cc
Bastian Blank 19 years ago
parent
commit
9aeccd5af3
  1. 226
      main-menu.c
  2. 5
      main-menu.h

226
main-menu.c

@ -36,35 +36,30 @@ int default_priority = 1;
/* Save priority set by main-menu to detect priority changes from the user */
int local_priority = -1;
static int check_script(struct package_t *p, char *scriptname);
static struct linkedlist_t *packages;
#ifdef DODEBUG
static int do_system(const char *cmd) {
DPRINTF("cmd is %s\n", cmd);
return system(cmd);
}
#endif
static struct debconfclient *debconf;
/*
* qsort comparison function (sort by menu item values, fall back to
* lexical sort to resolve ties deterministically).
*/
int compare (const void *a, const void *b) {
/* Sometimes, I wish I was writing perl. */
int r=(*(struct package_t **)a)->installer_menu_item -
(*(struct package_t **)b)->installer_menu_item;
int package_array_compare (const void *v1, const void *v2) {
di_system_package *p1, *p2;
p1 = *(di_system_package **)v1;
p2 = *(di_system_package **)v2;
int r = p1->installer_menu_item - p2->installer_menu_item;
if (r) return r;
return strcmp((*(struct package_t **)b)->package,
(*(struct package_t **)a)->package);
return strcmp(p1->p.package, p2->p.package);
}
int isdefault(struct package_t *p) {
int isdefault(di_package *p) {
int check;
check = check_script(p, "menutest");
if (check == 1 || p->status == unpacked || p->status == half_configured) {
check = di_system_dpkg_package_control_file_exec(p, "menutest", 0, NULL);
if (!check || p->status == di_package_status_unpacked || p->status == di_package_status_half_configured) {
return 1;
}
else {
@ -72,47 +67,18 @@ int isdefault(struct package_t *p) {
}
}
/* Calls a control skript and passes its exit status
* Returns :
* 0 if selected script returns false or something goes wrong
* 1 if selected script return true
* -1 if selected script is not present
*/
static int check_script(struct package_t *p, char *scriptname) {
char *script, *cmd;
struct stat statbuf;
int ret;
if (asprintf(&script, DPKGDIR "info/%s.%s", p->package, scriptname) == -1) {
return 0;
}
if (stat(script, &statbuf) == 0) {
if (asprintf(&cmd, "exec %s >/dev/null 2>&1", script) == -1) {
return 0;
}
ret = !SYSTEM(cmd);
free(cmd);
}
else {
ret = -1;
}
free(script);
return ret;
}
/* Expects a topologically ordered linked list of packages. */
static struct package_t *
get_default_menu_item(struct linkedlist_t *list)
static di_package *
get_default_menu_item(di_slist *list)
{
struct package_t *p, *q;
struct list_node *node;
int i, cont;
di_package *p;
di_slist_node *node, *node1;
int cont;
/* Traverse the list, return the first menu item that isn't installed */
for (node = list->head; node != NULL; node = node->next) {
p = (struct package_t *)node->data;
if (!p->installer_menu_item || p->status == installed || !check_script(p, "isinstallable"))
p = node->data;
if (!((di_system_package *)p)->installer_menu_item || p->status == di_package_status_installed || !di_system_dpkg_package_control_file_exec(p, "isinstallable", 0, NULL))
continue;
/* If menutest says this item should be default, make it so */
if (!isdefault(p))
@ -121,9 +87,9 @@ get_default_menu_item(struct linkedlist_t *list)
/* Check if a "parallel" package is installed
* (netcfg-{static,dhcp} and {lilo,grub}-installer are
* examples of parallel packages */
for (i = 0; p->provides[i] != NULL; i++) {
q = p->provides[i]->ptr;
if (q != NULL && di_pkg_is_installed(q)) {
for (node1 = p->depends.head; node1; node1 = node1->next) {
di_package_dependency *d = node->data;
if (d->type == di_package_dependency_type_provides && d->ptr->status == di_package_status_installed) {
cont = 1;
break;
}
@ -137,107 +103,104 @@ get_default_menu_item(struct linkedlist_t *list)
/* Return the text of the menu entry for PACKAGE, translated to
LANGUAGE if possible. */
static char *menu_entry(struct debconfclient *debconf, char *language,
struct package_t *package)
static size_t menu_entry(struct debconfclient *debconf, char *language, di_package *package, char *buf, size_t size)
{
char *entry = NULL, *question;
char question[256];
asprintf(&question, "debian-installer/%s/title", package->package);
snprintf(question, sizeof(question), "debian-installer/%s/title", package->package);
if (language) {
char *field;
char field[128];
asprintf(&field, "Description-%s.UTF-8", language);
snprintf(field, sizeof (128), "Description-%s.UTF-8", language);
if (!debconf_metaget(debconf, question, field))
entry = strdup(debconf->value);
free(field);
{
strncpy(buf, debconf->value, size);
return strlen (buf);
}
}
if (entry == NULL && !debconf_metaget(debconf, question, "Description"))
entry = strdup(debconf->value);
free(question);
if (!debconf_metaget(debconf, question, "Description"))
{
strncpy(buf, debconf->value, size);
return strlen (buf);
}
/* The following fallback case can go away once all packages
have transitioned to the new form. */
if (entry == NULL) {
di_logf("Falling back to the package description for %s",
package->package);
entry = strdup(package->description);
}
return entry;
di_log(DI_LOG_LEVEL_INFO, "Falling back to the package description for %s", package->package);
strncpy(buf, package->description, size);
return strlen (buf);
}
/* Displays the main menu via debconf and returns the selected menu item. */
struct package_t *show_main_menu(struct linkedlist_t *list) {
static struct debconfclient *debconf = NULL;
di_package *show_main_menu(di_packages *packages, di_packages_allocator *allocator) {
char *language = NULL;
struct package_t **package_list, *p;
struct linkedlist_t *olist;
struct list_node *node;
struct package_t *menudefault = NULL, *ret = NULL;
di_package **package_array, *p;
di_slist *list;
di_slist_node *node;
di_package *menudefault = NULL, *ret = NULL;
int i = 0, num = 0;
char *s;
char menutext[1024];
char buf[256], *menu, *s;
int menu_size, menu_used, size;
if (! debconf)
debconf = debconfclient_new();
debconf->command(debconf, "GET", "debian-installer/language", NULL);
if (language)
free(language);
if (debconf->value)
language = strdup(debconf->value);
/* Make a flat list of the packages. */
for (node = list->head; node; node = node->next) {
p = (struct package_t *)node->data;
if (p->installer_menu_item)
for (node = packages->list.head; node; node = node->next) {
p = node->data;
if (((di_system_package *)p)->installer_menu_item)
num++;
}
package_list = malloc(num * sizeof(struct package_t *));
for (node = list->head; node; node = node->next) {
p = (struct package_t *)node->data;
if (p->installer_menu_item)
package_list[i++] = (struct package_t *)node->data;
package_array = di_new (di_package *, num + 1);
package_array[num] = NULL;
for (node = packages->list.head; node; node = node->next) {
p = node->data;
if (((di_system_package *)p)->installer_menu_item)
package_array[i++] = node->data;
}
/* Sort by menu number. */
qsort(package_list, num, sizeof(struct package_t *), compare);
qsort(package_array, num, sizeof (di_package *), package_array_compare);
/* Order menu so depended-upon packages come first. */
/* The menu number is really only used to break ties. */
olist = di_pkg_toposort_arr(package_list, num);
list = di_packages_resolve_dependencies_array (packages, package_array, allocator);
/*
* Generate list of menu choices for debconf.
*/
s = menutext;
for (node = olist->head; node != NULL; node = node->next) {
char *entry;
p = (struct package_t *)node->data;
if (!p->installer_menu_item || !check_script(p, "isinstallable"))
menu = di_malloc(1024);
menu[0] = '\0';
menu_size = 1024;
menu_used = 1;
for (node = list->head; node != NULL; node = node->next) {
p = node->data;
if (!((di_system_package *)p)->installer_menu_item || !check_script(p, "isinstallable"))
continue;
entry = menu_entry(debconf, language, p);
strcpy(s, entry);
s += strlen(entry);
*s++ = ',';
*s++ = ' ';
free(entry);
size = menu_entry(debconf, language, p, buf, sizeof (buf));
if (menu_used + size + 2 > menu_size)
{
menu_size += 1024;
menu = di_realloc(ret, menu_size);
}
strcat(menu, buf);
menu_used += size + 2;
if (node->next)
strcat(menu, ", ");
}
/* Trim trailing ", " */
if (s > menutext)
s = s - 2;
*s = 0;
s = menutext;
menudefault = get_default_menu_item(olist);
free(olist);
menudefault = get_default_menu_item(list);
di_slist_free(list);
/* Make debconf show the menu and get the user's choice. */
debconf->command(debconf, "SETTITLE", "debian-installer/main-menu-title", NULL);
debconf->command(debconf, "CAPB", NULL);
debconf->command(debconf, "FSET", MAIN_MENU, "seen", "false", NULL);
debconf->command(debconf, "SUBST", MAIN_MENU, "MENU", menutext, NULL);
debconf->command(debconf, "SUBST", MAIN_MENU, "MENU", menu, NULL);
if (menudefault) {
char *entry = menu_entry(debconf, language, menudefault);
debconf->command(debconf, "SET", MAIN_MENU, entry, NULL);
free(entry);
menu_entry(debconf, language, menudefault, buf, sizeof (buf));
debconf->command(debconf, "SET", MAIN_MENU, buf, NULL);
}
debconf->command(debconf, "INPUT", "medium", MAIN_MENU, NULL);
debconf->command(debconf, "GO", NULL);
@ -246,23 +209,19 @@ struct package_t *show_main_menu(struct linkedlist_t *list) {
/* Figure out which menu item was selected. */
for (i = 0; i < num; i++) {
char *entry;
p = package_list[i];
entry = menu_entry(debconf, language, p);
if (strcmp(entry, s) == 0) {
free(entry);
p = package_array[i];
menu_entry(debconf, language, p, buf, sizeof (buf));
if (strcmp(buf, s) == 0) {
ret = p;
break;
}
free(entry);
}
free(s);
free(language);
free(package_list);
free(package_array);
return ret;
}
static int check_special(struct package_t *p);
static int check_special(di_package *p);
/*
* Satisfy the dependencies of a virtual package. Its dependencies
@ -270,7 +229,7 @@ static int check_special(struct package_t *p);
* question for the user to pick and choose. Other dependencies are
* just fed recursively through di_config_package.
*/
static int satisfy_virtual(struct package_t *p) {
static int satisfy_virtual(di_package *p) {
struct debconfclient *debconf;
struct package_t *dep, *defpkg = NULL;
int i;
@ -283,9 +242,6 @@ static int satisfy_virtual(struct package_t *p) {
if (debconf->value)
language = strdup(debconf->value);
if (asprintf(&choices, "") == -1) {
return 0;
}
/* Compile a list of providing package. The default choice will be the
* package with highest priority. If we have ties, menu items are
* preferred. If we still have ties, the default choice is arbitrary */
@ -521,9 +477,13 @@ static void adjust_default_priority (void) {
}
int main (int argc, char **argv) {
struct package_t *p;
di_package *p;
di_packages *packages;
di_packages_allocator *allocator;
int ret;
debconf = debconfclient_new();
/* This spawns a process that traps all stderr from the rest of
* main-menu and the programs it calls, storing it in STDERR_LOG. */
intercept_stderr();
@ -531,7 +491,7 @@ int main (int argc, char **argv) {
/* Tell udpkg to shut up. */
setenv("UDPKG_QUIET", "y", 1);
packages = di_status_read();
packages = di_system_packages_status_read_file();
while ((p=show_main_menu(packages))) {
ret = do_menu_item(p);
adjust_default_priority();

5
main-menu.h

@ -1,11 +1,9 @@
#ifdef DODEBUG
#include <assert.h>
#define ASSERT(x) assert(x)
#define SYSTEM(x) do_system(x)
#define DPRINTF(fmt,args...) fprintf(stderr, fmt, ##args)
#else
#define ASSERT(x) /* nothing */
#define SYSTEM(x) system(x)
#define DPRINTF(fmt,args...) /* nothing */
#endif
@ -16,6 +14,3 @@
#include <debian-installer.h>
/* status.c */
struct linkedlist_t *status_read(void);

Loading…
Cancel
Save