plist.c revision 379
1#ifndef lint
2static const char *rcsid = "$Id: plist.c,v 1.6 1993/09/04 05:06:52 jkh Exp $";
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 * General packing list routines.
22 *
23 */
24
25#include "lib.h"
26
27/* Add an item to a packing list */
28void
29add_plist(Package *p, plist_t type, char *arg)
30{
31    PackingList tmp;
32
33    tmp = new_plist_entry();
34    tmp->name = copy_string(arg);
35    tmp->type = type;
36
37    if (!p->head)
38	p->head = p->tail = tmp;
39    else {
40	tmp->prev = p->tail;
41	p->tail->next = tmp;
42	p->tail = tmp;
43    }
44}
45
46void
47add_plist_top(Package *p, plist_t type, char *arg)
48{
49    PackingList tmp;
50
51    tmp = new_plist_entry();
52    tmp->name = copy_string(arg);
53    tmp->type = type;
54
55    if (!p->head)
56	p->head = p->tail = tmp;
57    else {
58	tmp->next = p->head;
59	p->head->prev = tmp;
60	p->head = tmp;
61    }
62}
63
64/* Return the last (most recent) entry in a packing list */
65PackingList
66last_plist(Package *p)
67{
68    return p->tail;
69}
70
71/* Mark all items in a packing list to prevent iteration over them */
72void
73mark_plist(Package *pkg)
74{
75    PackingList p = pkg->head;
76
77    while (p) {
78	p->marked = TRUE;
79	p = p->next;
80    }
81}
82
83/* Return whether or not there is an item of 'type' in the list */
84Boolean
85in_plist(Package *pkg, plist_t type)
86{
87    PackingList p = pkg->head;
88
89    while (p) {
90	if (p->type == type)
91	    return TRUE;
92	p = p->next;
93    }
94    return FALSE;
95}
96
97/* Allocate a new packing list entry */
98PackingList
99new_plist_entry(void)
100{
101    PackingList ret;
102
103    ret = (PackingList)malloc(sizeof(struct _plist));
104    bzero(ret, sizeof(struct _plist));
105    return ret;
106}
107
108/* Free an entire packing list */
109void
110free_plist(Package *pkg)
111{
112    PackingList p = pkg->head;
113
114    while (p) {
115	PackingList p1 = p->next;
116
117	free(p->name);
118	free(p);
119	p = p1;
120    }
121    pkg->head = pkg->tail = NULL;
122}
123
124/*
125 * For an ascii string denoting a plist command, return its code and
126 * optionally its argument(s)
127 */
128int
129plist_cmd(char *s, char **arg)
130{
131    char cmd[FILENAME_MAX + 20];	/* 20 == fudge for max cmd len */
132    char *cp, *sp;
133
134    strcpy(cmd, s);
135    str_lowercase(cmd);
136    cp = cmd;
137    sp = s;
138    while (*cp) {
139	if (isspace(*cp)) {
140	    *cp = '\0';
141	    while (isspace(*sp)) /* Never sure if macro, increment later */
142		++sp;
143	    break;
144	}
145	++cp, ++sp;
146    }
147    if (arg)
148	*arg = sp;
149    if (!strcmp(cmd, "cwd"))
150	return PLIST_CWD;
151    else if (!strcmp(cmd, "cd"))
152	return PLIST_CWD;
153    else if (!strcmp(cmd, "exec"))
154	return PLIST_CMD;
155    else if (!strcmp(cmd, "mode"))
156	return PLIST_CHMOD;
157    else if (!strcmp(cmd, "owner"))
158	return PLIST_CHOWN;
159    else if (!strcmp(cmd, "group"))
160	return PLIST_CHGRP;
161    else if (!strcmp(cmd, "comment"))
162	return PLIST_COMMENT;
163    else if (!strcmp(cmd, "ignore"))
164	return PLIST_IGNORE;
165    else if (!strcmp(cmd, "name"))
166	return PLIST_NAME;
167    else
168	return FAIL;
169}
170
171/* Read a packing list from a file */
172void
173read_plist(Package *pkg, FILE *fp)
174{
175    char *cp, pline[FILENAME_MAX];
176    int cmd;
177
178    while (fgets(pline, FILENAME_MAX, fp)) {
179	int len = strlen(pline) - 1;
180
181	while (isspace(pline[len]))
182	    pline[len--] = '\0';
183	if (!len)
184	    continue;
185	cp = pline;
186	if (pline[0] == CMD_CHAR) {
187	    cmd = plist_cmd(pline + 1, &cp);
188	    if (cmd == FAIL)
189		barf("Bad command '%s'", pline);
190	}
191	else
192	    cmd = PLIST_FILE;
193	add_plist(pkg, cmd, cp);
194    }
195}
196
197/* Write a packing list to a file, converting commands to ascii equivs */
198void
199write_plist(Package *pkg, FILE *fp)
200{
201    PackingList plist = pkg->head;
202
203    while (plist) {
204	switch(plist->type) {
205	case PLIST_FILE:
206	    fprintf(fp, "%s\n", plist->name);
207	    break;
208
209	case PLIST_CWD:
210	    fprintf(fp, "%ccwd %s\n", CMD_CHAR, plist->name);
211	    break;
212
213	case PLIST_CMD:
214	    fprintf(fp, "%cexec %s\n", CMD_CHAR, plist->name);
215	    break;
216
217	case PLIST_CHMOD:
218	    fprintf(fp, "%cchmod %s\n", CMD_CHAR,
219		    plist->name ? plist->name : "");
220	    break;
221
222	case PLIST_CHOWN:
223	    fprintf(fp, "%cchown %s\n", CMD_CHAR,
224		    plist->name ? plist->name : "");
225	    break;
226
227	case PLIST_CHGRP:
228	    fprintf(fp, "%cchgrp %s\n", CMD_CHAR,
229		    plist->name ? plist->name : "");
230	    break;
231
232	case PLIST_COMMENT:
233	    fprintf(fp, "%ccomment %s\n", CMD_CHAR, plist->name);
234	    break;
235
236	case PLIST_IGNORE:
237	    fprintf(fp, "%cignore\n", CMD_CHAR);
238	    break;
239
240	case PLIST_NAME:
241	    fprintf(fp, "%cname %s\n", CMD_CHAR, plist->name);
242	    break;
243
244	default:
245	    barf("Unknown command type %d (%s)\n", plist->type, plist->name);
246	    break;
247	}
248	plist = plist->next;
249    }
250}
251
252/* Delete the results of a package installation, not the packaging itself */
253void
254delete_package(Boolean ign_err, Package *pkg)
255{
256    PackingList p = pkg->head;
257    char *Where = ".";
258
259    while (p) {
260	if (p->type == PLIST_CWD) {
261	    Where = p->name;
262	    if (Verbose)
263		printf("(CWD to %s)\n", Where);
264	}
265	else if (p->type == PLIST_IGNORE)
266	    p = p->next;
267	else if (p->type == PLIST_FILE) {
268	    char full_name[FILENAME_MAX];
269
270	    sprintf(full_name, "%s/%s", Where, p->name);
271	    if (Verbose)
272		printf("Delete: %s\n", full_name);
273
274	    if (!Fake && delete_hierarchy(full_name, ign_err))
275		whinge("Unable to completely remove file '%s'", full_name);
276	}
277	p = p->next;
278    }
279}
280
281/* Selectively delete a hierarchy */
282int
283delete_hierarchy(char *dir, Boolean ign_err)
284{
285    char *cp1, *cp2;
286
287    cp1 = cp2 = dir;
288    if (vsystem("%s -r%s %s", REMOVE_CMD, (ign_err ? "f" : ""), dir))
289	return 1;
290    while (cp2) {
291	if ((cp2 = rindex(cp1, '/')) != NULL)
292	    *cp2 = '\0';
293	if (!isempty(dir))
294	    return 0;
295	if (vsystem("%s %s", RMDIR_CMD, dir) && ign_err)
296	    return 1;
297	/* Put it back */
298	if (cp2) {
299	    *cp2 = '/';
300	    cp1 = cp2 - 1;
301	}
302    }
303    return 0;
304}
305