perform.c revision 21673
1#ifndef lint
2static const char *rcsid = "$FreeBSD: head/usr.sbin/pkg_install/delete/perform.c 21673 1997-01-14 07:20:47Z jkh $";
3#endif
4
5/*
6 * FreeBSD install - a package for the installation and maintainance
7 * of non-core utilities.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 *
18 * Jordan K. Hubbard
19 * 18 July 1993
20 *
21 * This is the main body of the delete module.
22 *
23 */
24
25#include "lib.h"
26#include "delete.h"
27
28static int pkg_do(char *);
29static void sanity_check(char *);
30static void undepend(PackingList, char *);
31static char LogDir[FILENAME_MAX];
32
33
34int
35pkg_perform(char **pkgs)
36{
37    int i, err_cnt = 0;
38
39    for (i = 0; pkgs[i]; i++)
40	err_cnt += pkg_do(pkgs[i]);
41    return err_cnt;
42}
43
44static Package Plist;
45
46/* This is seriously ugly code following.  Written very fast! */
47static int
48pkg_do(char *pkg)
49{
50    FILE *cfile;
51    char home[FILENAME_MAX];
52    PackingList p;
53    char *tmp;
54
55    /* Reset some state */
56    if (Plist.head)
57	free_plist(&Plist);
58
59    sprintf(LogDir, "%s/%s", (tmp = getenv(PKG_DBDIR)) ? tmp : DEF_LOG_DIR,
60    	    pkg);
61    if (!fexists(LogDir)) {
62	whinge("No such package '%s' installed.", pkg);
63	return 1;
64    }
65    if (!getcwd(home, FILENAME_MAX))
66	barf("Unable to get current working directory!");
67    if (chdir(LogDir) == FAIL) {
68	whinge("Unable to change directory to %s!  Deinstall failed.", LogDir);
69	return 1;
70    }
71    if (!isemptyfile(REQUIRED_BY_FNAME)) {
72	char buf[512];
73	whinge("Package `%s' is required by these other packages", pkg);
74	whinge("and may not be deinstalled%s:", Force ? " (but I'll delete it anyway)" : "" );
75	cfile = fopen(REQUIRED_BY_FNAME, "r");
76	if (cfile) {
77	    while (fgets(buf, sizeof(buf), cfile))
78		fprintf(stderr, "%s", buf);
79	    fclose(cfile);
80	} else
81	    whinge("cannot open requirements file `%s'", REQUIRED_BY_FNAME);
82	if (!Force)
83	    return 1;
84    }
85    sanity_check(LogDir);
86    cfile = fopen(CONTENTS_FNAME, "r");
87    if (!cfile) {
88	whinge("Unable to open '%s' file.", CONTENTS_FNAME);
89	return 1;
90    }
91    /* If we have a prefix, add it now */
92    if (Prefix)
93	add_plist(&Plist, PLIST_CWD, Prefix);
94    read_plist(&Plist, cfile);
95    fclose(cfile);
96    setenv(PKG_PREFIX_VNAME,
97	   (p = find_plist(&Plist, PLIST_CWD)) ? p->name : NULL, 1);
98    if (fexists(REQUIRE_FNAME)) {
99	if (Verbose)
100	    printf("Executing 'require' script.\n");
101	vsystem("chmod +x %s", REQUIRE_FNAME);	/* be sure */
102	if (vsystem("./%s %s DEINSTALL", REQUIRE_FNAME, pkg)) {
103	    whinge("Package %s fails requirements %s", pkg,
104		   Force ? "." : "- not deleted.");
105	    if (!Force)
106		return 1;
107	}
108    }
109    if (!NoDeInstall && fexists(DEINSTALL_FNAME)) {
110	if (Fake)
111	    printf("Would execute de-install script at this point.\n");
112	else {
113	    vsystem("chmod +x %s", DEINSTALL_FNAME);	/* make sure */
114	    if (vsystem("./%s %s DEINSTALL", DEINSTALL_FNAME, pkg)) {
115		whinge("De-Install script returned error status.");
116		if (!Force)
117		    return 1;
118	    }
119	}
120    }
121    if (chdir(home) == FAIL)
122	barf("Toto!  This doesn't look like Kansas anymore!");
123    if (!Fake) {
124	/* Some packages aren't packed right, so we need to just ignore delete_package()'s status.  Ugh! :-( */
125	if (delete_package(FALSE, CleanDirs, &Plist) == FAIL)
126	    whinge("Couldn't entirely delete package (perhaps the packing list is\n"
127		 "incorrectly specified?)\n");
128	if (vsystem("%s -r %s", REMOVE_CMD, LogDir)) {
129	    whinge("Couldn't remove log entry in %s, de-install failed.", LogDir);
130	    if (!Force)
131		return 1;
132	}
133    }
134    for (p = Plist.head; p ; p = p->next) {
135	if (p->type != PLIST_PKGDEP)
136	    continue;
137	if (Verbose)
138	    printf("Attempting to remove dependency on package `%s'\n", p->name);
139	if (!Fake)
140	    undepend(p, pkg);
141    }
142    return 0;
143}
144
145static void
146sanity_check(char *pkg)
147{
148    if (!fexists(CONTENTS_FNAME))
149	barf("Installed package %s has no %s file!", pkg, CONTENTS_FNAME);
150}
151
152void
153cleanup(int sig)
154{
155    /* Nothing to do */
156}
157
158static void
159undepend(PackingList p, char *pkgname)
160{
161     char fname[FILENAME_MAX], ftmp[FILENAME_MAX];
162     char fbuf[FILENAME_MAX];
163     FILE *fp, *fpwr;
164     char *tmp;
165     int s;
166
167     sprintf(fname, "%s/%s/%s",
168	     (tmp = getenv(PKG_DBDIR)) ? tmp : DEF_LOG_DIR,
169	     p->name, REQUIRED_BY_FNAME);
170     fp = fopen(fname, "r");
171     if (fp == NULL) {
172	 whinge("Couldn't open dependency file `%s'", fname);
173	 return;
174     }
175     sprintf(ftmp, "%s.XXXXXX", fname);
176     s = mkstemp(ftmp);
177     if (s == -1) {
178	 fclose(fp);
179	 whinge("Couldn't open temp file `%s'", ftmp);
180	 return;
181     }
182     fpwr = fdopen(s, "w");
183     if (fpwr == NULL) {
184	 close(s);
185	 fclose(fp);
186	 whinge("Couldn't fdopen temp file `%s'", ftmp);
187	 remove(ftmp);
188	 return;
189     }
190     while (fgets(fbuf, sizeof(fbuf), fp) != NULL) {
191	 if (fbuf[strlen(fbuf)-1] == '\n')
192	     fbuf[strlen(fbuf)-1] = '\0';
193	 if (strcmp(fbuf, pkgname))		/* no match */
194	     fputs(fbuf, fpwr), putc('\n', fpwr);
195     }
196     (void) fclose(fp);
197     if (fchmod(s, 0644) == FAIL) {
198	 whinge("Error changing permission of temp file `%s'", ftmp);
199	 fclose(fpwr);
200	 remove(ftmp);
201	 return;
202     }
203     if (fclose(fpwr) == EOF) {
204	 whinge("Error closing temp file `%s'", ftmp);
205	 remove(ftmp);
206	 return;
207     }
208     if (rename(ftmp, fname) == -1)
209	 whinge("Error renaming `%s' to `%s'", ftmp, fname);
210     remove(ftmp);			/* just in case */
211     return;
212}
213