blob: 55d97adda0590ffe43dfd13349119c0c6cbd680b [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? */
Eric Andersene5dfced2001-04-09 22:48:12 +000023//#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 */
Glenn L McGrathd22e5602001-04-11 02:12:08 +000034
Glenn L McGrath3af1f882001-02-12 11:33:09 +000035static 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 McGrath305fdfa2001-04-08 13:27:39 +000051//static const int status_want_unknown = 1;
52static const int status_want_install = 2;
53//static const int status_want_hold = 3;
54//static const int status_want_deinstall = 4;
55//static const int status_want_purge = 5;
Glenn L McGrathc9005752001-02-10 02:05:24 +000056
Glenn L McGrath305fdfa2001-04-08 13:27:39 +000057static const int status_flag_ok = 1;
58//static const int status_flag_reinstreq = 2;
59//static const int status_flag_hold = 3;
60//static const int status_flag_holdreinstreq = 4;
Glenn L McGrathc9005752001-02-10 02:05:24 +000061
Glenn L McGrath305fdfa2001-04-08 13:27:39 +000062//static const int status_statusnoninstalled = 1;
63static const int status_status_unpacked = 2;
64static const int status_status_halfconfigured = 3;
65static const int status_status_installed = 4;
66static const int status_status_halfinstalled = 5;
67//static const int status_statusconfigfiles = 6;
68//static const int status_statuspostinstfailed = 7;
69//static const int status_statusremovalfailed = 8;
Glenn L McGrathc9005752001-02-10 02:05:24 +000070
Glenn L McGrath305fdfa2001-04-08 13:27:39 +000071static const char *status_words_want[] = { "unknown", "install", "hold", "deinstall", "purge", 0 };
72static const char *status_words_flag[] = { "ok", "reinstreq", "hold", "hold-reinstreq", 0 };
73static const char *status_words_status[] = { "not-installed", "unpacked", "half-configured", "installed",
74 "half-installed", "config-files", "post-inst-failed", "removal-failed", 0 };
Glenn L McGrathaf8c65d2001-02-10 03:19:51 +000075
Eric Andersen3e6ff902001-03-09 21:24:12 +000076static const int color_white = 0;
77static const int color_grey = 1;
78static const int color_black = 2;
Glenn L McGrathc9005752001-02-10 02:05:24 +000079
80/* data structures */
Glenn L McGrath649968c2001-02-10 14:26:48 +000081typedef struct package_s {
Glenn L McGrathc9005752001-02-10 02:05:24 +000082 char *file;
83 char *package;
84 char *version;
85 char *depends;
86 char *provides;
87 char *description;
88 int installer_menu_item;
Glenn L McGrath305fdfa2001-04-08 13:27:39 +000089 unsigned char status_want;
90 unsigned char status_flag;
91 unsigned char status_status;
Glenn L McGrathc9005752001-02-10 02:05:24 +000092 char color; /* for topo-sort */
Glenn L McGrath649968c2001-02-10 14:26:48 +000093 struct package_s *requiredfor[DEPENDSMAX];
Glenn L McGrathc9005752001-02-10 02:05:24 +000094 unsigned short requiredcount;
Glenn L McGrath649968c2001-02-10 14:26:48 +000095 struct package_s *next;
96} package_t;
Glenn L McGrathc9005752001-02-10 02:05:24 +000097
Glenn L McGrath63106462001-02-11 01:40:23 +000098#ifdef DODEBUG
99static int do_system(const char *cmd)
100{
101 DPRINTF("cmd is %s\n", cmd);
102 return system(cmd);
103}
104#else
105#define do_system(cmd) system(cmd)
106#endif
107
Glenn L McGrath649968c2001-02-10 14:26:48 +0000108static int package_compare(const void *p1, const void *p2)
109{
110 return strcmp(((package_t *)p1)->package,
111 ((package_t *)p2)->package);
112}
Glenn L McGrathc9005752001-02-10 02:05:24 +0000113
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000114/*
115 * NOTE: this was handled by a "rm -rf" shell command
116 * Maybe theis behaviour should be integrated into the rm applet
117 * (i dont appreciate the rm applets recursive action fn)-bug1
118 */
119static int remove_dir(const char *dirname)
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000120{
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000121 struct dirent *fp;
122 DIR *dp = opendir(dirname);
123 while ((fp = readdir(dp)) != NULL) {
124 struct stat statbuf;
125 char *filename;
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000126
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000127 filename = (char *) xcalloc(1, strlen(dirname) + strlen(fp->d_name) + 2);
128 strcpy(filename, dirname);
129 strcat(filename, fp->d_name);
130 lstat(filename, &statbuf);
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000131
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000132 if ((strcmp(fp->d_name, ".") != 0) && (strcmp(fp->d_name, "..") != 0)) {
133 if (S_ISDIR(statbuf.st_mode)) {
134 remove_dir(strcat(filename, "/"));
135 }
136 else if (remove(filename) == -1) {
137 perror_msg(filename);
138 }
139 }
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000140 }
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000141 remove(dirname);
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000142 return EXIT_SUCCESS;
143}
144
Glenn L McGrathc9005752001-02-10 02:05:24 +0000145#ifdef DODEPENDS
146#include <ctype.h>
147
148static char **depends_split(const char *dependsstr)
149{
150 static char *dependsvec[DEPENDSMAX];
151 char *p;
152 int i = 0;
153
154 dependsvec[0] = 0;
Glenn L McGrath63106462001-02-11 01:40:23 +0000155 if (dependsstr == 0) {
156 goto end;
Glenn L McGrathc9005752001-02-10 02:05:24 +0000157 }
Glenn L McGrath63106462001-02-11 01:40:23 +0000158
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000159 p = xstrdup(dependsstr);
Glenn L McGrath63106462001-02-11 01:40:23 +0000160 while (*p != 0 && *p != '\n') {
161 if (*p != ' ') {
162 if (*p == ',') {
163 *p = 0;
164 dependsvec[++i] = 0;
165 } else {
166 if (dependsvec[i] == 0) {
167 dependsvec[i] = p;
168 }
169 }
170 } else {
171 *p = 0; /* eat the space... */
172 }
173 p++;
174 }
175 *p = 0;
176
177end:
Glenn L McGrathc9005752001-02-10 02:05:24 +0000178 dependsvec[i+1] = 0;
179 return dependsvec;
180}
181
Glenn L McGrath63106462001-02-11 01:40:23 +0000182/* Topological sort algorithm:
183 * ordered is the output list, pkgs is the dependency graph, pkg is
184 * the current node
185 *
186 * recursively add all the adjacent nodes to the ordered list, marking
187 * each one as visited along the way
188 *
189 * yes, this algorithm looks a bit odd when all the params have the
190 * same type :-)
191 */
Glenn L McGrath649968c2001-02-10 14:26:48 +0000192static void depends_sort_visit(package_t **ordered, package_t *pkgs,
193 package_t *pkg)
Glenn L McGrathc9005752001-02-10 02:05:24 +0000194{
Glenn L McGrathc9005752001-02-10 02:05:24 +0000195 unsigned short i;
196
197 /* mark node as processing */
Glenn L McGrathaf8c65d2001-02-10 03:19:51 +0000198 pkg->color = color_grey;
Glenn L McGrathc9005752001-02-10 02:05:24 +0000199
200 /* visit each not-yet-visited node */
201 for (i = 0; i < pkg->requiredcount; i++)
Glenn L McGrathaf8c65d2001-02-10 03:19:51 +0000202 if (pkg->requiredfor[i]->color == color_white)
Glenn L McGrathc9005752001-02-10 02:05:24 +0000203 depends_sort_visit(ordered, pkgs, pkg->requiredfor[i]);
204
205#if 0
206 /* add it to the list */
Eric Andersenb50d7072001-02-15 19:50:11 +0000207 newnode = (struct package_t *)xmalloc(sizeof(struct package_t));
Glenn L McGrathc9005752001-02-10 02:05:24 +0000208 /* make a shallow copy */
209 *newnode = *pkg;
210 newnode->next = *ordered;
211 *ordered = newnode;
212#endif
Glenn L McGrath63106462001-02-11 01:40:23 +0000213
Glenn L McGrathc9005752001-02-10 02:05:24 +0000214 pkg->next = *ordered;
215 *ordered = pkg;
216
217 /* mark node as done */
Glenn L McGrathaf8c65d2001-02-10 03:19:51 +0000218 pkg->color = color_black;
Glenn L McGrathc9005752001-02-10 02:05:24 +0000219}
220
Glenn L McGrath649968c2001-02-10 14:26:48 +0000221static package_t *depends_sort(package_t *pkgs)
Glenn L McGrathc9005752001-02-10 02:05:24 +0000222{
223 /* TODO: it needs to break cycles in the to-be-installed package
224 * graph... */
Glenn L McGrath649968c2001-02-10 14:26:48 +0000225 package_t *ordered = NULL;
226 package_t *pkg;
Glenn L McGrathc9005752001-02-10 02:05:24 +0000227
Glenn L McGrath63106462001-02-11 01:40:23 +0000228 for (pkg = pkgs; pkg != 0; pkg = pkg->next) {
Glenn L McGrathaf8c65d2001-02-10 03:19:51 +0000229 pkg->color = color_white;
Glenn L McGrath63106462001-02-11 01:40:23 +0000230 }
231 for (pkg = pkgs; pkg != 0; pkg = pkg->next) {
232 if (pkg->color == color_white) {
Glenn L McGrathc9005752001-02-10 02:05:24 +0000233 depends_sort_visit(&ordered, pkgs, pkg);
Glenn L McGrath63106462001-02-11 01:40:23 +0000234 }
235 }
Glenn L McGrathc9005752001-02-10 02:05:24 +0000236
237 /* Leaks the old list... return the new one... */
238 return ordered;
239}
240
241
242/* resolve package dependencies --
243 * for each package in the list of packages to be installed, we parse its
244 * dependency info to determine if the dependent packages are either
245 * already installed, or are scheduled to be installed. If both tests fail
246 * than bail.
247 *
248 * The algorithm here is O(n^2*m) where n = number of packages to be
249 * installed and m is the # of dependencies per package. Not a terribly
250 * efficient algorithm, but given that at any one time you are unlikely
251 * to install a very large number of packages it doesn't really matter
252 */
Glenn L McGrath649968c2001-02-10 14:26:48 +0000253static package_t *depends_resolve(package_t *pkgs, void *status)
Glenn L McGrathc9005752001-02-10 02:05:24 +0000254{
Glenn L McGrath649968c2001-02-10 14:26:48 +0000255 package_t *pkg, *chk;
256 package_t dependpkg;
Glenn L McGrathc9005752001-02-10 02:05:24 +0000257 char **dependsvec;
258 int i;
259 void *found;
260
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000261 for (pkg = pkgs; pkg != 0; pkg = pkg->next) {
Glenn L McGrathc9005752001-02-10 02:05:24 +0000262 dependsvec = depends_split(pkg->depends);
263 i = 0;
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000264 while (dependsvec[i] != 0) {
Glenn L McGrathc9005752001-02-10 02:05:24 +0000265 /* Check for dependencies; first look for installed packages */
266 dependpkg.package = dependsvec[i];
Glenn L McGrath305fdfa2001-04-08 13:27:39 +0000267 if (((found = tfind(&dependpkg, &status, package_compare)) == 0) ||
268 ((chk = *(package_t **)found) && (chk->status_flag & status_flag_ok) &&
269 (chk->status_status & status_status_installed))) {
Glenn L McGrath63106462001-02-11 01:40:23 +0000270
Glenn L McGrathc9005752001-02-10 02:05:24 +0000271 /* if it fails, we look through the list of packages we are going to
272 * install */
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000273 for (chk = pkgs; chk != 0; chk = chk->next) {
Glenn L McGrath63106462001-02-11 01:40:23 +0000274 if (strcmp(chk->package, dependsvec[i]) == 0 || (chk->provides &&
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000275 strncmp(chk->provides, dependsvec[i], strlen(dependsvec[i])) == 0)) {
276 if (chk->requiredcount >= DEPENDSMAX) {
Eric Andersene5dfced2001-04-09 22:48:12 +0000277 error_msg("Too many dependencies for %s", chk->package);
Glenn L McGrathc9005752001-02-10 02:05:24 +0000278 return 0;
279 }
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000280 if (chk != pkg) {
Glenn L McGrathc9005752001-02-10 02:05:24 +0000281 chk->requiredfor[chk->requiredcount++] = pkg;
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000282 }
Glenn L McGrathc9005752001-02-10 02:05:24 +0000283 break;
284 }
285 }
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000286 if (chk == 0) {
Eric Andersene5dfced2001-04-09 22:48:12 +0000287 error_msg("%s depends on %s, but it is not going to be installed", pkg->package, dependsvec[i]);
Glenn L McGrathc9005752001-02-10 02:05:24 +0000288 return 0;
289 }
290 }
291 i++;
292 }
293 }
294
295 return depends_sort(pkgs);
296}
297#endif
298
299/* Status file handling routines
300 *
301 * This is a fairly minimalistic implementation. there are two main functions
302 * that are supported:
303 *
304 * 1) reading the entire status file:
305 * the status file is read into memory as a binary-tree, with just the
306 * package and status info preserved
307 *
308 * 2) merging the status file
309 * control info from (new) packages is merged into the status file,
310 * replacing any pre-existing entries. when a merge happens, status info
311 * read using the status_read function is written back to the status file
312 */
Glenn L McGrath305fdfa2001-04-08 13:27:39 +0000313static unsigned char status_parse(const char *line, const char **status_words)
Glenn L McGrathc9005752001-02-10 02:05:24 +0000314{
Glenn L McGrath305fdfa2001-04-08 13:27:39 +0000315 unsigned char status_num;
316 int i = 0;
Glenn L McGrath63106462001-02-11 01:40:23 +0000317
Glenn L McGrath305fdfa2001-04-08 13:27:39 +0000318 while (status_words[i] != 0) {
319 if (strncmp(line, status_words[i], strlen(status_words[i])) == 0) {
320 status_num = (char)i;
321 return(status_num);
Glenn L McGrath63106462001-02-11 01:40:23 +0000322 }
Glenn L McGrath305fdfa2001-04-08 13:27:39 +0000323 i++;
Glenn L McGrathc9005752001-02-10 02:05:24 +0000324 }
Glenn L McGrath305fdfa2001-04-08 13:27:39 +0000325 /* parse error */
326 error_msg("Invalid status word");
327 return(0);
Glenn L McGrathc9005752001-02-10 02:05:24 +0000328}
329
330/*
331 * Read a control file (or a stanza of a status file) and parse it,
332 * filling parsed fields into the package structure
333 */
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000334static int control_read(FILE *file, package_t *p)
Glenn L McGrathc9005752001-02-10 02:05:24 +0000335{
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000336 char *line;
337
338 while ((line = get_line_from_file(file)) != NULL) {
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000339 line[strlen(line) - 1] = '\0';
Glenn L McGrath63106462001-02-11 01:40:23 +0000340
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000341 if (strlen(line) == 0) {
342 break;
Glenn L McGrath305fdfa2001-04-08 13:27:39 +0000343 }
344 else if (strstr(line, "Package: ") == line) {
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000345 p->package = xstrdup(line + 9);
Glenn L McGrath305fdfa2001-04-08 13:27:39 +0000346 }
347 else if (strstr(line, "Status: ") == line) {
348 char *word_pointer;
349 word_pointer = strchr(line, ' ') + 1;
350 p->status_want = status_parse(word_pointer, status_words_want);
351 word_pointer = strchr(word_pointer, ' ') + 1;
352 p->status_flag = status_parse(word_pointer, status_words_flag);
353 word_pointer = strchr(word_pointer, ' ') + 1;
354 p->status_status = status_parse(word_pointer, status_words_status);
355 }
356 else if (strstr(line, "Depends: ") == line) {
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000357 p->depends = xstrdup(line + 9);
Glenn L McGrath305fdfa2001-04-08 13:27:39 +0000358 }
359 else if (strstr(line, "Provides: ") == line) {
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000360 p->provides = xstrdup(line + 10);
Glenn L McGrath305fdfa2001-04-08 13:27:39 +0000361 }
362 else if (strstr(line, "Description: ") == line) {
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000363 p->description = xstrdup(line + 13);
Glenn L McGrathc9005752001-02-10 02:05:24 +0000364 /* This is specific to the Debian Installer. Ifdef? */
Glenn L McGrath305fdfa2001-04-08 13:27:39 +0000365 }
366 else if (strstr(line, "installer-menu-item: ") == line) {
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000367 p->installer_menu_item = atoi(line + 21);
Glenn L McGrathc9005752001-02-10 02:05:24 +0000368 }
369 /* TODO: localized descriptions */
370 }
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000371 free(line);
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000372 return EXIT_SUCCESS;
Glenn L McGrathc9005752001-02-10 02:05:24 +0000373}
374
Glenn L McGrath649968c2001-02-10 14:26:48 +0000375static void *status_read(void)
Glenn L McGrathc9005752001-02-10 02:05:24 +0000376{
377 FILE *f;
378 void *status = 0;
Glenn L McGrath649968c2001-02-10 14:26:48 +0000379 package_t *m = 0, *p = 0, *t = 0;
Glenn L McGrathc9005752001-02-10 02:05:24 +0000380
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000381 if (getenv(udpkg_quiet) == NULL) {
Glenn L McGrathc9005752001-02-10 02:05:24 +0000382 printf("(Reading database...)\n");
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000383 }
Glenn L McGrath63106462001-02-11 01:40:23 +0000384
Eric Andersene5dfced2001-04-09 22:48:12 +0000385 if ((f = wfopen(statusfile, "r")) == NULL) {
Glenn L McGrath305fdfa2001-04-08 13:27:39 +0000386 return(NULL);
387 }
388
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000389 while (!feof(f)) {
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000390 m = (package_t *)xcalloc(1, sizeof(package_t));
Glenn L McGrathc9005752001-02-10 02:05:24 +0000391 control_read(f, m);
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000392 if (m->package) {
Glenn L McGrathc9005752001-02-10 02:05:24 +0000393 /*
394 * If there is an item in the tree by this name,
395 * it must be a virtual package; insert real
396 * package in preference.
397 */
398 tdelete(m, &status, package_compare);
399 tsearch(m, &status, package_compare);
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000400 if (m->provides) {
Glenn L McGrathc9005752001-02-10 02:05:24 +0000401 /*
402 * A "Provides" triggers the insertion
403 * of a pseudo package into the status
404 * binary-tree.
405 */
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000406 p = (package_t *)xcalloc(1, sizeof(package_t));
407 p->package = xstrdup(m->provides);
Glenn L McGrath649968c2001-02-10 14:26:48 +0000408 t = *(package_t **)tsearch(p, &status, package_compare);
Glenn L McGrath63106462001-02-11 01:40:23 +0000409 if (t != p) {
Glenn L McGrathc9005752001-02-10 02:05:24 +0000410 free(p->package);
411 free(p);
Glenn L McGrath305fdfa2001-04-08 13:27:39 +0000412 } else {
Glenn L McGrathc9005752001-02-10 02:05:24 +0000413 /*
414 * Pseudo package status is the
415 * same as the status of the
416 * package providing it
417 * FIXME: (not quite right, if 2
418 * packages of different statuses
Glenn L McGrath305fdfa2001-04-08 13:27:39 +0000419 * provide it).
420 */
421 t->status_want = m->status_want;
422 t->status_flag = m->status_flag;
423 t->status_status = m->status_status;
Glenn L McGrathc9005752001-02-10 02:05:24 +0000424 }
425 }
426 }
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000427 else {
Glenn L McGrathc9005752001-02-10 02:05:24 +0000428 free(m);
429 }
430 }
431 fclose(f);
432 return status;
433}
434
Glenn L McGrath649968c2001-02-10 14:26:48 +0000435static int status_merge(void *status, package_t *pkgs)
Glenn L McGrathc9005752001-02-10 02:05:24 +0000436{
437 FILE *fin, *fout;
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000438 char *line = NULL;
Glenn L McGrath649968c2001-02-10 14:26:48 +0000439 package_t *pkg = 0, *statpkg = 0;
440 package_t locpkg;
Glenn L McGrathc9005752001-02-10 02:05:24 +0000441
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000442 if ((fout = wfopen(new_statusfile, "w")) == NULL) {
Glenn L McGrathc9005752001-02-10 02:05:24 +0000443 return 0;
444 }
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000445 if (getenv(udpkg_quiet) == NULL) {
Glenn L McGrathc9005752001-02-10 02:05:24 +0000446 printf("(Updating database...)\n");
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000447 }
Glenn L McGrath305fdfa2001-04-08 13:27:39 +0000448
Glenn L McGrath13e9c7a2001-04-08 07:18:08 +0000449 /*
450 * Dont use wfopen here, handle errors ourself
451 */
452 if ((fin = fopen(statusfile, "r")) != NULL) {
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000453 while (((line = get_line_from_file(fin)) != NULL) && !feof(fin)) {
454 line[strlen(line) - 1] = '\0'; /* trim newline */
455 /* If we see a package header, find out if it's a package
456 * that we have processed. if so, we skip that block for
457 * now (write it at the end).
458 *
459 * we also look at packages in the status cache and update
460 * their status fields
Glenn L McGrath13e9c7a2001-04-08 07:18:08 +0000461 */
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000462 if (strstr(line, "Package: ") == line) {
463 for (pkg = pkgs; pkg != 0 && strcmp(line + 9,
464 pkg->package) != 0; pkg = pkg->next) ;
Glenn L McGrath63106462001-02-11 01:40:23 +0000465
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000466 locpkg.package = line + 9;
467 statpkg = tfind(&locpkg, &status, package_compare);
Glenn L McGrath13e9c7a2001-04-08 07:18:08 +0000468
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000469 /* note: statpkg should be non-zero, unless the status
470 * file was changed while we are processing (no locking
471 * is currently done...
472 */
473 if (statpkg != 0) {
474 statpkg = *(package_t **)statpkg;
475 }
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000476 }
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000477 if (pkg != 0) {
478 continue;
479 }
480 if (strstr(line, "Status: ") == line && statpkg != 0) {
Glenn L McGrath305fdfa2001-04-08 13:27:39 +0000481 snprintf(line, sizeof(line), "Status: %s %s %s",
482 status_words_want[statpkg->status_want - 1],
483 status_words_flag[statpkg->status_flag - 1],
484 status_words_status[statpkg->status_status - 1]);
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000485 }
Eric Andersene5dfced2001-04-09 22:48:12 +0000486 fprintf(fout, "%s\n", line);
Glenn L McGrathc9005752001-02-10 02:05:24 +0000487 }
Glenn L McGrath13e9c7a2001-04-08 07:18:08 +0000488 fclose(fin);
Glenn L McGrathc9005752001-02-10 02:05:24 +0000489 }
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000490 free(line);
Glenn L McGrathc9005752001-02-10 02:05:24 +0000491
492 // Print out packages we processed.
493 for (pkg = pkgs; pkg != 0; pkg = pkg->next) {
Glenn L McGrath305fdfa2001-04-08 13:27:39 +0000494 fprintf(fout, "Package: %s\nStatus: %s %s %s\n",
495 pkg->package, status_words_want[pkg->status_want - 1],
496 status_words_flag[pkg->status_flag - 1],
497 status_words_status[pkg->status_status - 1]);
498
Glenn L McGrathc9005752001-02-10 02:05:24 +0000499 if (pkg->depends)
500 fprintf(fout, "Depends: %s\n", pkg->depends);
501 if (pkg->provides)
502 fprintf(fout, "Provides: %s\n", pkg->provides);
503 if (pkg->installer_menu_item)
504 fprintf(fout, "installer-menu-item: %i\n", pkg->installer_menu_item);
505 if (pkg->description)
506 fprintf(fout, "Description: %s\n", pkg->description);
507 fputc('\n', fout);
508 }
Glenn L McGrathc9005752001-02-10 02:05:24 +0000509 fclose(fout);
510
Glenn L McGrath13e9c7a2001-04-08 07:18:08 +0000511 /*
512 * Its ok if renaming statusfile fails becasue it doesnt exist
513 */
514 if (rename(statusfile, bak_statusfile) == -1) {
515 struct stat stat_buf;
Glenn L McGrath13e9c7a2001-04-08 07:18:08 +0000516 if (stat(statusfile, &stat_buf) == 0) {
Glenn L McGrath305fdfa2001-04-08 13:27:39 +0000517 error_msg("Couldnt create backup status file");
Glenn L McGrath13e9c7a2001-04-08 07:18:08 +0000518 return(EXIT_FAILURE);
519 }
Glenn L McGrath305fdfa2001-04-08 13:27:39 +0000520 error_msg("No status file found, creating new one");
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000521 }
Glenn L McGrath63106462001-02-11 01:40:23 +0000522
Glenn L McGrath13e9c7a2001-04-08 07:18:08 +0000523 if (rename(new_statusfile, statusfile) == -1) {
524 error_msg("Couldnt create status file");
525 return(EXIT_FAILURE);
526 }
527 return(EXIT_SUCCESS);
Glenn L McGrathc9005752001-02-10 02:05:24 +0000528}
529
Glenn L McGrathc9005752001-02-10 02:05:24 +0000530static int is_file(const char *fn)
531{
532 struct stat statbuf;
533
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000534 if (stat(fn, &statbuf) < 0) {
535 return 0;
536 }
Glenn L McGrathc9005752001-02-10 02:05:24 +0000537 return S_ISREG(statbuf.st_mode);
538}
539
Glenn L McGrath649968c2001-02-10 14:26:48 +0000540static int dpkg_doconfigure(package_t *pkg)
Glenn L McGrathc9005752001-02-10 02:05:24 +0000541{
542 int r;
543 char postinst[1024];
544 char buf[1024];
Glenn L McGrath63106462001-02-11 01:40:23 +0000545
Glenn L McGrathc9005752001-02-10 02:05:24 +0000546 DPRINTF("Configuring %s\n", pkg->package);
Glenn L McGrath305fdfa2001-04-08 13:27:39 +0000547 pkg->status_status = 0;
Glenn L McGrath510f0dd2001-02-10 14:53:08 +0000548 snprintf(postinst, sizeof(postinst), "%s%s.postinst", infodir, pkg->package);
Glenn L McGrath63106462001-02-11 01:40:23 +0000549
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000550 if (is_file(postinst)) {
Glenn L McGrathc9005752001-02-10 02:05:24 +0000551 snprintf(buf, sizeof(buf), "%s configure", postinst);
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000552 if ((r = do_system(buf)) != 0) {
Eric Andersene5dfced2001-04-09 22:48:12 +0000553 error_msg("postinst exited with status %d\n", r);
Glenn L McGrath305fdfa2001-04-08 13:27:39 +0000554 pkg->status_status = status_status_halfconfigured;
Glenn L McGrathc9005752001-02-10 02:05:24 +0000555 return 1;
556 }
557 }
Glenn L McGrath305fdfa2001-04-08 13:27:39 +0000558 pkg->status_status = status_status_installed;
Glenn L McGrathc9005752001-02-10 02:05:24 +0000559
560 return 0;
561}
562
Glenn L McGrath649968c2001-02-10 14:26:48 +0000563static int dpkg_dounpack(package_t *pkg)
Glenn L McGrathc9005752001-02-10 02:05:24 +0000564{
Glenn L McGrath63106462001-02-11 01:40:23 +0000565 int r = 0, i;
Glenn L McGrath305fdfa2001-04-08 13:27:39 +0000566 int status = TRUE;
Eric Andersene5dfced2001-04-09 22:48:12 +0000567 char *cwd = xgetcwd(0);
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000568 char *src_file = NULL;
569 char *dst_file = NULL;
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000570// char *lst_file = NULL;
571 char *adminscripts[] = { "prerm", "postrm", "preinst", "postinst",
572 "conffiles", "md5sums", "shlibs", "templates" };
Glenn L McGrathc9005752001-02-10 02:05:24 +0000573
574 DPRINTF("Unpacking %s\n", pkg->package);
575
Eric Andersene5dfced2001-04-09 22:48:12 +0000576 if(cwd==NULL)
577 exit(EXIT_FAILURE);
Glenn L McGrathc9005752001-02-10 02:05:24 +0000578 chdir("/");
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000579 deb_extract(dpkg_deb_extract, "/", pkg->file);
580
Glenn L McGrath63106462001-02-11 01:40:23 +0000581 /* Installs the package scripts into the info directory */
582 for (i = 0; i < sizeof(adminscripts) / sizeof(adminscripts[0]); i++) {
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000583 struct stat src_stat_buf;
584 int src_fd = 0, dst_fd = 0;
585
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000586 /* The full path of the current location of the admin file */
587 src_file = xrealloc(src_file, strlen(dpkgcidir) + strlen(pkg->package) + strlen(adminscripts[i]) + 1);
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000588 sprintf(src_file, "%s%s/%s", dpkgcidir, pkg->package, adminscripts[i]);
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000589
590 /* the full path of where we want the file to be copied to */
591 dst_file = xrealloc(dst_file, strlen(infodir) + strlen(pkg->package) + strlen(adminscripts[i]) + 1);
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000592 sprintf(dst_file, "%s%s.%s", infodir, pkg->package, adminscripts[i]);
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000593
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000594 /*
595 * copy admin file to permanent home
596 * NOTE: Maybe merge this behaviour into libb/copy_file.c
597 */
598 if (lstat(src_file, &src_stat_buf) == 0) {
599 if ((src_fd = open(src_file, O_RDONLY)) != -1) {
600 if ((dst_fd = open(dst_file, O_WRONLY | O_CREAT, 0644)) == -1) {
Glenn L McGrath305fdfa2001-04-08 13:27:39 +0000601 status = FALSE;
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000602 perror_msg("Opening %s", dst_file);
603 }
604 copy_file_chunk(src_fd, dst_fd, src_stat_buf.st_size);
605 close(src_fd);
606 close(dst_fd);
607 } else {
Glenn L McGrath305fdfa2001-04-08 13:27:39 +0000608 status = FALSE;
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000609 error_msg("couldnt open [%s]\n", src_file);
610 }
Glenn L McGrath63106462001-02-11 01:40:23 +0000611 }
Glenn L McGrath63106462001-02-11 01:40:23 +0000612 }
613
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000614 /*
615 * create the list file
616 * FIXME: currently this dumps the lst to stdout instead of a file
617 */
618/* lst_file = (char *) xmalloc(strlen(infodir) + strlen(pkg->package) + 6);
619 strcpy(lst_file, infodir);
620 strcat(lst_file, pkg->package);
621 strcat(lst_file, ".list");
622 deb_extract(dpkg_deb_list, NULL, pkg->file);
623*/
624
Glenn L McGrath305fdfa2001-04-08 13:27:39 +0000625 pkg->status_want = status_want_install;
626 pkg->status_flag = status_flag_ok;
627
628 if (status == TRUE) {
629 pkg->status_status = status_status_unpacked;
Glenn L McGrath63106462001-02-11 01:40:23 +0000630 } else {
Glenn L McGrath305fdfa2001-04-08 13:27:39 +0000631 pkg->status_status = status_status_halfinstalled;
Glenn L McGrath63106462001-02-11 01:40:23 +0000632 }
Glenn L McGrath305fdfa2001-04-08 13:27:39 +0000633
Glenn L McGrathc9005752001-02-10 02:05:24 +0000634 chdir(cwd);
635 return r;
636}
637
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000638/*
639 * Extract and parse the control.tar.gz from the specified package
640 */
Glenn L McGrath649968c2001-02-10 14:26:48 +0000641static int dpkg_unpackcontrol(package_t *pkg)
Glenn L McGrathc9005752001-02-10 02:05:24 +0000642{
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000643 char *tmp_name;
644 FILE *file;
645 int length;
Glenn L McGrathc9005752001-02-10 02:05:24 +0000646
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000647 /* clean the temp directory (dpkgcidir) be recreating it */
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000648 remove_dir(dpkgcidir);
Glenn L McGrath37849f32001-04-08 07:23:53 +0000649 if (create_path(dpkgcidir, S_IRWXU) == FALSE) {
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000650 return EXIT_FAILURE;
Glenn L McGrath63106462001-02-11 01:40:23 +0000651 }
Glenn L McGrathc9005752001-02-10 02:05:24 +0000652
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000653 /*
654 * Get the package name from the file name,
655 * first remove the directories
656 */
657 if ((tmp_name = strrchr(pkg->file, '/')) == NULL) {
658 tmp_name = pkg->file;
659 } else {
660 tmp_name++;
Glenn L McGrathc9005752001-02-10 02:05:24 +0000661 }
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000662 /* now remove trailing version numbers etc */
663 length = strcspn(tmp_name, "_.");
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000664 pkg->package = (char *) xcalloc(1, length + 1);
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000665 /* store the package name */
666 strncpy(pkg->package, tmp_name, length);
Glenn L McGrath63106462001-02-11 01:40:23 +0000667
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000668 /* work out the full extraction path */
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000669 tmp_name = (char *) xcalloc(1, strlen(dpkgcidir) + strlen(pkg->package) + 9);
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000670 strcpy(tmp_name, dpkgcidir);
671 strcat(tmp_name, pkg->package);
672
673 /* extract control.tar.gz to the full extraction path */
674 deb_extract(dpkg_deb_control, tmp_name, pkg->file);
675
676 /* parse the extracted control file */
677 strcat(tmp_name, "/control");
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000678 if ((file = wfopen(tmp_name, "r")) == NULL) {
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000679 return EXIT_FAILURE;
680 }
681 if (control_read(file, pkg) == EXIT_FAILURE) {
682 return EXIT_FAILURE;
683 }
684
685 return EXIT_SUCCESS;
Glenn L McGrathc9005752001-02-10 02:05:24 +0000686}
687
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000688static int dpkg_unpack(package_t *pkgs, void *status)
Glenn L McGrathc9005752001-02-10 02:05:24 +0000689{
690 int r = 0;
Glenn L McGrath649968c2001-02-10 14:26:48 +0000691 package_t *pkg;
Glenn L McGrathc9005752001-02-10 02:05:24 +0000692
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000693 for (pkg = pkgs; pkg != 0; pkg = pkg->next) {
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000694 if (dpkg_unpackcontrol(pkg) == EXIT_FAILURE) {
695 return EXIT_FAILURE;
696 }
697 if ((r = dpkg_dounpack(pkg)) != 0 ) {
698 break;
699 }
Glenn L McGrathc9005752001-02-10 02:05:24 +0000700 }
701 status_merge(status, pkgs);
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000702 remove_dir(dpkgcidir);
Glenn L McGrath63106462001-02-11 01:40:23 +0000703
Glenn L McGrathc9005752001-02-10 02:05:24 +0000704 return r;
705}
706
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000707static int dpkg_configure(package_t *pkgs, void *status)
Glenn L McGrathc9005752001-02-10 02:05:24 +0000708{
709 int r = 0;
710 void *found;
Glenn L McGrath649968c2001-02-10 14:26:48 +0000711 package_t *pkg;
Glenn L McGrath63106462001-02-11 01:40:23 +0000712
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000713 for (pkg = pkgs; pkg != 0 && r == 0; pkg = pkg->next) {
Glenn L McGrathc9005752001-02-10 02:05:24 +0000714 found = tfind(pkg, &status, package_compare);
Glenn L McGrath63106462001-02-11 01:40:23 +0000715
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000716 if (found == 0) {
Eric Andersene5dfced2001-04-09 22:48:12 +0000717 error_msg("Trying to configure %s, but it is not installed", pkg->package);
Glenn L McGrathc9005752001-02-10 02:05:24 +0000718 r = 1;
Glenn L McGrath63106462001-02-11 01:40:23 +0000719 }
720 /* configure the package listed in the status file;
721 * not pkg, as we have info only for the latter
722 */
723 else {
Glenn L McGrath649968c2001-02-10 14:26:48 +0000724 r = dpkg_doconfigure(*(package_t **)found);
Glenn L McGrathc9005752001-02-10 02:05:24 +0000725 }
726 }
727 status_merge(status, 0);
Glenn L McGrath63106462001-02-11 01:40:23 +0000728
Glenn L McGrathc9005752001-02-10 02:05:24 +0000729 return r;
730}
731
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000732static int dpkg_install(package_t *pkgs, void *status)
Glenn L McGrathc9005752001-02-10 02:05:24 +0000733{
Glenn L McGrath649968c2001-02-10 14:26:48 +0000734 package_t *p, *ordered = 0;
Glenn L McGrath63106462001-02-11 01:40:23 +0000735
Glenn L McGrathc9005752001-02-10 02:05:24 +0000736 /* Stage 1: parse all the control information */
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000737 for (p = pkgs; p != 0; p = p->next) {
738 if (dpkg_unpackcontrol(p) == EXIT_FAILURE) {
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000739 return(EXIT_FAILURE);
Glenn L McGrathc9005752001-02-10 02:05:24 +0000740 }
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000741 }
742
Glenn L McGrathc9005752001-02-10 02:05:24 +0000743 /* Stage 2: resolve dependencies */
744#ifdef DODEPENDS
745 ordered = depends_resolve(pkgs, status);
746#else
747 ordered = pkgs;
748#endif
749
750 /* Stage 3: install */
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000751 for (p = ordered; p != 0; p = p->next) {
Glenn L McGrath305fdfa2001-04-08 13:27:39 +0000752 p->status_want = status_want_install;
Glenn L McGrathc9005752001-02-10 02:05:24 +0000753
754 /* for now the flag is always set to ok... this is probably
755 * not what we want
756 */
Glenn L McGrath305fdfa2001-04-08 13:27:39 +0000757 p->status_flag = status_flag_ok;
Glenn L McGrathc9005752001-02-10 02:05:24 +0000758
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000759 DPRINTF("Installing %s\n", p->package);
760 if (dpkg_dounpack(p) != 0) {
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000761 perror_msg(p->file);
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000762 }
Glenn L McGrath305fdfa2001-04-08 13:27:39 +0000763
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000764 if (dpkg_doconfigure(p) != 0) {
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000765 perror_msg(p->file);
Glenn L McGrathc9005752001-02-10 02:05:24 +0000766 }
767 }
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000768
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000769 if (ordered != 0) {
Glenn L McGrathc9005752001-02-10 02:05:24 +0000770 status_merge(status, pkgs);
Glenn L McGrath0c9d77c2001-02-11 00:17:22 +0000771 }
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000772 remove_dir(dpkgcidir);
Glenn L McGrath63106462001-02-11 01:40:23 +0000773
Glenn L McGrathc9005752001-02-10 02:05:24 +0000774 return 0;
775}
776
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000777/*
778 * Not implemented yet
779 *
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000780static int dpkg_remove(package_t *pkgs, void *status)
Glenn L McGrathc9005752001-02-10 02:05:24 +0000781{
Glenn L McGrath649968c2001-02-10 14:26:48 +0000782 package_t *p;
Glenn L McGrath63106462001-02-11 01:40:23 +0000783
Glenn L McGrathc9005752001-02-10 02:05:24 +0000784 for (p = pkgs; p != 0; p = p->next)
785 {
786 }
787 status_merge(status, 0);
Glenn L McGrath63106462001-02-11 01:40:23 +0000788
Glenn L McGrathc9005752001-02-10 02:05:24 +0000789 return 0;
790}
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000791*/
Glenn L McGrathc9005752001-02-10 02:05:24 +0000792
Glenn L McGrath649968c2001-02-10 14:26:48 +0000793extern int dpkg_main(int argc, char **argv)
Glenn L McGrathc9005752001-02-10 02:05:24 +0000794{
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000795 const int arg_install = 1;
796 const int arg_unpack = 2;
797 const int arg_configure = 4;
798
Glenn L McGrath649968c2001-02-10 14:26:48 +0000799 package_t *p, *packages = NULL;
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000800 void *status = NULL;
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000801 char opt = 0;
802 int optflag = 0;
Glenn L McGrath63106462001-02-11 01:40:23 +0000803
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000804 while ((opt = getopt(argc, argv, "iruc")) != -1) {
805 switch (opt) {
806 case 'i':
807 optflag |= arg_install;
808 break;
809 case 'u':
810 optflag |= arg_unpack;
811 break;
812 case 'c':
813 optflag |= arg_configure;
814 break;
815 default:
816 show_usage();
817 }
Glenn L McGrathc9005752001-02-10 02:05:24 +0000818 }
Glenn L McGrath63106462001-02-11 01:40:23 +0000819
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000820 while (optind < argc) {
821 p = (package_t *) xcalloc(1, sizeof(package_t));
822 if (optflag & arg_configure) {
823 p->package = xstrdup(argv[optind]);
824 } else {
825 p->file = xstrdup(argv[optind]);
826 }
827 p->next = packages;
828 packages = p;
829
830 optind++;
831 }
832
Glenn L McGrath37849f32001-04-08 07:23:53 +0000833 create_path(dpkgcidir, S_IRWXU);
834 create_path(infodir, S_IRWXU);
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000835
Glenn L McGrath3af1f882001-02-12 11:33:09 +0000836 status = status_read();
837
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000838 if (optflag & arg_install) {
839 return dpkg_install(packages, status);
Glenn L McGrathc9005752001-02-10 02:05:24 +0000840 }
Glenn L McGrath0e757a22001-04-08 05:27:18 +0000841 else if (optflag & arg_unpack) {
842 return dpkg_unpack(packages, status);
843 }
844 else if (optflag & arg_configure) {
845 return dpkg_configure(packages, status);
846 }
847 return(EXIT_FAILURE);
Eric Andersen67991cf2001-02-14 21:23:06 +0000848}