You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

711 lines
20 KiB

  1. /*
  2. * Debian Installer main menu program.
  3. *
  4. * Copyright 2000,2004 Joey Hess <joeyh@debian.org>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. */
  16. #include "main-menu.h"
  17. #include <cdebconf/debconfclient.h>
  18. #include <stdlib.h>
  19. #include <search.h>
  20. #include <stdio.h>
  21. #include <sys/stat.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <signal.h>
  25. #include <sys/types.h>
  26. #include <unistd.h>
  27. #include <dirent.h>
  28. #include <errno.h>
  29. const int RAISE = 1;
  30. const int LOWER = 0;
  31. int last_successful_item = -1;
  32. /* Save default priority, to be able to return to it when we have to lower it */
  33. int default_priority = 1;
  34. /* Save priority set by main-menu to detect priority changes from the user */
  35. int local_priority = -1;
  36. static struct debconfclient *debconf;
  37. static int di_config_package(di_system_package *p,
  38. int (*virtfunc)(di_system_package *));
  39. static void modify_debconf_priority (int raise_or_lower);
  40. /*
  41. * qsort comparison function (sort by menu item values, fall back to
  42. * lexical sort to resolve ties deterministically).
  43. */
  44. int package_array_compare (const void *v1, const void *v2) {
  45. di_system_package *p1, *p2;
  46. p1 = *(di_system_package **)v1;
  47. p2 = *(di_system_package **)v2;
  48. int r = p1->installer_menu_item - p2->installer_menu_item;
  49. if (r) return r;
  50. return strcmp(p1->p.package, p2->p.package);
  51. }
  52. int isdefault(di_system_package *p) {
  53. int check;
  54. check = di_system_dpkg_package_control_file_exec(&p->p, "menutest", 0, NULL);
  55. if (check <= 0 || p->p.status == di_package_status_unpacked || p->p.status == di_package_status_half_configured)
  56. return true;
  57. return false;
  58. }
  59. bool isinstallable(di_system_package *p) {
  60. int check;
  61. check = di_system_dpkg_package_control_file_exec(&p->p, "isinstallable", 0, NULL);
  62. if (check <= 0)
  63. return true;
  64. return false;
  65. }
  66. /* Return nonzero if all of the virtual packages that P provides are
  67. provided by installed packages. */
  68. int provides_installed_virtual_packages(di_package *p) {
  69. di_slist_node *node1, *node2;
  70. int provides = 0;
  71. for (node1 = p->depends.head; node1; node1 = node1->next) {
  72. di_package_dependency *d = node1->data;
  73. if (d->type == di_package_dependency_type_provides) {
  74. int installed = 0;
  75. provides = 1;
  76. for (node2 = d->ptr->depends.head; node2; node2 = node2->next) {
  77. d = node2->data;
  78. if (d->type == di_package_dependency_type_reverse_provides
  79. && d->ptr->status == di_package_status_installed) {
  80. installed = 1;
  81. break;
  82. }
  83. }
  84. if (!installed)
  85. return 0;
  86. }
  87. }
  88. return provides;
  89. }
  90. /* Expects a topologically ordered linked list of packages. */
  91. static di_system_package *
  92. get_default_menu_item(di_slist *list)
  93. {
  94. di_system_package *p;
  95. di_slist_node *node;
  96. /* Traverse the list, return the first menu item that isn't installed */
  97. for (node = list->head; node != NULL; node = node->next) {
  98. p = node->data;
  99. //di_log(DI_LOG_LEVEL_DEBUG, "find default; on: %s", p->p.package);
  100. if (!p->installer_menu_item ||
  101. p->p.status == di_package_status_installed ||
  102. !isinstallable(p)) {
  103. //di_log(DI_LOG_LEVEL_DEBUG, "not menu item; or not installed");
  104. continue;
  105. }
  106. if (p->installer_menu_item < last_successful_item &&
  107. p->installer_menu_item < NEVERDEFAULT) {
  108. //di_log(DI_LOG_LEVEL_DEBUG, "not in range to be default");
  109. continue;
  110. }
  111. /* If menutest says this item should be default, make it so */
  112. if (!isdefault(p)) {
  113. //di_log(DI_LOG_LEVEL_DEBUG, "isdefalt says no");
  114. continue;
  115. }
  116. /* If all of the virtual packages provided by a
  117. package have already been satisfied, do not default
  118. to it. */
  119. if (!provides_installed_virtual_packages(&p->p)) {
  120. //di_log(DI_LOG_LEVEL_DEBUG, "success on this one");
  121. return p;
  122. }
  123. //di_log(DI_LOG_LEVEL_DEBUG, "not default");
  124. }
  125. /* Severely broken, there are no menu items in the sorted list */
  126. return NULL;
  127. }
  128. /* Return the text of the menu entry for PACKAGE. */
  129. static size_t menu_entry(struct debconfclient *debconf, di_system_package *package, char *buf, size_t size)
  130. {
  131. char question[256];
  132. snprintf(question, sizeof(question), "debian-installer/%s/title", package->p.package);
  133. if (!debconf_metaget(debconf, question, "Description")) {
  134. strncpy(buf, debconf->value, size);
  135. return strlen (buf);
  136. }
  137. /* The following fallback case can go away once all packages
  138. have transitioned to the new form. */
  139. di_log(DI_LOG_LEVEL_INFO, "Falling back to the package description for %s", package->p.package);
  140. if (package->p.short_description)
  141. strncpy(buf, package->p.short_description, size);
  142. return strlen (buf);
  143. }
  144. /* Displays the main menu via debconf and returns the selected menu item. */
  145. di_system_package *show_main_menu(di_packages *packages, di_packages_allocator *allocator) {
  146. di_system_package **package_array, *p;
  147. di_slist *list;
  148. di_slist_node *node;
  149. di_system_package *menudefault = NULL, *ret = NULL;
  150. int i = 0, num = 0;
  151. char buf[256], *menu, *s;
  152. int menu_size, menu_used, size;
  153. for (node = packages->list.head; node; node = node->next) {
  154. p = node->data;
  155. if (((di_system_package *)p)->installer_menu_item)
  156. num++;
  157. }
  158. package_array = di_new (di_system_package *, num + 1);
  159. package_array[num] = NULL;
  160. for (node = packages->list.head; node; node = node->next) {
  161. p = node->data;
  162. if (p->installer_menu_item)
  163. package_array[i++] = node->data;
  164. }
  165. /* Sort by menu number. */
  166. qsort(package_array, num, sizeof (di_system_package *), package_array_compare);
  167. /* Order menu so depended-upon packages come first. */
  168. /* The menu number is really only used to break ties. */
  169. list = di_system_packages_resolve_dependencies_array_permissive (packages, (di_package **) package_array, allocator);
  170. /*
  171. * Generate list of menu choices for debconf.
  172. */
  173. menu = di_malloc(1024);
  174. menu[0] = '\0';
  175. menu_size = 1024;
  176. menu_used = 1;
  177. for (node = list->head; node != NULL; node = node->next) {
  178. p = node->data;
  179. if (!p->installer_menu_item ||
  180. !isinstallable(p))
  181. continue;
  182. size = menu_entry(debconf, p, buf, sizeof (buf));
  183. if (menu_used + size + 2 > menu_size)
  184. {
  185. menu_size += 1024;
  186. menu = di_realloc(menu, menu_size);
  187. }
  188. if (*menu)
  189. strcat(menu, ", ");
  190. strcat(menu, buf);
  191. menu_used += size + 2;
  192. }
  193. menudefault = get_default_menu_item(list);
  194. di_slist_free(list);
  195. /* Make debconf show the menu and get the user's choice. */
  196. debconf_settitle(debconf, "debian-installer/main-menu-title");
  197. debconf_capb(debconf);
  198. debconf_subst(debconf, MAIN_MENU, "MENU", menu);
  199. if (menudefault) {
  200. menu_entry(debconf, menudefault, buf, sizeof (buf));
  201. debconf_set(debconf, MAIN_MENU, buf);
  202. }
  203. else {
  204. di_log(DI_LOG_LEVEL_INFO, "no default menu item");
  205. modify_debconf_priority(LOWER);
  206. }
  207. debconf_input(debconf, MENU_PRIORITY, MAIN_MENU);
  208. debconf_go(debconf);
  209. debconf_get(debconf, MAIN_MENU);
  210. s = strdup(debconf->value);
  211. /* Figure out which menu item was selected. */
  212. for (i = 0; i < num; i++) {
  213. p = package_array[i];
  214. menu_entry(debconf, p, buf, sizeof (buf));
  215. if (strcmp(buf, s) == 0) {
  216. ret = p;
  217. break;
  218. }
  219. }
  220. if (! ret) {
  221. /* This could happen because of a debconf protocol problem
  222. * (for example, leading whitespace in menu items can
  223. * be stripped and confuse the comparisons), or other
  224. * problem. */
  225. di_log(DI_LOG_LEVEL_WARNING, "Internal error! Cannot find \"%s\" in menu.", s);
  226. }
  227. free(package_array);
  228. return ret;
  229. }
  230. /*
  231. * Satisfy the dependencies of a virtual package. Its dependencies
  232. * that actually provide the package are presented in a debconf select
  233. * question for the user to pick and choose. Other dependencies are
  234. * just fed recursively through di_config_package.
  235. */
  236. static int satisfy_virtual(di_system_package *p) {
  237. di_slist_node *node;
  238. di_system_package *dep, *defpkg = NULL;
  239. char buf[256], *menu, *s = NULL;
  240. size_t menu_size, menu_used, size;
  241. int is_menu_item = 0;
  242. menu = di_malloc(1024);
  243. menu[0] = '\0';
  244. menu_size = 1024;
  245. menu_used = 1;
  246. /* Compile a list of providing package. The default choice will be the
  247. * package with highest priority. If we have ties, menu items are
  248. * preferred. If we still have ties, the default choice is arbitrary */
  249. for (node = p->p.depends.head; node; node = node->next) {
  250. di_package_dependency *d = node->data;
  251. dep = (di_system_package *)d->ptr;
  252. if (d->type == di_package_dependency_type_depends) {
  253. /* Non-providing dependency */
  254. di_log(DI_LOG_LEVEL_DEBUG, "non-providing dependency from %s to %s", p->p.package, dep->p.package);
  255. if (dep->p.status != di_package_status_installed) {
  256. switch (di_config_package(dep, satisfy_virtual)) {
  257. case -1:
  258. return -1;
  259. case EXIT_BACKUP:
  260. return EXIT_BACKUP;
  261. }
  262. }
  263. continue;
  264. }
  265. if (d->type != di_package_dependency_type_reverse_provides)
  266. continue;
  267. if (dep->p.status == di_package_status_installed) {
  268. /* This means that a providing package is already
  269. * configure. So we short-circuit. */
  270. menu_used = 0;
  271. break;
  272. }
  273. if (defpkg == NULL || dep->p.priority > defpkg->p.priority ||
  274. (dep->p.priority == defpkg->p.priority &&
  275. dep->installer_menu_item < defpkg->installer_menu_item))
  276. defpkg = dep;
  277. /* This only makes sense if one of the dependencies
  278. * is a menu item */
  279. if (dep->installer_menu_item)
  280. is_menu_item = 1;
  281. size = menu_entry(debconf, dep, buf, sizeof (buf));
  282. if (menu_used + size + 2 > menu_size)
  283. {
  284. menu_size += 1024;
  285. menu = di_realloc(menu, menu_size);
  286. }
  287. if (dep == defpkg) {
  288. /* We want the default to be the first item */
  289. char *temp;
  290. temp = di_malloc (menu_size);
  291. strcpy(temp, menu);
  292. strcpy(menu, buf);
  293. if (strlen(temp)) {
  294. strcat(menu, ", ");
  295. strcat(menu, temp);
  296. }
  297. di_free(temp);
  298. } else {
  299. if (strlen(menu)) {
  300. strcat(menu, ", ");
  301. }
  302. strcat(menu, buf);
  303. }
  304. menu_used += size + 2;
  305. }
  306. if (menu_used >= 2)
  307. menu[menu_used-2] = '\0';
  308. if (menu_used > 1) {
  309. if (is_menu_item) {
  310. char *priority = "medium";
  311. /* Only let the user choose if one of them is a menu item */
  312. if (defpkg != NULL) {
  313. menu_entry(debconf, defpkg, buf, sizeof(buf));
  314. debconf_set(debconf, MISSING_PROVIDE, buf);
  315. } else {
  316. /* TODO: How to figure out a default? */
  317. priority = "critical";
  318. }
  319. debconf_capb(debconf, "backup");
  320. debconf_subst(debconf, MISSING_PROVIDE, "CHOICES", menu);
  321. debconf_input(debconf, priority, MISSING_PROVIDE);
  322. if (debconf_go(debconf) != 0)
  323. return 0;
  324. debconf_capb(debconf);
  325. debconf_get(debconf, MISSING_PROVIDE);
  326. s = strdup(debconf->value);
  327. }
  328. /* Go through the dependencies again */
  329. for (node = p->p.depends.head; node; node = node->next) {
  330. di_package_dependency *d = node->data;
  331. dep = (di_system_package *)d->ptr;
  332. menu_entry(debconf, dep, buf, sizeof(buf));
  333. if (!is_menu_item || strcmp(s, buf) == 0) {
  334. /* Ick. If we have a menu item it has to match the
  335. * debconf choice, otherwise we configure all of
  336. * the providing packages */
  337. switch (di_config_package(dep, satisfy_virtual)) {
  338. case -1:
  339. return -1;
  340. case EXIT_BACKUP:
  341. return EXIT_BACKUP;
  342. }
  343. if (is_menu_item)
  344. break;
  345. }
  346. }
  347. }
  348. free(menu);
  349. free(s);
  350. /* It doesn't make sense to configure virtual packages,
  351. * since they are, well, virtual. */
  352. p->p.status = di_package_status_installed;
  353. return 1;
  354. }
  355. static void set_package_title(di_system_package *p) {
  356. char *title;
  357. if (!p->installer_menu_item)
  358. return;
  359. asprintf(&title, "debian-installer/%s/title", p->p.package);
  360. if (debconf_settitle(debconf, title))
  361. di_log(DI_LOG_LEVEL_WARNING, "Unable to set title for %s.", p->p.package);
  362. free(title);
  363. }
  364. static int do_menu_item(di_system_package *p) {
  365. di_log(DI_LOG_LEVEL_DEBUG, "Menu item '%s' selected", p->p.package);
  366. return di_config_package(p, satisfy_virtual);
  367. }
  368. static char *debconf_priorities[] =
  369. {
  370. "low",
  371. "medium",
  372. "high",
  373. "critical"
  374. };
  375. #define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
  376. static void modify_debconf_priority (int raise_or_lower) {
  377. int pri, i;
  378. static int menu_pri = -1;
  379. const char *template = "debconf/priority";
  380. debconf_get(debconf, template);
  381. if (menu_pri == -1) {
  382. for (i = 0; (size_t)i < ARRAY_SIZE(debconf_priorities); ++i) {
  383. if (0 == strcmp(MENU_PRIORITY,
  384. debconf_priorities[i]) ) {
  385. menu_pri = i;
  386. break;
  387. }
  388. }
  389. }
  390. pri = 1;
  391. if ( debconf->value ) {
  392. for (i = 0; (size_t)i < ARRAY_SIZE(debconf_priorities); ++i) {
  393. if (0 == strcmp(debconf->value,
  394. debconf_priorities[i]) ) {
  395. pri = i;
  396. break;
  397. }
  398. }
  399. }
  400. if (raise_or_lower == LOWER) {
  401. --pri;
  402. /* Make sure the menu is always displayed after a single
  403. * backing up.
  404. */
  405. if (menu_pri != -1 && pri > menu_pri)
  406. pri = menu_pri;
  407. }
  408. else if (raise_or_lower == RAISE)
  409. ++pri;
  410. if (0 > pri)
  411. pri = 0;
  412. if (pri > default_priority)
  413. pri = default_priority;
  414. if (local_priority != pri) {
  415. di_log(DI_LOG_LEVEL_INFO, "Modifying debconf priority limit from '%s' to '%s'",
  416. debconf->value ? debconf->value : "(null)",
  417. debconf_priorities[pri] ? debconf_priorities[pri] : "(null)");
  418. local_priority = pri;
  419. debconf_set(debconf, template, debconf_priorities[pri]);
  420. }
  421. }
  422. static void adjust_default_priority (void) {
  423. int pri, i;
  424. const char *template = "debconf/priority";
  425. debconf_get(debconf, template);
  426. pri = 1;
  427. if ( debconf->value ) {
  428. for (i = 0; (size_t)i < ARRAY_SIZE(debconf_priorities); ++i) {
  429. if (0 == strcmp(debconf->value,
  430. debconf_priorities[i]) ) {
  431. pri = i;
  432. break;
  433. }
  434. }
  435. }
  436. if ( pri != local_priority ) {
  437. di_log(DI_LOG_LEVEL_INFO, "Priority changed externally, setting main-menu default to '%s' (%s)",
  438. debconf_priorities[pri] ? debconf_priorities[pri] : "(null)", debconf->value);
  439. local_priority = pri;
  440. default_priority = pri;
  441. }
  442. }
  443. void notify_user_of_failure (di_system_package *p) {
  444. char buf[256];
  445. debconf_capb(debconf);
  446. menu_entry(debconf, p, buf, sizeof (buf));
  447. debconf_subst(debconf, ITEM_FAILURE, "ITEM", buf);
  448. debconf_input(debconf, "critical", ITEM_FAILURE);
  449. debconf_go(debconf);
  450. debconf_capb(debconf, "backup");
  451. }
  452. /* execute scripts in a directory */
  453. static void do_scripts (const char *dir) {
  454. struct dirent **namelist;
  455. int entries, i;
  456. /* scandir() isn't POSIX, but it makes things easy. */
  457. entries = scandir(dir, &namelist, NULL, alphasort);
  458. if (entries < 0)
  459. return;
  460. for (i = 0; i < entries; ++i) {
  461. int ret;
  462. size_t len;
  463. char *filename;
  464. struct stat st;
  465. if (strcmp(namelist[i]->d_name, ".") == 0 || strcmp(namelist[i]->d_name, "..") == 0)
  466. continue;
  467. /* sizeof(MAIN_MENU_DIR) includes trailing \0 */
  468. len = strlen(dir) + 1 + strlen(namelist[i]->d_name) + 1;
  469. filename = di_new(char, len);
  470. snprintf(filename, len, "%s/%s", dir, namelist[i]->d_name);
  471. di_log(DI_LOG_LEVEL_INFO, "filename=%s", filename);
  472. if (stat(filename, &st) != 0) {
  473. di_log(DI_LOG_LEVEL_WARNING, "Can't stat %s (%s)", filename, strerror(errno));
  474. di_free(filename);
  475. continue;
  476. }
  477. if (!S_ISREG(st.st_mode)) {
  478. di_log(DI_LOG_LEVEL_WARNING, "%s is not a regular file", filename);
  479. di_free(filename);
  480. continue;
  481. }
  482. if (access(filename, X_OK) != 0) {
  483. di_log(DI_LOG_LEVEL_WARNING, "%s is not executable", filename);
  484. di_free(filename);
  485. continue;
  486. }
  487. di_log(DI_LOG_LEVEL_DEBUG, "Executing %s", filename);
  488. ret = system(filename);
  489. if (ret != 0)
  490. di_log(DI_LOG_LEVEL_WARNING, "%s exited with status %d", filename, ret);
  491. di_free(filename);
  492. }
  493. }
  494. /* Cheap-and-cheerful run-parts-a-like for /lib/main-menu.d. Allows packages
  495. * to register scripts to be run at main-menu startup that need to share
  496. * main-menu's debconf frontend but that don't merit a menu item, such as
  497. * setting an info message.
  498. */
  499. static void menu_startup (void) {
  500. do_scripts(MAIN_MENU_DIR);
  501. }
  502. static void package_scripts(char *pkg_name, char *dir) {
  503. size_t len;
  504. char *pkg_dir_name;
  505. len = strlen(dir) + 1 + strlen(pkg_name) + 1;
  506. pkg_dir_name = di_new(char, len);
  507. snprintf(pkg_dir_name, len, "%s/%s", dir, pkg_name);
  508. di_log(DI_LOG_LEVEL_INFO, "pkg_dir_name=%s", pkg_dir_name);
  509. do_scripts(pkg_dir_name);
  510. di_free(pkg_dir_name);
  511. }
  512. static void package_pre(char *pkg_name) {
  513. di_log(DI_LOG_LEVEL_INFO, "Start Pre-scripts for package %s", pkg_name);
  514. package_scripts(pkg_name, MAIN_MENU_PRE_DIR);
  515. }
  516. static void package_post(char *pkg_name) {
  517. di_log(DI_LOG_LEVEL_INFO, "Start Post-scripts for package %s", pkg_name);
  518. package_scripts(pkg_name, MAIN_MENU_POST_DIR);
  519. }
  520. int main (int argc __attribute__ ((unused)), char **argv) {
  521. di_system_package *p;
  522. di_packages *packages;
  523. di_packages_allocator *allocator;
  524. int ret;
  525. debconf = debconfclient_new();
  526. di_system_init(basename(argv[0]));
  527. /* Tell udpkg to shut up. */
  528. setenv("UDPKG_QUIET", "y", 1);
  529. menu_startup();
  530. allocator = di_system_packages_allocator_alloc ();
  531. packages = di_system_packages_status_read_file(DI_SYSTEM_DPKG_STATUSFILE, allocator);
  532. while ((p=show_main_menu(packages, allocator))) {
  533. package_pre(p->p.package);
  534. ret = do_menu_item(p);
  535. adjust_default_priority();
  536. switch (ret) {
  537. case EXIT_OK:
  538. /* Success */
  539. package_post(p->p.package);
  540. if (p->installer_menu_item < NEVERDEFAULT) {
  541. last_successful_item = p->installer_menu_item;
  542. modify_debconf_priority(RAISE);
  543. //di_log(DI_LOG_LEVEL_DEBUG, "Installed package '%s', raising last_successful_item to %d", p->p.package, p->installer_menu_item);
  544. }
  545. else {
  546. // di_log(DI_LOG_LEVEL_DEBUG, "Installed package '%s' but no raise since %d >= %i", p->p.package, p->installer_menu_item, NEVERDEFAULT);
  547. }
  548. break;
  549. case EXIT_BACKUP:
  550. di_log(DI_LOG_LEVEL_INFO, "Menu item '%s' succeeded but requested to be left unconfigured.", p->p.package);
  551. modify_debconf_priority(LOWER);
  552. break;
  553. default:
  554. di_log(DI_LOG_LEVEL_WARNING, "Menu item '%s' failed.", p->p.package);
  555. notify_user_of_failure(p);
  556. modify_debconf_priority(LOWER);
  557. }
  558. di_packages_free (packages);
  559. di_packages_allocator_free (allocator);
  560. allocator = di_system_packages_allocator_alloc ();
  561. packages = di_system_packages_status_read_file(DI_SYSTEM_DPKG_STATUSFILE, allocator);
  562. /* tell cdebconf to save the database */
  563. debconf->command(debconf, "X_SAVE", NULL);
  564. }
  565. return EXIT_FAILURE;
  566. }
  567. /*
  568. * Configure all dependencies, special case for virtual packages.
  569. * This is done depth-first.
  570. */
  571. static int di_config_package(di_system_package *p,
  572. int (*virtfunc)(di_system_package *)) {
  573. char *configcommand;
  574. int ret;
  575. di_slist_node *node;
  576. di_system_package *dep;
  577. di_log(DI_LOG_LEVEL_DEBUG, "configure %s, status: %d\n", p->p.package, p->p.status);
  578. if (p->p.type == di_package_type_virtual_package) {
  579. di_log(DI_LOG_LEVEL_DEBUG, "virtual package %s\n", p->p.package);
  580. if (virtfunc)
  581. return virtfunc(p);
  582. else
  583. return -1;
  584. }
  585. else if (p->p.type == di_package_type_non_existent)
  586. return 0;
  587. for (node = p->p.depends.head; node; node = node->next) {
  588. di_package_dependency *d = node->data;
  589. dep = (di_system_package *)d->ptr;
  590. if (dep->p.status == di_package_status_installed)
  591. continue;
  592. if (d->type != di_package_dependency_type_depends)
  593. continue;
  594. /* Recursively configure this package */
  595. switch (di_config_package(dep, virtfunc)) {
  596. case -1:
  597. return -1;
  598. case EXIT_BACKUP:
  599. return EXIT_BACKUP;
  600. }
  601. }
  602. set_package_title(p);
  603. if (asprintf(&configcommand, "exec udpkg --configure --force-configure %s", p->p.package) == -1)
  604. return -1;
  605. ret = di_exec_shell_log(configcommand);
  606. ret = di_exec_mangle_status(ret);
  607. free(configcommand);
  608. switch (ret) {
  609. case EXIT_OK:
  610. p->p.status = di_package_status_installed;
  611. break;
  612. default:
  613. di_log(DI_LOG_LEVEL_WARNING, "Configuring '%s' failed with error code %d", p->p.package, ret);
  614. ret = -1;
  615. case EXIT_BACKUP:
  616. p->p.status = di_package_status_half_configured;
  617. break;
  618. }
  619. return ret;
  620. }
  621. /* vim: noexpandtab sw=8
  622. */