Browse Source

work on the main menu at ALS

r39
keep-around/c8703c509368e1805e513d61f98a9d17d2cdd9cc
Joey Hess 22 years ago
parent
commit
10c13b8e2f
  1. 4
      Makefile
  2. 6
      TODO
  3. 30
      debconf.c
  4. 83
      main-menu.c
  5. 20
      main-menu.h
  6. 23
      status.c

4
Makefile

@ -2,6 +2,10 @@ CFLAGS=-Wall -g
OBJS=$(subst .c,.o,$(wildcard *.c))
BIN=main-menu
ifdef DEBUG
CFLAGS:=$(CFLAGS) -DDODEBUG
endif
all: $(BIN)
$(BIN): $(OBJS)

6
TODO

@ -1,5 +1,7 @@
* Once something is picked from the menu, (re)configure its package (and
first configure everything its package depends on).
* Fix all memory leaks (probably just the btree and the actual package
structs).
* Picking a main menu item that is unpacked but not configured doesn't seem
to be running dpkg.
* Figure out how to handle configuring only one virtual package (pick off
of a menu?) if the menu item depends on a virtual package.
* Does not support translating menu items. Two possibilities:

30
debconf.c

@ -1,3 +1,7 @@
/*
* Debconf communication routines.
*/
#include "main-menu.h"
#include <stdio.h>
@ -8,6 +12,12 @@
/* Holds the textual return code of the last command. */
char *text;
/* Returns the last command's textual return code. */
char *debconf_ret (void) {
return text;
}
/* Talks to debconf and returns the numeric return code. */
int debconf_command (const char *fmt, ...) {
char buf[BUFSIZE];
va_list ap;
@ -19,13 +29,15 @@ int debconf_command (const char *fmt, ...) {
fflush(stdout); /* make sure debconf sees it to prevent deadlock */
fgets(buf, BUFSIZE, stdin);
/* TODO: this could be more robust */
strtok(buf, " \t\n");
text=strtok(NULL, "\n");
return atoi(buf);
}
char *debconf_ret (void) {
return text;
buf[strlen(buf)-1] = 0;
if (strlen(buf)) {
strtok(buf, " \t\n");
text=strtok(NULL, "\n");
return atoi(buf);
}
else {
/* Nothing was entered; never really happens. */
text=buf;
return 0;
}
}

83
main-menu.c

@ -1,3 +1,19 @@
/*
* Debian Installer main menu program.
*
* Copyright 2000 Joey Hess <joeyh@debian.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "main-menu.h"
#include <stdlib.h>
@ -6,11 +22,12 @@
#include <sys/stat.h>
#include <stdlib.h>
/* For btree. */
int package_compare (const void *p1, const void *p2) {
return strcmp(((struct package_t *)p1)->package,
((struct package_t *)p2)->package);
#ifdef DODEBUG
static int do_system(const char *cmd) {
DPRINTF("cmd is %s\n", cmd);
return system(cmd);
}
#endif
/*
* qsort comparison function (sort by menu item values, fallback to lexical
@ -24,19 +41,23 @@ int compare (const void *a, const void *b) {
(*(struct package_t **)a)->package);
}
static void order(struct package_t *p, void *package_tree,
struct package_t **head, struct package_t **tail) {
struct package_t dep;
void *found;
/*
* Builds a linked list of packages, ordered by dependencies, so
* depended-upon packages come first. Pass the package to start ordering
* at. head points to the start of the ordered list of packages, and tail
* points to the end of the list (generally pass in pointers to NULL, unless
* successive calls to the function are needed to build up a larger list.
*/
void order(struct package_t *p, struct package_t **head, struct package_t **tail) {
struct package_t *found;
int i;
if (p->processed)
return;
for (i=0; p->depends[i] != 0; i++) {
dep.package = p->depends[i];
if ((found = tfind(&dep, &package_tree, package_compare)))
order(*(struct package_t **)found, package_tree, head, tail);
if ((found = tree_find(p->depends[1])))
order(found, head, tail);
}
if (*head) {
@ -55,7 +76,7 @@ int isdefault(struct package_t *p) {
sprintf(menutest, DPKGDIR "info/%s.menutest", p->package);
if (stat(menutest, &statbuf) == 0) {
return ! system(menutest);
return ! SYSTEM(menutest);
}
else if (p->status == STATUS_UNPACKED) {
return 1;
@ -63,19 +84,16 @@ int isdefault(struct package_t *p) {
return 0;
}
/* Displays the main menu via debconf. */
/* Displays the main menu via debconf and returns the selected menu item. */
struct package_t *show_main_menu(struct package_t *packages) {
struct package_t **package_list, *p, *head = NULL, *tail = NULL;
int i = 0, num = 0;
void *package_tree = NULL;
char *s, *menudefault = NULL;
char menutext[1024];
/* Make a flat list of the packages, plus a btree for name lookup. */
for (p = packages; p; p = p->next) {
tsearch(p, &package_tree, package_compare);
/* Make a flat list of the packages. */
for (p = packages; p; p = p->next)
num++;
}
package_list = malloc(num * sizeof(struct package_t *));
for (p = packages; p; p = p->next) {
package_list[i] = p;
@ -89,9 +107,11 @@ struct package_t *show_main_menu(struct package_t *packages) {
/* The menu number is really only used to break ties. */
for (i = 0; i < num ; i++) {
if (package_list[i]->installer_menu_item) {
order(package_list[i], package_tree, &head, &tail);
order(package_list[i], &head, &tail);
}
}
free(package_list);
/*
* Generate list of menu choices for debconf. Also figure out which
@ -133,6 +153,30 @@ struct package_t *show_main_menu(struct package_t *packages) {
}
void do_menu_item(struct package_t *p) {
char configcommand[1024];
struct package_t *head = NULL, *tail = NULL;
if (p->status == STATUS_INSTALLED) {
/* The menu item is already configured, so reconfigure it. */
sprintf(configcommand, "dpkg-reconfigure %s", p->package);
SYSTEM(configcommand);
}
else if (p->status == STATUS_UNPACKED) {
/*
* The menu item is not yet configured. Make sure everything
* it depends on is configured, then configure it.
*/
order(p, &head, &tail);
/* TODO: bug here, these should not be null */
DPRINTF("head: %p, tail: %p\n", head, tail);
for (p = head; p; p = p->next) {
if (p->status == STATUS_UNPACKED) {
sprintf(configcommand, "dpkg --configure %s",
p->package);
SYSTEM(configcommand);
}
}
}
}
int main (int argc, char **argv) {
@ -141,6 +185,7 @@ int main (int argc, char **argv) {
packages = status_read();
while ((p=show_main_menu(packages))) {
do_menu_item(p);
packages = status_read();
}

20
main-menu.h

@ -1,3 +1,14 @@
#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
#define BUFSIZE 4096
#define DPKGDIR "./" // "/var/lib/dpkg/"
#define STATUSFILE DPKGDIR "status"
@ -21,7 +32,14 @@ struct package_t {
struct package_t *next;
};
/* status.c */
struct package_t *status_read(void);
int package_compare (const void *, const void *);
/* debconf.c */
int debconf_command (const char *, ...);
char *debconf_ret (void);
/* tree.c */
struct package_t *tree_find(char *);
struct package_t *tree_add(const char *);
void tree_clear();

23
status.c

@ -1,3 +1,7 @@
/*
* dpkg status file reading routines
*/
#include "main-menu.h"
#include <stdio.h>
@ -12,9 +16,7 @@ struct package_t *status_read(void) {
FILE *f;
char *b, buf[BUFSIZE];
int i;
struct package_t virt, *newp, *p = 0;
void *package_tree = NULL;
void *found;
struct package_t *found, *newp, *p = 0;
if ((f = fopen(STATUSFILE, "r")) == NULL) {
perror(STATUSFILE);
@ -24,12 +26,9 @@ struct package_t *status_read(void) {
while (fgets(buf, BUFSIZE, f) && !feof(f)) {
buf[strlen(buf)-1] = 0;
if (strstr(buf, "Package: ") == buf) {
newp = malloc(sizeof(struct package_t));
memset(newp, 0, sizeof(struct package_t));
newp = tree_add(buf + 9);
newp->next = p;
p = newp;
p->package = strdup(buf+9);
tsearch(p, &package_tree, package_compare);
}
else if (strstr(buf, "Installer-Menu-Item: ") == buf) {
p->installer_menu_item = atoi(buf+21);
@ -87,17 +86,13 @@ struct package_t *status_read(void) {
* means that virtual packages are actually ANDed
* for the purposes of this program.
*/
virt.package = buf+10;
if ((found = tfind(&virt, &package_tree, package_compare))) {
newp=*(struct package_t **)found;
if ((found = tree_find(buf + 10))) {
newp=found;
}
else {
newp = malloc(sizeof(struct package_t));
memset(newp, 0, sizeof(struct package_t));
newp = tree_add(buf + 10);
newp->next=p->next;
p->next=newp;
newp->package = strdup(virt.package);
tsearch(newp, &package_tree, package_compare);
}
for (i=0; newp->depends[i] != 0; i++);
newp->depends[i] = p->package;

Loading…
Cancel
Save