blob: b0f6adcd3bc58d9e4aebe6d20ead0a87a879959f [file] [log] [blame]
Glenn L McGrath0e757a22001-04-08 05:27:18 +00001#include <dirent.h>
2#include <getopt.h>
Glenn L McGrathc9005752001-02-10 02:05:24 +00003#include <stdio.h>
4#include <string.h>
5#include <stdlib.h>
6#include <search.h>
7#include <errno.h>
8#include <fcntl.h>
9#include <unistd.h>
10#include <utime.h>
11#include <sys/types.h>
12#include <sys/stat.h>
Glenn L McGrath649968c2001-02-10 14:26:48 +000013
Glenn L McGrathc9005752001-02-10 02:05:24 +000014#include "busybox.h"
15
Eric Andersen3c0b4252001-03-14 01:31:11 +000016
Glenn L McGrath3af1f882001-02-12 11:33:09 +000017#define DEPENDSMAX 64 /* maximum number of depends we can handle */
Glenn L McGrathc9005752001-02-10 02:05:24 +000018
Glenn L McGrath3af1f882001-02-12 11:33:09 +000019/* Should we do full dependency checking? */
Glenn L McGrathc9005752001-02-10 02:05:24 +000020#define DODEPENDS 1
21
Glenn L McGrath3af1f882001-02-12 11:33:09 +000022/* Should we do debugging? */
23#define DODEBUG 1
Glenn L McGrathc9005752001-02-10 02:05:24 +000024
25#ifdef DODEBUG
Glenn L McGrathc9005752001-02-10 02:05:24 +000026#define SYSTEM(x) do_system(x)
27#define DPRINTF(fmt,args...) fprintf(stderr, fmt, ##args)
28#else
Glenn L McGrathc9005752001-02-10 02:05:24 +000029#define SYSTEM(x) system(x)
30#define DPRINTF(fmt,args...) /* nothing */
31#endif
32
Glenn L McGrath3af1f882001-02-12 11:33:09 +000033/* from dpkg-deb.c */
34extern int deb_extract(int optflags, const char *dir_name, const char *deb_filename);
35static const int dpkg_deb_contents = 1;
36static const int dpkg_deb_control = 2;
37// const int dpkg_deb_info = 4;
38static const int dpkg_deb_extract = 8;
39static const int dpkg_deb_verbose_extract = 16;
40static const int dpkg_deb_list = 32;
Glenn L McGrath510f0dd2001-02-10 14:53:08 +000041
Glenn L McGrath63106462001-02-11 01:40:23 +000042static const char statusfile[] = "/var/lib/dpkg/status.udeb";
43static const char new_statusfile[] = "/var/lib/dpkg/status.udeb.new";
44static const char bak_statusfile[] = "/var/lib/dpkg/status.udeb.bak";
45
46static const char dpkgcidir[] = "/var/lib/dpkg/tmp.ci/";
Glenn L McGrath63106462001-02-11 01:40:23 +000047
Glenn L McGrath510f0dd2001-02-10 14:53:08 +000048static const char infodir[] = "/var/lib/dpkg/info/";
49static const char udpkg_quiet[] = "UDPKG_QUIET";
Glenn L McGrathc9005752001-02-10 02:05:24 +000050
Glenn L McGrathaf8c65d2001-02-10 03:19:51 +000051//static const int status_wantstart = 0;
52//static const int status_wantunknown = (1 << 0);
53static const int status_wantinstall = (1 << 1);
54//static const int status_wanthold = (1 << 2);
55//static const int status_wantdeinstall = (1 << 3);
56//static const int status_wantpurge = (1 << 4);
57static const int status_wantmask = 31;
Glenn L McGrathc9005752001-02-10 02:05:24 +000058
Glenn L McGrathaf8c65d2001-02-10 03:19:51 +000059//static const int status_flagstart = 5;
60static const int status_flagok = (1 << 5); /* 32 */
61//static const int status_flagreinstreq = (1 << 6);
62//static const int status_flaghold = (1 << 7);
63//static const int status_flagholdreinstreq = (1 << 8);
64static const int status_flagmask = 480;
Glenn L McGrathc9005752001-02-10 02:05:24 +000065
Glenn L McGrathaf8c65d2001-02-10 03:19:51 +000066//static const int status_statusstart = 9;
67//static const int status_statusnoninstalled = (1 << 9); /* 512 */
68static const int status_statusunpacked = (1 << 10);
69static const int status_statushalfconfigured = (1 << 11);
70static const int status_statusinstalled = (1 << 12);
71static const int status_statushalfinstalled = (1 << 13);
72//static const int status_statusconfigfiles = (1 << 14);
73//static const int status_statuspostinstfailed = (1 << 15);
74//static const int status_statusremovalfailed = (1 << 16);
75static const int status_statusmask = 130560; /* i assume status_statusinstalled is supposed to be included */
Glenn L McGrathc9005752001-02-10 02:05:24 +000076
Glenn L McGrathaf8c65d2001-02-10 03:19:51 +000077static const char *statuswords[][10] = {
78 { (char *) 0, "unknown", "install", "hold", "deinstall", "purge", 0 },
79 { (char *) 5, "ok", "reinstreq", "hold", "hold-reinstreq", 0 },
80 { (char *) 9, "not-installed", "unpacked", "half-configured",
81 "installed", "half-installed", "config-files",
82 "post-inst-failed", "removal-failed", 0 }
83};
84
Eric Andersen3e6ff902001-03-09 21:24:12 +000085static const int color_white = 0;
86static const int color_grey = 1;
87static const int color_black = 2;
Glenn L McGrathc9005752001-02-10 02:05:24 +000088
89/* data structures */
Glenn L McGrath649968c2001-02-10 14:26:48 +000090typedef struct package_s {
Glenn L McGrathc9005752001-02-10 02:05:24 +000091 char *file;
92 char *package;
93 char *version;
94 char *depends;
95 char *provides;
96 char *description;
97 int installer_menu_item;
98 unsigned long status;
99 char color; /* for topo-sort */
Glenn L McGrath649968c2001-02-10 14:26:48 +0000100 struct package_s *requiredfor[DEPENDSMAX];
Glenn L McGrathc9005752001-02-10 02:05:24 +0000101 unsigned short requiredcount;
Glenn L McGrath649968c2001-02-10 14:26:48 +0000102 struct package_s *next;
103} package_t;
Glenn L McGrathc9005752001-02-10 02:05:24 +0000104
Glenn L McGrath63106462001-02-11 01:40:23 +0000105#ifdef DODEBUG
106static int do_system(const char *cmd)
107{
108 DPRINTF("cmd is %s\n", cmd);
109 return system(cmd);
110}
111#else
112#define do_system(cmd) system(cmd)
113#endif
114
Glenn L McGrath649968c2001-02-10 14:26:48 +0000115static int package_compare(const void *p1, const void *p2)
116{
117 return strcmp(((package_t *)p1)->package,
118 ((package_t *)p2)->package);
119}
Glenn L McGrathc9005752001-02-10 02:05:24 +0000120
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000121/*
122 * NOTE: this was handled by a "rm -rf" shell command
123 * Maybe theis behaviour should be integrated into the rm applet
124 * (i dont appreciate the rm applets recursive action fn)-bug1
125 */
126static int remove_dir(const char *dirname)
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000127{
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000128 struct dirent *fp;
129 DIR *dp = opendir(dirname);
130 while ((fp = readdir(dp)) != NULL) {
131 struct stat statbuf;
132 char *filename;
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000133
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000134 filename = (char *) xcalloc(1, strlen(dirname) + strlen(fp->d_name) + 2);
135 strcpy(filename, dirname);
136 strcat(filename, fp->d_name);
137 lstat(filename, &statbuf);
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000138
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000139 if ((strcmp(fp->d_name, ".") != 0) && (strcmp(fp->d_name, "..") != 0)) {
140 if (S_ISDIR(statbuf.st_mode)) {
141 remove_dir(strcat(filename, "/"));
142 }
143 else if (remove(filename) == -1) {
144 perror_msg(filename);
145 }
146 }
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000147 }
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000148 remove(dirname);
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000149 return EXIT_SUCCESS;
150}
151
Glenn L McGrathc9005752001-02-10 02:05:24 +0000152#ifdef DODEPENDS
153#include <ctype.h>
154
155static char **depends_split(const char *dependsstr)
156{
157 static char *dependsvec[DEPENDSMAX];
158 char *p;
159 int i = 0;
160
161 dependsvec[0] = 0;
Glenn L McGrath63106462001-02-11 01:40:23 +0000162 if (dependsstr == 0) {
163 goto end;
Glenn L McGrathc9005752001-02-10 02:05:24 +0000164 }
Glenn L McGrath63106462001-02-11 01:40:23 +0000165
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000166 p = xstrdup(dependsstr);
Glenn L McGrath63106462001-02-11 01:40:23 +0000167 while (*p != 0 && *p != '\n') {
168 if (*p != ' ') {
169 if (*p == ',') {
170 *p = 0;
171 dependsvec[++i] = 0;
172 } else {
173 if (dependsvec[i] == 0) {
174 dependsvec[i] = p;
175 }
176 }
177 } else {
178 *p = 0; /* eat the space... */
179 }
180 p++;
181 }
182 *p = 0;
183
184end:
Glenn L McGrathc9005752001-02-10 02:05:24 +0000185 dependsvec[i+1] = 0;
186 return dependsvec;
187}
188
Glenn L McGrath63106462001-02-11 01:40:23 +0000189/* Topological sort algorithm:
190 * ordered is the output list, pkgs is the dependency graph, pkg is
191 * the current node
192 *
193 * recursively add all the adjacent nodes to the ordered list, marking
194 * each one as visited along the way
195 *
196 * yes, this algorithm looks a bit odd when all the params have the
197 * same type :-)
198 */
Glenn L McGrath649968c2001-02-10 14:26:48 +0000199static void depends_sort_visit(package_t **ordered, package_t *pkgs,
200 package_t *pkg)
Glenn L McGrathc9005752001-02-10 02:05:24 +0000201{
Glenn L McGrathc9005752001-02-10 02:05:24 +0000202 unsigned short i;
203
204 /* mark node as processing */
Glenn L McGrathaf8c65d2001-02-10 03:19:51 +0000205 pkg->color = color_grey;
Glenn L McGrathc9005752001-02-10 02:05:24 +0000206
207 /* visit each not-yet-visited node */
208 for (i = 0; i < pkg->requiredcount; i++)
Glenn L McGrathaf8c65d2001-02-10 03:19:51 +0000209 if (pkg->requiredfor[i]->color == color_white)
Glenn L McGrathc9005752001-02-10 02:05:24 +0000210 depends_sort_visit(ordered, pkgs, pkg->requiredfor[i]);
211
212#if 0
213 /* add it to the list */
Eric Andersenb50d7072001-02-15 19:50:11 +0000214 newnode = (struct package_t *)xmalloc(sizeof(struct package_t));
Glenn L McGrathc9005752001-02-10 02:05:24 +0000215 /* make a shallow copy */
216 *newnode = *pkg;
217 newnode->next = *ordered;
218 *ordered = newnode;
219#endif
Glenn L McGrath63106462001-02-11 01:40:23 +0000220
Glenn L McGrathc9005752001-02-10 02:05:24 +0000221 pkg->next = *ordered;
222 *ordered = pkg;
223
224 /* mark node as done */
Glenn L McGrathaf8c65d2001-02-10 03:19:51 +0000225 pkg->color = color_black;
Glenn L McGrathc9005752001-02-10 02:05:24 +0000226}
227
Glenn L McGrath649968c2001-02-10 14:26:48 +0000228static package_t *depends_sort(package_t *pkgs)
Glenn L McGrathc9005752001-02-10 02:05:24 +0000229{
230 /* TODO: it needs to break cycles in the to-be-installed package
231 * graph... */
Glenn L McGrath649968c2001-02-10 14:26:48 +0000232 package_t *ordered = NULL;
233 package_t *pkg;
Glenn L McGrathc9005752001-02-10 02:05:24 +0000234
Glenn L McGrath63106462001-02-11 01:40:23 +0000235 for (pkg = pkgs; pkg != 0; pkg = pkg->next) {
Glenn L McGrathaf8c65d2001-02-10 03:19:51 +0000236 pkg->color = color_white;
Glenn L McGrath63106462001-02-11 01:40:23 +0000237 }
238 for (pkg = pkgs; pkg != 0; pkg = pkg->next) {
239 if (pkg->color == color_white) {
Glenn L McGrathc9005752001-02-10 02:05:24 +0000240 depends_sort_visit(&ordered, pkgs, pkg);
Glenn L McGrath63106462001-02-11 01:40:23 +0000241 }
242 }
Glenn L McGrathc9005752001-02-10 02:05:24 +0000243
244 /* Leaks the old list... return the new one... */
245 return ordered;
246}
247
248
249/* resolve package dependencies --
250 * for each package in the list of packages to be installed, we parse its
251 * dependency info to determine if the dependent packages are either
252 * already installed, or are scheduled to be installed. If both tests fail
253 * than bail.
254 *
255 * The algorithm here is O(n^2*m) where n = number of packages to be
256 * installed and m is the # of dependencies per package. Not a terribly
257 * efficient algorithm, but given that at any one time you are unlikely
258 * to install a very large number of packages it doesn't really matter
259 */
Glenn L McGrath649968c2001-02-10 14:26:48 +0000260static package_t *depends_resolve(package_t *pkgs, void *status)
Glenn L McGrathc9005752001-02-10 02:05:24 +0000261{
Glenn L McGrath649968c2001-02-10 14:26:48 +0000262 package_t *pkg, *chk;
263 package_t dependpkg;
Glenn L McGrathc9005752001-02-10 02:05:24 +0000264 char **dependsvec;
265 int i;
266 void *found;
267
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000268 for (pkg = pkgs; pkg != 0; pkg = pkg->next) {
Glenn L McGrathc9005752001-02-10 02:05:24 +0000269 dependsvec = depends_split(pkg->depends);
270 i = 0;
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000271 while (dependsvec[i] != 0) {
Glenn L McGrathc9005752001-02-10 02:05:24 +0000272 /* Check for dependencies; first look for installed packages */
273 dependpkg.package = dependsvec[i];
274 if ((found = tfind(&dependpkg, &status, package_compare)) == 0 ||
Glenn L McGrath649968c2001-02-10 14:26:48 +0000275 ((chk = *(package_t **)found) &&
Glenn L McGrathaf8c65d2001-02-10 03:19:51 +0000276 (chk->status & (status_flagok | status_statusinstalled)) !=
Glenn L McGrath63106462001-02-11 01:40:23 +0000277 (status_flagok | status_statusinstalled))) {
278
Glenn L McGrathc9005752001-02-10 02:05:24 +0000279 /* if it fails, we look through the list of packages we are going to
280 * install */
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000281 for (chk = pkgs; chk != 0; chk = chk->next) {
Glenn L McGrath63106462001-02-11 01:40:23 +0000282 if (strcmp(chk->package, dependsvec[i]) == 0 || (chk->provides &&
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000283 strncmp(chk->provides, dependsvec[i], strlen(dependsvec[i])) == 0)) {
284 if (chk->requiredcount >= DEPENDSMAX) {
Glenn L McGrath63106462001-02-11 01:40:23 +0000285 fprintf(stderr, "Too many dependencies for %s\n", chk->package);
Glenn L McGrathc9005752001-02-10 02:05:24 +0000286 return 0;
287 }
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000288 if (chk != pkg) {
Glenn L McGrathc9005752001-02-10 02:05:24 +0000289 chk->requiredfor[chk->requiredcount++] = pkg;
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000290 }
Glenn L McGrathc9005752001-02-10 02:05:24 +0000291 break;
292 }
293 }
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000294 if (chk == 0) {
Glenn L McGrathc9005752001-02-10 02:05:24 +0000295 fprintf(stderr, "%s depends on %s, but it is not going to be installed\n", pkg->package, dependsvec[i]);
296 return 0;
297 }
298 }
299 i++;
300 }
301 }
302
303 return depends_sort(pkgs);
304}
305#endif
306
307/* Status file handling routines
308 *
309 * This is a fairly minimalistic implementation. there are two main functions
310 * that are supported:
311 *
312 * 1) reading the entire status file:
313 * the status file is read into memory as a binary-tree, with just the
314 * package and status info preserved
315 *
316 * 2) merging the status file
317 * control info from (new) packages is merged into the status file,
318 * replacing any pre-existing entries. when a merge happens, status info
319 * read using the status_read function is written back to the status file
320 */
Glenn L McGrathc9005752001-02-10 02:05:24 +0000321static unsigned long status_parse(const char *line)
322{
323 char *p;
324 int i, j;
325 unsigned long l = 0;
Glenn L McGrath63106462001-02-11 01:40:23 +0000326
327 for (i = 0; i < 3; i++) {
328 if ((p = strchr(line, ' ')) != NULL) {
329 *p = 0;
330 }
Glenn L McGrathc9005752001-02-10 02:05:24 +0000331 j = 1;
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000332 while (statuswords[i][j] != 0) {
333 if (strcmp(line, statuswords[i][j]) == 0) {
Glenn L McGrathc9005752001-02-10 02:05:24 +0000334 l |= (1 << ((int)statuswords[i][0] + j - 1));
335 break;
336 }
337 j++;
338 }
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000339 /* parse error */
340 if (statuswords[i][j] == 0) {
341 return 0;
342 }
Glenn L McGrathc9005752001-02-10 02:05:24 +0000343 line = p+1;
344 }
Glenn L McGrath63106462001-02-11 01:40:23 +0000345
Glenn L McGrathc9005752001-02-10 02:05:24 +0000346 return l;
347}
348
349static const char *status_print(unsigned long flags)
350{
351 /* this function returns a static buffer... */
352 static char buf[256];
353 int i, j;
354
355 buf[0] = 0;
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000356 for (i = 0; i < 3; i++) {
Glenn L McGrathc9005752001-02-10 02:05:24 +0000357 j = 1;
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000358 while (statuswords[i][j] != 0) {
359 if ((flags & (1 << ((int)statuswords[i][0] + j - 1))) != 0) {
Glenn L McGrathc9005752001-02-10 02:05:24 +0000360 strcat(buf, statuswords[i][j]);
361 if (i < 2) strcat(buf, " ");
362 break;
363 }
364 j++;
365 }
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000366 if (statuswords[i][j] == 0) {
Glenn L McGrathc9005752001-02-10 02:05:24 +0000367 fprintf(stderr, "corrupted status flag!!\n");
368 return NULL;
369 }
370 }
Glenn L McGrath63106462001-02-11 01:40:23 +0000371
Glenn L McGrathc9005752001-02-10 02:05:24 +0000372 return buf;
373}
374
375/*
376 * Read a control file (or a stanza of a status file) and parse it,
377 * filling parsed fields into the package structure
378 */
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000379static int control_read(FILE *file, package_t *p)
Glenn L McGrathc9005752001-02-10 02:05:24 +0000380{
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000381 char *line;
382
383 while ((line = get_line_from_file(file)) != NULL) {
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000384 line[strlen(line) - 1] = '\0';
Glenn L McGrath63106462001-02-11 01:40:23 +0000385
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000386 if (strlen(line) == 0) {
387 break;
388 } else
389 if (strstr(line, "Package: ") == line) {
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000390 p->package = xstrdup(line + 9);
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000391 } else
392 if (strstr(line, "Status: ") == line) {
393 p->status = status_parse(line + 8);
394 } else
395 if (strstr(line, "Depends: ") == line) {
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000396 p->depends = xstrdup(line + 9);
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000397 } else
398 if (strstr(line, "Provides: ") == line) {
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000399 p->provides = xstrdup(line + 10);
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000400 } else
401 if (strstr(line, "Description: ") == line) {
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000402 p->description = xstrdup(line + 13);
Glenn L McGrathc9005752001-02-10 02:05:24 +0000403 /* This is specific to the Debian Installer. Ifdef? */
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000404 } else
405 if (strstr(line, "installer-menu-item: ") == line) {
406 p->installer_menu_item = atoi(line + 21);
Glenn L McGrathc9005752001-02-10 02:05:24 +0000407 }
408 /* TODO: localized descriptions */
409 }
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000410 free(line);
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000411 return EXIT_SUCCESS;
Glenn L McGrathc9005752001-02-10 02:05:24 +0000412}
413
Glenn L McGrath649968c2001-02-10 14:26:48 +0000414static void *status_read(void)
Glenn L McGrathc9005752001-02-10 02:05:24 +0000415{
416 FILE *f;
417 void *status = 0;
Glenn L McGrath649968c2001-02-10 14:26:48 +0000418 package_t *m = 0, *p = 0, *t = 0;
Glenn L McGrathc9005752001-02-10 02:05:24 +0000419
Glenn L McGrath63106462001-02-11 01:40:23 +0000420 if ((f = fopen(statusfile, "r")) == NULL) {
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000421 perror_msg(statusfile);
Glenn L McGrathc9005752001-02-10 02:05:24 +0000422 return 0;
423 }
Glenn L McGrath63106462001-02-11 01:40:23 +0000424
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000425 if (getenv(udpkg_quiet) == NULL) {
Glenn L McGrathc9005752001-02-10 02:05:24 +0000426 printf("(Reading database...)\n");
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000427 }
Glenn L McGrath63106462001-02-11 01:40:23 +0000428
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000429 while (!feof(f)) {
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000430 m = (package_t *)xcalloc(1, sizeof(package_t));
Glenn L McGrathc9005752001-02-10 02:05:24 +0000431 control_read(f, m);
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000432 if (m->package) {
Glenn L McGrathc9005752001-02-10 02:05:24 +0000433 /*
434 * If there is an item in the tree by this name,
435 * it must be a virtual package; insert real
436 * package in preference.
437 */
438 tdelete(m, &status, package_compare);
439 tsearch(m, &status, package_compare);
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000440 if (m->provides) {
Glenn L McGrathc9005752001-02-10 02:05:24 +0000441 /*
442 * A "Provides" triggers the insertion
443 * of a pseudo package into the status
444 * binary-tree.
445 */
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000446 p = (package_t *)xcalloc(1, sizeof(package_t));
447 p->package = xstrdup(m->provides);
Glenn L McGrathc9005752001-02-10 02:05:24 +0000448
Glenn L McGrath649968c2001-02-10 14:26:48 +0000449 t = *(package_t **)tsearch(p, &status, package_compare);
Glenn L McGrath63106462001-02-11 01:40:23 +0000450 if (t != p) {
Glenn L McGrathc9005752001-02-10 02:05:24 +0000451 free(p->package);
452 free(p);
453 }
454 else {
455 /*
456 * Pseudo package status is the
457 * same as the status of the
458 * package providing it
459 * FIXME: (not quite right, if 2
460 * packages of different statuses
461 * provide it).
462 */
463 t->status = m->status;
464 }
465 }
466 }
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000467 else {
Glenn L McGrathc9005752001-02-10 02:05:24 +0000468 free(m);
469 }
470 }
471 fclose(f);
472 return status;
473}
474
Glenn L McGrath649968c2001-02-10 14:26:48 +0000475static int status_merge(void *status, package_t *pkgs)
Glenn L McGrathc9005752001-02-10 02:05:24 +0000476{
477 FILE *fin, *fout;
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000478 char *line = NULL;
Glenn L McGrath649968c2001-02-10 14:26:48 +0000479 package_t *pkg = 0, *statpkg = 0;
480 package_t locpkg;
Glenn L McGrathc9005752001-02-10 02:05:24 +0000481
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000482 if ((fout = wfopen(new_statusfile, "w")) == NULL) {
Glenn L McGrathc9005752001-02-10 02:05:24 +0000483 return 0;
484 }
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000485 if (getenv(udpkg_quiet) == NULL) {
Glenn L McGrathc9005752001-02-10 02:05:24 +0000486 printf("(Updating database...)\n");
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000487 }
Glenn L McGrath13e9c7a2001-04-08 07:18:08 +0000488 /*
489 * Dont use wfopen here, handle errors ourself
490 */
491 if ((fin = fopen(statusfile, "r")) != NULL) {
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000492 while (((line = get_line_from_file(fin)) != NULL) && !feof(fin)) {
493 line[strlen(line) - 1] = '\0'; /* trim newline */
494 /* If we see a package header, find out if it's a package
495 * that we have processed. if so, we skip that block for
496 * now (write it at the end).
497 *
498 * we also look at packages in the status cache and update
499 * their status fields
Glenn L McGrath13e9c7a2001-04-08 07:18:08 +0000500 */
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000501 if (strstr(line, "Package: ") == line) {
502 for (pkg = pkgs; pkg != 0 && strcmp(line + 9,
503 pkg->package) != 0; pkg = pkg->next) ;
Glenn L McGrath63106462001-02-11 01:40:23 +0000504
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000505 locpkg.package = line + 9;
506 statpkg = tfind(&locpkg, &status, package_compare);
Glenn L McGrath13e9c7a2001-04-08 07:18:08 +0000507
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000508 /* note: statpkg should be non-zero, unless the status
509 * file was changed while we are processing (no locking
510 * is currently done...
511 */
512 if (statpkg != 0) {
513 statpkg = *(package_t **)statpkg;
514 }
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000515 }
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000516 if (pkg != 0) {
517 continue;
518 }
519 if (strstr(line, "Status: ") == line && statpkg != 0) {
520 snprintf(line, sizeof(line), "Status: %s",
521 status_print(statpkg->status));
522 }
523 fputs(line, fout);
524 fputc('\n', fout);
Glenn L McGrathc9005752001-02-10 02:05:24 +0000525 }
Glenn L McGrath13e9c7a2001-04-08 07:18:08 +0000526 fclose(fin);
Glenn L McGrathc9005752001-02-10 02:05:24 +0000527 }
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000528 free(line);
Glenn L McGrathc9005752001-02-10 02:05:24 +0000529
530 // Print out packages we processed.
531 for (pkg = pkgs; pkg != 0; pkg = pkg->next) {
532 fprintf(fout, "Package: %s\nStatus: %s\n",
533 pkg->package, status_print(pkg->status));
534 if (pkg->depends)
535 fprintf(fout, "Depends: %s\n", pkg->depends);
536 if (pkg->provides)
537 fprintf(fout, "Provides: %s\n", pkg->provides);
538 if (pkg->installer_menu_item)
539 fprintf(fout, "installer-menu-item: %i\n", pkg->installer_menu_item);
540 if (pkg->description)
541 fprintf(fout, "Description: %s\n", pkg->description);
542 fputc('\n', fout);
543 }
Glenn L McGrathc9005752001-02-10 02:05:24 +0000544 fclose(fout);
545
Glenn L McGrath13e9c7a2001-04-08 07:18:08 +0000546 /*
547 * Its ok if renaming statusfile fails becasue it doesnt exist
548 */
549 if (rename(statusfile, bak_statusfile) == -1) {
550 struct stat stat_buf;
551 error_msg("Couldnt create backup status file");
552 if (stat(statusfile, &stat_buf) == 0) {
553 return(EXIT_FAILURE);
554 }
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000555 }
Glenn L McGrath63106462001-02-11 01:40:23 +0000556
Glenn L McGrath13e9c7a2001-04-08 07:18:08 +0000557 if (rename(new_statusfile, statusfile) == -1) {
558 error_msg("Couldnt create status file");
559 return(EXIT_FAILURE);
560 }
561 return(EXIT_SUCCESS);
Glenn L McGrathc9005752001-02-10 02:05:24 +0000562}
563
Glenn L McGrathc9005752001-02-10 02:05:24 +0000564static int is_file(const char *fn)
565{
566 struct stat statbuf;
567
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000568 if (stat(fn, &statbuf) < 0) {
569 return 0;
570 }
Glenn L McGrathc9005752001-02-10 02:05:24 +0000571 return S_ISREG(statbuf.st_mode);
572}
573
Glenn L McGrath649968c2001-02-10 14:26:48 +0000574static int dpkg_doconfigure(package_t *pkg)
Glenn L McGrathc9005752001-02-10 02:05:24 +0000575{
576 int r;
577 char postinst[1024];
578 char buf[1024];
Glenn L McGrath63106462001-02-11 01:40:23 +0000579
Glenn L McGrathc9005752001-02-10 02:05:24 +0000580 DPRINTF("Configuring %s\n", pkg->package);
Glenn L McGrathaf8c65d2001-02-10 03:19:51 +0000581 pkg->status &= status_statusmask;
Glenn L McGrath510f0dd2001-02-10 14:53:08 +0000582 snprintf(postinst, sizeof(postinst), "%s%s.postinst", infodir, pkg->package);
Glenn L McGrath63106462001-02-11 01:40:23 +0000583
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000584 if (is_file(postinst)) {
Glenn L McGrathc9005752001-02-10 02:05:24 +0000585 snprintf(buf, sizeof(buf), "%s configure", postinst);
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000586 if ((r = do_system(buf)) != 0) {
Glenn L McGrathc9005752001-02-10 02:05:24 +0000587 fprintf(stderr, "postinst exited with status %d\n", r);
Glenn L McGrathaf8c65d2001-02-10 03:19:51 +0000588 pkg->status |= status_statushalfconfigured;
Glenn L McGrathc9005752001-02-10 02:05:24 +0000589 return 1;
590 }
591 }
Glenn L McGrathaf8c65d2001-02-10 03:19:51 +0000592 pkg->status |= status_statusinstalled;
Glenn L McGrathc9005752001-02-10 02:05:24 +0000593
594 return 0;
595}
596
Glenn L McGrath649968c2001-02-10 14:26:48 +0000597static int dpkg_dounpack(package_t *pkg)
Glenn L McGrathc9005752001-02-10 02:05:24 +0000598{
Glenn L McGrath63106462001-02-11 01:40:23 +0000599 int r = 0, i;
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000600 char *cwd;
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000601 char *src_file = NULL;
602 char *dst_file = NULL;
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000603// char *lst_file = NULL;
604 char *adminscripts[] = { "prerm", "postrm", "preinst", "postinst",
605 "conffiles", "md5sums", "shlibs", "templates" };
Glenn L McGrathc9005752001-02-10 02:05:24 +0000606
607 DPRINTF("Unpacking %s\n", pkg->package);
608
609 cwd = getcwd(0, 0);
610 chdir("/");
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000611 deb_extract(dpkg_deb_extract, "/", pkg->file);
612
Glenn L McGrath63106462001-02-11 01:40:23 +0000613 /* Installs the package scripts into the info directory */
614 for (i = 0; i < sizeof(adminscripts) / sizeof(adminscripts[0]); i++) {
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000615 struct stat src_stat_buf;
616 int src_fd = 0, dst_fd = 0;
617
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000618 /* The full path of the current location of the admin file */
619 src_file = xrealloc(src_file, strlen(dpkgcidir) + strlen(pkg->package) + strlen(adminscripts[i]) + 1);
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000620 sprintf(src_file, "%s%s/%s", dpkgcidir, pkg->package, adminscripts[i]);
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000621
622 /* the full path of where we want the file to be copied to */
623 dst_file = xrealloc(dst_file, strlen(infodir) + strlen(pkg->package) + strlen(adminscripts[i]) + 1);
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000624 sprintf(dst_file, "%s%s.%s", infodir, pkg->package, adminscripts[i]);
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000625
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000626 /*
627 * copy admin file to permanent home
628 * NOTE: Maybe merge this behaviour into libb/copy_file.c
629 */
630 if (lstat(src_file, &src_stat_buf) == 0) {
631 if ((src_fd = open(src_file, O_RDONLY)) != -1) {
632 if ((dst_fd = open(dst_file, O_WRONLY | O_CREAT, 0644)) == -1) {
633 perror_msg("Opening %s", dst_file);
634 }
635 copy_file_chunk(src_fd, dst_fd, src_stat_buf.st_size);
636 close(src_fd);
637 close(dst_fd);
638 } else {
639 error_msg("couldnt open [%s]\n", src_file);
640 }
Glenn L McGrath63106462001-02-11 01:40:23 +0000641 }
Glenn L McGrath63106462001-02-11 01:40:23 +0000642 }
643
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000644 /*
645 * create the list file
646 * FIXME: currently this dumps the lst to stdout instead of a file
647 */
648/* lst_file = (char *) xmalloc(strlen(infodir) + strlen(pkg->package) + 6);
649 strcpy(lst_file, infodir);
650 strcat(lst_file, pkg->package);
651 strcat(lst_file, ".list");
652 deb_extract(dpkg_deb_list, NULL, pkg->file);
653*/
654
Glenn L McGrath63106462001-02-11 01:40:23 +0000655 pkg->status &= status_wantmask;
656 pkg->status |= status_wantinstall;
657 pkg->status &= status_flagmask;
658 pkg->status |= status_flagok;
659 pkg->status &= status_statusmask;
660
661 if (r == 0) {
662 pkg->status |= status_statusunpacked;
663 } else {
664 pkg->status |= status_statushalfinstalled;
665 }
Glenn L McGrathc9005752001-02-10 02:05:24 +0000666 chdir(cwd);
667 return r;
668}
669
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000670/*
671 * Extract and parse the control.tar.gz from the specified package
672 */
Glenn L McGrath649968c2001-02-10 14:26:48 +0000673static int dpkg_unpackcontrol(package_t *pkg)
Glenn L McGrathc9005752001-02-10 02:05:24 +0000674{
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000675 char *tmp_name;
676 FILE *file;
677 int length;
Glenn L McGrathc9005752001-02-10 02:05:24 +0000678
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000679 /* clean the temp directory (dpkgcidir) be recreating it */
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000680 remove_dir(dpkgcidir);
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000681 if (mkdir(dpkgcidir, S_IRWXU) != 0) {
682 perror("mkdir");
683 return EXIT_FAILURE;
Glenn L McGrath63106462001-02-11 01:40:23 +0000684 }
Glenn L McGrathc9005752001-02-10 02:05:24 +0000685
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000686 /*
687 * Get the package name from the file name,
688 * first remove the directories
689 */
690 if ((tmp_name = strrchr(pkg->file, '/')) == NULL) {
691 tmp_name = pkg->file;
692 } else {
693 tmp_name++;
Glenn L McGrathc9005752001-02-10 02:05:24 +0000694 }
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000695 /* now remove trailing version numbers etc */
696 length = strcspn(tmp_name, "_.");
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000697 pkg->package = (char *) xcalloc(1, length + 1);
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000698 /* store the package name */
699 strncpy(pkg->package, tmp_name, length);
Glenn L McGrath63106462001-02-11 01:40:23 +0000700
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000701 /* work out the full extraction path */
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000702 tmp_name = (char *) xcalloc(1, strlen(dpkgcidir) + strlen(pkg->package) + 9);
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000703 strcpy(tmp_name, dpkgcidir);
704 strcat(tmp_name, pkg->package);
705
706 /* extract control.tar.gz to the full extraction path */
707 deb_extract(dpkg_deb_control, tmp_name, pkg->file);
708
709 /* parse the extracted control file */
710 strcat(tmp_name, "/control");
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000711 if ((file = wfopen(tmp_name, "r")) == NULL) {
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000712 return EXIT_FAILURE;
713 }
714 if (control_read(file, pkg) == EXIT_FAILURE) {
715 return EXIT_FAILURE;
716 }
717
718 return EXIT_SUCCESS;
Glenn L McGrathc9005752001-02-10 02:05:24 +0000719}
720
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000721static int dpkg_unpack(package_t *pkgs, void *status)
Glenn L McGrathc9005752001-02-10 02:05:24 +0000722{
723 int r = 0;
Glenn L McGrath649968c2001-02-10 14:26:48 +0000724 package_t *pkg;
Glenn L McGrathc9005752001-02-10 02:05:24 +0000725
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000726 for (pkg = pkgs; pkg != 0; pkg = pkg->next) {
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000727 if (dpkg_unpackcontrol(pkg) == EXIT_FAILURE) {
728 return EXIT_FAILURE;
729 }
730 if ((r = dpkg_dounpack(pkg)) != 0 ) {
731 break;
732 }
Glenn L McGrathc9005752001-02-10 02:05:24 +0000733 }
734 status_merge(status, pkgs);
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000735 remove_dir(dpkgcidir);
Glenn L McGrath63106462001-02-11 01:40:23 +0000736
Glenn L McGrathc9005752001-02-10 02:05:24 +0000737 return r;
738}
739
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000740static int dpkg_configure(package_t *pkgs, void *status)
Glenn L McGrathc9005752001-02-10 02:05:24 +0000741{
742 int r = 0;
743 void *found;
Glenn L McGrath649968c2001-02-10 14:26:48 +0000744 package_t *pkg;
Glenn L McGrath63106462001-02-11 01:40:23 +0000745
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000746 for (pkg = pkgs; pkg != 0 && r == 0; pkg = pkg->next) {
Glenn L McGrathc9005752001-02-10 02:05:24 +0000747 found = tfind(pkg, &status, package_compare);
Glenn L McGrath63106462001-02-11 01:40:23 +0000748
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000749 if (found == 0) {
Glenn L McGrathc9005752001-02-10 02:05:24 +0000750 fprintf(stderr, "Trying to configure %s, but it is not installed\n", pkg->package);
751 r = 1;
Glenn L McGrath63106462001-02-11 01:40:23 +0000752 }
753 /* configure the package listed in the status file;
754 * not pkg, as we have info only for the latter
755 */
756 else {
Glenn L McGrath649968c2001-02-10 14:26:48 +0000757 r = dpkg_doconfigure(*(package_t **)found);
Glenn L McGrathc9005752001-02-10 02:05:24 +0000758 }
759 }
760 status_merge(status, 0);
Glenn L McGrath63106462001-02-11 01:40:23 +0000761
Glenn L McGrathc9005752001-02-10 02:05:24 +0000762 return r;
763}
764
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000765static int dpkg_install(package_t *pkgs, void *status)
Glenn L McGrathc9005752001-02-10 02:05:24 +0000766{
Glenn L McGrath649968c2001-02-10 14:26:48 +0000767 package_t *p, *ordered = 0;
Glenn L McGrath63106462001-02-11 01:40:23 +0000768
Glenn L McGrathc9005752001-02-10 02:05:24 +0000769 /* Stage 1: parse all the control information */
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000770 for (p = pkgs; p != 0; p = p->next) {
771 if (dpkg_unpackcontrol(p) == EXIT_FAILURE) {
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000772 return(EXIT_FAILURE);
Glenn L McGrathc9005752001-02-10 02:05:24 +0000773 }
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000774 }
775
Glenn L McGrathc9005752001-02-10 02:05:24 +0000776 /* Stage 2: resolve dependencies */
777#ifdef DODEPENDS
778 ordered = depends_resolve(pkgs, status);
779#else
780 ordered = pkgs;
781#endif
782
783 /* Stage 3: install */
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000784 for (p = ordered; p != 0; p = p->next) {
Glenn L McGrathaf8c65d2001-02-10 03:19:51 +0000785 p->status &= status_wantmask;
786 p->status |= status_wantinstall;
Glenn L McGrathc9005752001-02-10 02:05:24 +0000787
788 /* for now the flag is always set to ok... this is probably
789 * not what we want
790 */
Glenn L McGrathaf8c65d2001-02-10 03:19:51 +0000791 p->status &= status_flagmask;
792 p->status |= status_flagok;
Glenn L McGrathc9005752001-02-10 02:05:24 +0000793
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000794 DPRINTF("Installing %s\n", p->package);
795 if (dpkg_dounpack(p) != 0) {
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000796 perror_msg(p->file);
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000797 }
798 if (dpkg_doconfigure(p) != 0) {
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000799 perror_msg(p->file);
Glenn L McGrathc9005752001-02-10 02:05:24 +0000800 }
801 }
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000802
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000803 if (ordered != 0) {
Glenn L McGrathc9005752001-02-10 02:05:24 +0000804 status_merge(status, pkgs);
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000805 }
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000806 remove_dir(dpkgcidir);
Glenn L McGrath63106462001-02-11 01:40:23 +0000807
Glenn L McGrathc9005752001-02-10 02:05:24 +0000808 return 0;
809}
810
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000811/*
812 * Not implemented yet
813 *
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000814static int dpkg_remove(package_t *pkgs, void *status)
Glenn L McGrathc9005752001-02-10 02:05:24 +0000815{
Glenn L McGrath649968c2001-02-10 14:26:48 +0000816 package_t *p;
Glenn L McGrath63106462001-02-11 01:40:23 +0000817
Glenn L McGrathc9005752001-02-10 02:05:24 +0000818 for (p = pkgs; p != 0; p = p->next)
819 {
820 }
821 status_merge(status, 0);
Glenn L McGrath63106462001-02-11 01:40:23 +0000822
Glenn L McGrathc9005752001-02-10 02:05:24 +0000823 return 0;
824}
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000825*/
Glenn L McGrathc9005752001-02-10 02:05:24 +0000826
Glenn L McGrath649968c2001-02-10 14:26:48 +0000827extern int dpkg_main(int argc, char **argv)
Glenn L McGrathc9005752001-02-10 02:05:24 +0000828{
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000829 const int arg_install = 1;
830 const int arg_unpack = 2;
831 const int arg_configure = 4;
832
Glenn L McGrath649968c2001-02-10 14:26:48 +0000833 package_t *p, *packages = NULL;
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000834 void *status = NULL;
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000835 char opt = 0;
836 int optflag = 0;
Glenn L McGrath63106462001-02-11 01:40:23 +0000837
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000838 while ((opt = getopt(argc, argv, "iruc")) != -1) {
839 switch (opt) {
840 case 'i':
841 optflag |= arg_install;
842 break;
843 case 'u':
844 optflag |= arg_unpack;
845 break;
846 case 'c':
847 optflag |= arg_configure;
848 break;
849 default:
850 show_usage();
851 }
Glenn L McGrathc9005752001-02-10 02:05:24 +0000852 }
Glenn L McGrath63106462001-02-11 01:40:23 +0000853
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000854 while (optind < argc) {
855 p = (package_t *) xcalloc(1, sizeof(package_t));
856 if (optflag & arg_configure) {
857 p->package = xstrdup(argv[optind]);
858 } else {
859 p->file = xstrdup(argv[optind]);
860 }
861 p->next = packages;
862 packages = p;
863
864 optind++;
865 }
866
867 create_path(dpkgcidir, 0755);
868 create_path(infodir, 0755);
869
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000870 status = status_read();
871
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000872 if (optflag & arg_install) {
873 return dpkg_install(packages, status);
Glenn L McGrathc9005752001-02-10 02:05:24 +0000874 }
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000875 else if (optflag & arg_unpack) {
876 return dpkg_unpack(packages, status);
877 }
878 else if (optflag & arg_configure) {
879 return dpkg_configure(packages, status);
880 }
881 return(EXIT_FAILURE);
Eric Andersen67991cf2001-02-14 21:23:06 +0000882}