xref: /dflybsd-src/usr.bin/dsynth/pkglist.c (revision 5d0718a8775196ba673595dea1fc0ccbc02b800b)
18e25f19bSMatthew Dillon /*
28e25f19bSMatthew Dillon  * Copyright (c) 2019 The DragonFly Project.  All rights reserved.
38e25f19bSMatthew Dillon  *
48e25f19bSMatthew Dillon  * This code is derived from software contributed to The DragonFly Project
58e25f19bSMatthew Dillon  * by Matthew Dillon <dillon@backplane.com>
68e25f19bSMatthew Dillon  *
78e25f19bSMatthew Dillon  * This code uses concepts and configuration based on 'synth', by
88e25f19bSMatthew Dillon  * John R. Marino <draco@marino.st>, which was written in ada.
98e25f19bSMatthew Dillon  *
108e25f19bSMatthew Dillon  * Redistribution and use in source and binary forms, with or without
118e25f19bSMatthew Dillon  * modification, are permitted provided that the following conditions
128e25f19bSMatthew Dillon  * are met:
138e25f19bSMatthew Dillon  *
148e25f19bSMatthew Dillon  * 1. Redistributions of source code must retain the above copyright
158e25f19bSMatthew Dillon  *    notice, this list of conditions and the following disclaimer.
168e25f19bSMatthew Dillon  * 2. Redistributions in binary form must reproduce the above copyright
178e25f19bSMatthew Dillon  *    notice, this list of conditions and the following disclaimer in
188e25f19bSMatthew Dillon  *    the documentation and/or other materials provided with the
198e25f19bSMatthew Dillon  *    distribution.
208e25f19bSMatthew Dillon  * 3. Neither the name of The DragonFly Project nor the names of its
218e25f19bSMatthew Dillon  *    contributors may be used to endorse or promote products derived
228e25f19bSMatthew Dillon  *    from this software without specific, prior written permission.
238e25f19bSMatthew Dillon  *
248e25f19bSMatthew Dillon  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
258e25f19bSMatthew Dillon  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
268e25f19bSMatthew Dillon  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
278e25f19bSMatthew Dillon  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
288e25f19bSMatthew Dillon  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
298e25f19bSMatthew Dillon  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
308e25f19bSMatthew Dillon  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
318e25f19bSMatthew Dillon  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
328e25f19bSMatthew Dillon  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
338e25f19bSMatthew Dillon  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
348e25f19bSMatthew Dillon  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
358e25f19bSMatthew Dillon  * SUCH DAMAGE.
368e25f19bSMatthew Dillon  */
378e25f19bSMatthew Dillon 
388e25f19bSMatthew Dillon #include "dsynth.h"
398e25f19bSMatthew Dillon 
408e25f19bSMatthew Dillon #define PKG_HSIZE	32768
418e25f19bSMatthew Dillon #define PKG_HMASK	32767
428e25f19bSMatthew Dillon 
43710838f7SMatthew Dillon static int parsepkglist_file(const char *path, int debugstop);
448e25f19bSMatthew Dillon static void childGetPackageInfo(bulk_t *bulk);
458e25f19bSMatthew Dillon static void childGetBinaryDistInfo(bulk_t *bulk);
46a67bf8dbSMatthew Dillon static void childOptimizeEnv(bulk_t *bulk);
478e25f19bSMatthew Dillon static pkg_t *resolveDeps(pkg_t *dep_list, pkg_t ***list_tailp, int gentopo);
4877ac77e7SMatthew Dillon static void resolveFlavors(pkg_t *pkg, char *flavors, int gentopo);
4963fcce5bSMatthew Dillon static void resolveDepString(pkg_t *pkg, char *depstr,
5063fcce5bSMatthew Dillon 			int gentopo, int dep_type);
518e25f19bSMatthew Dillon static pkg_t *processPackageListBulk(int total);
528e25f19bSMatthew Dillon static int scan_and_queue_dir(const char *path, const char *level1, int level);
538e25f19bSMatthew Dillon static int scan_binary_repo(const char *path);
548e25f19bSMatthew Dillon #if 0
558e25f19bSMatthew Dillon static void pkgfree(pkg_t *pkg);
568e25f19bSMatthew Dillon #endif
578e25f19bSMatthew Dillon 
58eea2aa9aSMatthew Dillon static int PrepareSystemFlag;
59eea2aa9aSMatthew Dillon 
60d50f9ae3SSascha Wildner static pkg_t *PkgHash1[PKG_HSIZE];	/* by portdir */
61d50f9ae3SSascha Wildner static pkg_t *PkgHash2[PKG_HSIZE];	/* by pkgfile */
628e25f19bSMatthew Dillon 
638e25f19bSMatthew Dillon /*
648e25f19bSMatthew Dillon  * Allocate a new pkg structure plus basic initialization.
658e25f19bSMatthew Dillon  */
668e25f19bSMatthew Dillon static __inline pkg_t *
678e25f19bSMatthew Dillon allocpkg(void)
688e25f19bSMatthew Dillon {
698e25f19bSMatthew Dillon 	pkg_t *pkg;
708e25f19bSMatthew Dillon 
718e25f19bSMatthew Dillon 	pkg = calloc(1, sizeof(*pkg));
728e25f19bSMatthew Dillon 	pkg->idepon_list.next = &pkg->idepon_list;
738e25f19bSMatthew Dillon 	pkg->idepon_list.prev = &pkg->idepon_list;
748e25f19bSMatthew Dillon 	pkg->deponi_list.next = &pkg->deponi_list;
758e25f19bSMatthew Dillon 	pkg->deponi_list.prev = &pkg->deponi_list;
768e25f19bSMatthew Dillon 
778e25f19bSMatthew Dillon 	return pkg;
788e25f19bSMatthew Dillon }
798e25f19bSMatthew Dillon 
808e25f19bSMatthew Dillon /*
818e25f19bSMatthew Dillon  * Simple hash for lookups
828e25f19bSMatthew Dillon  */
838e25f19bSMatthew Dillon static __inline int
848e25f19bSMatthew Dillon pkghash(const char *str)
858e25f19bSMatthew Dillon {
868e25f19bSMatthew Dillon 	int hv = 0xABC32923;
878e25f19bSMatthew Dillon 	while (*str) {
888e25f19bSMatthew Dillon 		hv = (hv << 5) ^ *str;
898e25f19bSMatthew Dillon 		++str;
908e25f19bSMatthew Dillon 	}
918e25f19bSMatthew Dillon 	hv = hv ^ (hv / PKG_HSIZE) ^ (hv / PKG_HSIZE / PKG_HSIZE);
928e25f19bSMatthew Dillon 	return (hv & PKG_HMASK);
938e25f19bSMatthew Dillon }
948e25f19bSMatthew Dillon 
9593fe0327SMatthew Dillon static __inline const char *
9693fe0327SMatthew Dillon deptype2str(int dep_type)
9793fe0327SMatthew Dillon {
9893fe0327SMatthew Dillon     switch (dep_type) {
9993fe0327SMatthew Dillon     case DEP_TYPE_FETCH:
10093fe0327SMatthew Dillon 	return("FETCH_DEPENDS");
10193fe0327SMatthew Dillon     case DEP_TYPE_EXT:
10293fe0327SMatthew Dillon 	return("EXTRACT_DEPENDS");
10393fe0327SMatthew Dillon     case DEP_TYPE_PATCH:
10493fe0327SMatthew Dillon 	return("PATCH_DEPENDS");
10593fe0327SMatthew Dillon     case DEP_TYPE_BUILD:
10693fe0327SMatthew Dillon 	return("BUILD_DEPENDS");
10793fe0327SMatthew Dillon     case DEP_TYPE_LIB:
10893fe0327SMatthew Dillon 	return("LIB_DEPENDS");
10993fe0327SMatthew Dillon     case DEP_TYPE_RUN:
11093fe0327SMatthew Dillon 	return("RUN_DEPENDS");
11193fe0327SMatthew Dillon     default:
112bc91b54aSAlexandr Savca (chinarulezzz) 	return("UNKNOWN");
11393fe0327SMatthew Dillon     }
11493fe0327SMatthew Dillon }
11593fe0327SMatthew Dillon 
1168e25f19bSMatthew Dillon static void
1178e25f19bSMatthew Dillon pkg_enter(pkg_t *pkg)
1188e25f19bSMatthew Dillon {
1198e25f19bSMatthew Dillon 	pkg_t **pkgp;
1208e25f19bSMatthew Dillon 	pkg_t *scan;
1218e25f19bSMatthew Dillon 
1228e25f19bSMatthew Dillon 	if (pkg->portdir) {
1238e25f19bSMatthew Dillon 		pkgp = &PkgHash1[pkghash(pkg->portdir)];
1248e25f19bSMatthew Dillon 		while ((scan = *pkgp) != NULL) {
1258e25f19bSMatthew Dillon 			if (strcmp(pkg->portdir, scan->portdir) == 0)
1268e25f19bSMatthew Dillon 				break;
1278e25f19bSMatthew Dillon 			pkgp = &scan->hnext1;
1288e25f19bSMatthew Dillon 		}
12977ac77e7SMatthew Dillon 		ddassert(scan == NULL || (scan->flags & PKGF_PLACEHOLD));
1308e25f19bSMatthew Dillon 		if (scan && (scan->flags & PKGF_PLACEHOLD)) {
13177ac77e7SMatthew Dillon 			ddassert(scan->idepon_list.next == &scan->idepon_list);
13277ac77e7SMatthew Dillon 			ddassert(scan->deponi_list.next == &scan->deponi_list);
1338e25f19bSMatthew Dillon 			*pkgp = pkg;
1348e25f19bSMatthew Dillon 			pkg->hnext1 = scan->hnext1;
1358e25f19bSMatthew Dillon 			free(scan->portdir);
1368e25f19bSMatthew Dillon 			free(scan);
1378e25f19bSMatthew Dillon 			scan = NULL;
1388e25f19bSMatthew Dillon 		}
1398e25f19bSMatthew Dillon 		if (scan == NULL)
1408e25f19bSMatthew Dillon 			*pkgp = pkg;
1418e25f19bSMatthew Dillon 	}
1428e25f19bSMatthew Dillon 
1438e25f19bSMatthew Dillon 	if (pkg->pkgfile) {
1448e25f19bSMatthew Dillon 		pkgp = &PkgHash2[pkghash(pkg->pkgfile)];
1458e25f19bSMatthew Dillon 		while ((scan = *pkgp) != NULL) {
1468e25f19bSMatthew Dillon 			if (strcmp(pkg->pkgfile, scan->pkgfile) == 0)
1478e25f19bSMatthew Dillon 				break;
1488e25f19bSMatthew Dillon 			pkgp = &scan->hnext2;
1498e25f19bSMatthew Dillon 		}
1508e25f19bSMatthew Dillon 		if (scan == NULL)
1518e25f19bSMatthew Dillon 			*pkgp = pkg;
1528e25f19bSMatthew Dillon 	}
1538e25f19bSMatthew Dillon }
1548e25f19bSMatthew Dillon 
1558e25f19bSMatthew Dillon static pkg_t *
1568e25f19bSMatthew Dillon pkg_find(const char *match)
1578e25f19bSMatthew Dillon {
1588e25f19bSMatthew Dillon 	pkg_t **pkgp;
1598e25f19bSMatthew Dillon 	pkg_t *pkg;
1608e25f19bSMatthew Dillon 
1618e25f19bSMatthew Dillon 	pkgp = &PkgHash1[pkghash(match)];
1628e25f19bSMatthew Dillon 	for (pkg = *pkgp; pkg; pkg = pkg->hnext1) {
1638e25f19bSMatthew Dillon 		if (strcmp(pkg->portdir, match) == 0)
1648e25f19bSMatthew Dillon 			return pkg;
1658e25f19bSMatthew Dillon 	}
1668e25f19bSMatthew Dillon 	pkgp = &PkgHash2[pkghash(match)];
1678e25f19bSMatthew Dillon 	for (pkg = *pkgp; pkg; pkg = pkg->hnext2) {
1688e25f19bSMatthew Dillon 		if (strcmp(pkg->pkgfile, match) == 0)
1698e25f19bSMatthew Dillon 			return pkg;
1708e25f19bSMatthew Dillon 	}
1718e25f19bSMatthew Dillon 	return NULL;
1728e25f19bSMatthew Dillon }
1738e25f19bSMatthew Dillon 
1748e25f19bSMatthew Dillon /*
1758e25f19bSMatthew Dillon  * Parse a specific list of ports via origin name (portdir/subdir)
1768e25f19bSMatthew Dillon  */
1778e25f19bSMatthew Dillon pkg_t *
178710838f7SMatthew Dillon ParsePackageList(int n, char **ary, int debugstop)
1798e25f19bSMatthew Dillon {
1808e25f19bSMatthew Dillon 	pkg_t *list;
1818e25f19bSMatthew Dillon 	int total;
182310ce99fSMatthew Dillon 	int fail;
183310ce99fSMatthew Dillon 	int i;
1848e25f19bSMatthew Dillon 
1858e25f19bSMatthew Dillon 	total = 0;
186310ce99fSMatthew Dillon 	fail = 0;
1878e25f19bSMatthew Dillon 	initbulk(childGetPackageInfo, MaxBulk);
1888e25f19bSMatthew Dillon 
189f4094b20SMatthew Dillon 	/*
190710838f7SMatthew Dillon 	 * Always include ports-mgmt/pkg.  s4 is "x" meaning not a manual
191710838f7SMatthew Dillon 	 * selection, "d" meaning DEBUGSTOP mode, or NULL.
192f4094b20SMatthew Dillon 	 */
193f4094b20SMatthew Dillon 	queuebulk("ports-mgmt", "pkg", NULL, "x");
194f4094b20SMatthew Dillon 
1958e25f19bSMatthew Dillon 	for (i = 0; i < n; ++i) {
1968e25f19bSMatthew Dillon 		char *l1;
1978e25f19bSMatthew Dillon 		char *l2;
19853c9b6f3SMatthew Dillon 		char *l3;
19953c9b6f3SMatthew Dillon 		struct stat st;
2008e25f19bSMatthew Dillon 
2018e25f19bSMatthew Dillon 		l1 = strdup(ary[i]);
20253c9b6f3SMatthew Dillon 		if (stat(l1, &st) == 0 && S_ISREG(st.st_mode)) {
203710838f7SMatthew Dillon 			total += parsepkglist_file(l1, debugstop);
20453c9b6f3SMatthew Dillon 			continue;
2058e25f19bSMatthew Dillon 		}
20653c9b6f3SMatthew Dillon 
20753c9b6f3SMatthew Dillon 		l2 = strchr(l1, '/');
20853c9b6f3SMatthew Dillon 		if (l2 == NULL) {
20953c9b6f3SMatthew Dillon 			printf("Bad portdir specification: %s\n", l1);
21053c9b6f3SMatthew Dillon 			free(l1);
211310ce99fSMatthew Dillon 			fail = 1;
21253c9b6f3SMatthew Dillon 			continue;
21353c9b6f3SMatthew Dillon 		}
21453c9b6f3SMatthew Dillon 		*l2++ = 0;
21553c9b6f3SMatthew Dillon 		l3 = strchr(l2, '@');
21653c9b6f3SMatthew Dillon 		if (l3)
21753c9b6f3SMatthew Dillon 			*l3++ = 0;
218416608a0SMatthew Dillon 
219416608a0SMatthew Dillon 		/*
220416608a0SMatthew Dillon 		 * Silently ignore any manually specified ports-mgmt/pkg,
221416608a0SMatthew Dillon 		 * which we already auto-added.
222416608a0SMatthew Dillon 		 */
223416608a0SMatthew Dillon 		if (strcmp(l1, "ports-mgmt") != 0 ||
224416608a0SMatthew Dillon 		    strcmp(l2, "pkg") != 0)
225416608a0SMatthew Dillon 		{
226710838f7SMatthew Dillon 			queuebulk(l1, l2, l3, (debugstop ? "d" : NULL));
227416608a0SMatthew Dillon 		}
22853c9b6f3SMatthew Dillon 		++total;
2298e25f19bSMatthew Dillon 		free(l1);
2308e25f19bSMatthew Dillon 	}
2318e25f19bSMatthew Dillon 	printf("Processing %d ports\n", total);
2328e25f19bSMatthew Dillon 
2338e25f19bSMatthew Dillon 	list = processPackageListBulk(total);
234310ce99fSMatthew Dillon 	if (fail) {
235310ce99fSMatthew Dillon 		dfatal("Bad specifications, exiting");
236310ce99fSMatthew Dillon 		exit(1);
237310ce99fSMatthew Dillon 	}
2388e25f19bSMatthew Dillon 
2398e25f19bSMatthew Dillon 	return list;
2408e25f19bSMatthew Dillon }
2418e25f19bSMatthew Dillon 
24253c9b6f3SMatthew Dillon static
24353c9b6f3SMatthew Dillon int
244710838f7SMatthew Dillon parsepkglist_file(const char *path, int debugstop)
24553c9b6f3SMatthew Dillon {
24653c9b6f3SMatthew Dillon 	FILE *fp;
24753c9b6f3SMatthew Dillon 	char *base;
24853c9b6f3SMatthew Dillon 	char *l1;
24953c9b6f3SMatthew Dillon 	char *l2;
25053c9b6f3SMatthew Dillon 	char *l3;
25153c9b6f3SMatthew Dillon 	size_t len;
25253c9b6f3SMatthew Dillon 	int total;
25353c9b6f3SMatthew Dillon 
25453c9b6f3SMatthew Dillon 	if ((fp = fopen(path, "r")) == NULL) {
25553c9b6f3SMatthew Dillon 		dpanic_errno("Cannot read %s\n", path);
25653c9b6f3SMatthew Dillon 		/* NOT REACHED */
25753c9b6f3SMatthew Dillon 		return 0;
25853c9b6f3SMatthew Dillon 	}
25953c9b6f3SMatthew Dillon 
26053c9b6f3SMatthew Dillon 	total = 0;
26153c9b6f3SMatthew Dillon 
26253c9b6f3SMatthew Dillon 	while ((base = fgetln(fp, &len)) != NULL) {
26353c9b6f3SMatthew Dillon 		if (len == 0 || base[len-1] != '\n')
26453c9b6f3SMatthew Dillon 			continue;
26553c9b6f3SMatthew Dillon 		base[--len] = 0;
26653c9b6f3SMatthew Dillon 		l1 = strtok(base, " \t\r\n");
26753c9b6f3SMatthew Dillon 		if (l1 == NULL) {
26853c9b6f3SMatthew Dillon 			printf("Badly formatted pkg info line: %s\n", base);
26953c9b6f3SMatthew Dillon 			continue;
27053c9b6f3SMatthew Dillon 		}
27153c9b6f3SMatthew Dillon 		l2 = strchr(l1, '/');
27253c9b6f3SMatthew Dillon 		if (l2 == NULL) {
27353c9b6f3SMatthew Dillon 			printf("Badly formatted specification: %s\n", l1);
27453c9b6f3SMatthew Dillon 			continue;
27553c9b6f3SMatthew Dillon 		}
27653c9b6f3SMatthew Dillon 		*l2++ = 0;
27753c9b6f3SMatthew Dillon 		l3 = strchr(l2, '@');
27853c9b6f3SMatthew Dillon 		if (l3)
27953c9b6f3SMatthew Dillon 			*l3++ = 0;
280710838f7SMatthew Dillon 		queuebulk(l1, l2, l3, (debugstop ? "d" : NULL));
28153c9b6f3SMatthew Dillon 		++total;
28253c9b6f3SMatthew Dillon 	}
28353c9b6f3SMatthew Dillon 	fclose(fp);
28453c9b6f3SMatthew Dillon 
28553c9b6f3SMatthew Dillon 	return total;
28653c9b6f3SMatthew Dillon }
28753c9b6f3SMatthew Dillon 
2888e25f19bSMatthew Dillon /*
2898e25f19bSMatthew Dillon  * Parse packages from the list installed on the system.
2908e25f19bSMatthew Dillon  */
2918e25f19bSMatthew Dillon pkg_t *
2928e25f19bSMatthew Dillon GetLocalPackageList(void)
2938e25f19bSMatthew Dillon {
2948e25f19bSMatthew Dillon 	pkg_t *list;
2958e25f19bSMatthew Dillon 	FILE *fp;
2968e25f19bSMatthew Dillon 	char *base;
297eea2aa9aSMatthew Dillon 	char *data;
2988e25f19bSMatthew Dillon 	char *l1;
2998e25f19bSMatthew Dillon 	char *l2;
30053c9b6f3SMatthew Dillon 	char *l3;
3018e25f19bSMatthew Dillon 	int total;
302eea2aa9aSMatthew Dillon 	int state;
3038e25f19bSMatthew Dillon 	size_t len;
3048e25f19bSMatthew Dillon 
305eea2aa9aSMatthew Dillon 	PrepareSystemFlag = 1;
3068e25f19bSMatthew Dillon 	initbulk(childGetPackageInfo, MaxBulk);
3078e25f19bSMatthew Dillon 	total = 0;
308eea2aa9aSMatthew Dillon 	state = 0;
309eea2aa9aSMatthew Dillon 	l1 = NULL;
310eea2aa9aSMatthew Dillon 	l2 = NULL;
311eea2aa9aSMatthew Dillon 	l3 = NULL;
3128e25f19bSMatthew Dillon 
313eea2aa9aSMatthew Dillon 	fp = popen("pkg info -a -o -A", "r");
3148e25f19bSMatthew Dillon 
315f4094b20SMatthew Dillon 	/*
316710838f7SMatthew Dillon 	 * Always include ports-mgmt/pkg.  s4 is "x" meaning not a manual
317710838f7SMatthew Dillon 	 * selection, "d" meaning DEBUGSTOP mode, or NULL.
318f4094b20SMatthew Dillon 	 */
319f4094b20SMatthew Dillon 	queuebulk("ports-mgmt", "pkg", NULL, "x");
320f4094b20SMatthew Dillon 
3218e25f19bSMatthew Dillon 	while ((base = fgetln(fp, &len)) != NULL) {
3228e25f19bSMatthew Dillon 		if (len == 0 || base[len-1] != '\n')
3238e25f19bSMatthew Dillon 			continue;
3248e25f19bSMatthew Dillon 		base[--len] = 0;
3258e25f19bSMatthew Dillon 
326eea2aa9aSMatthew Dillon 		data = strchr(base, ':');
327eea2aa9aSMatthew Dillon 		if (data == NULL)
32853c9b6f3SMatthew Dillon 			continue;
329eea2aa9aSMatthew Dillon 		*data++ = 0;
330eea2aa9aSMatthew Dillon 
331eea2aa9aSMatthew Dillon 		base = strtok(base, " \t\r");
332eea2aa9aSMatthew Dillon 		data = strtok(data, " \t\r");
333eea2aa9aSMatthew Dillon 
334eea2aa9aSMatthew Dillon 		if (base == NULL || data == NULL)
335eea2aa9aSMatthew Dillon 			continue;
336eea2aa9aSMatthew Dillon 
337eea2aa9aSMatthew Dillon 		if (strcmp(base, "Origin") == 0) {
338eea2aa9aSMatthew Dillon 			if (state == 1) {
339eea2aa9aSMatthew Dillon 				queuebulk(l1, l2, NULL, NULL);
340eea2aa9aSMatthew Dillon 				state = 0;
34153c9b6f3SMatthew Dillon 				++total;
3428e25f19bSMatthew Dillon 			}
343eea2aa9aSMatthew Dillon 
344eea2aa9aSMatthew Dillon 			if (strchr(data, '/') == NULL) {
345eea2aa9aSMatthew Dillon 				printf("Badly formatted origin: %s\n", l1);
346eea2aa9aSMatthew Dillon 			}
347eea2aa9aSMatthew Dillon 			if (l1)
348eea2aa9aSMatthew Dillon 				free(l1);
349eea2aa9aSMatthew Dillon 			if (l3)
350eea2aa9aSMatthew Dillon 				free(l3);
351eea2aa9aSMatthew Dillon 			l1 = strdup(data);
352eea2aa9aSMatthew Dillon 			l2 = strchr(l1, '/');
353eea2aa9aSMatthew Dillon 			*l2++ = 0;
354eea2aa9aSMatthew Dillon 			l3 = strchr(l2, '@');	/* typically NULL */
355eea2aa9aSMatthew Dillon 			if (l3) {
356eea2aa9aSMatthew Dillon 				*l3++ = 0;
357eea2aa9aSMatthew Dillon 				l3 = strdup(l3);
358eea2aa9aSMatthew Dillon 			}
359eea2aa9aSMatthew Dillon 
360eea2aa9aSMatthew Dillon 			/*
361eea2aa9aSMatthew Dillon 			 * Don't queue ports-mgmt/pkg twice, we already
362eea2aa9aSMatthew Dillon 			 * queued it manually.
363eea2aa9aSMatthew Dillon 			 */
364eea2aa9aSMatthew Dillon 			if (strcmp(l1, "ports-mgmt") != 0 ||
365eea2aa9aSMatthew Dillon 			    strcmp(l2, "pkg") != 0) {
366eea2aa9aSMatthew Dillon 				state = 1;
367eea2aa9aSMatthew Dillon 			}
368eea2aa9aSMatthew Dillon 			continue;
369eea2aa9aSMatthew Dillon 		}
370eea2aa9aSMatthew Dillon 		if (state == 1 && strcmp(base, "flavor") == 0) {
371eea2aa9aSMatthew Dillon 			queuebulk(l1, l2, data, NULL);
372eea2aa9aSMatthew Dillon 			state = 0;
373eea2aa9aSMatthew Dillon 			++total;
374eea2aa9aSMatthew Dillon 		}
375eea2aa9aSMatthew Dillon 	}
376eea2aa9aSMatthew Dillon 	if (state == 1) {
377eea2aa9aSMatthew Dillon 		queuebulk(l1, l2, NULL, NULL);
378eea2aa9aSMatthew Dillon 		/*state = 0; not needed */
379eea2aa9aSMatthew Dillon 	}
380eea2aa9aSMatthew Dillon 	if (l1)
381eea2aa9aSMatthew Dillon 		free(l1);
382eea2aa9aSMatthew Dillon 	if (l3)
383eea2aa9aSMatthew Dillon 		free(l3);
384eea2aa9aSMatthew Dillon 
3858e25f19bSMatthew Dillon 	pclose(fp);
3868e25f19bSMatthew Dillon 
3878e25f19bSMatthew Dillon 	printf("Processing %d ports\n", total);
3888e25f19bSMatthew Dillon 
3898e25f19bSMatthew Dillon 	list = processPackageListBulk(total);
3908e25f19bSMatthew Dillon 
3918e25f19bSMatthew Dillon 	return list;
3928e25f19bSMatthew Dillon }
3938e25f19bSMatthew Dillon 
3948e25f19bSMatthew Dillon pkg_t *
3958e25f19bSMatthew Dillon GetFullPackageList(void)
3968e25f19bSMatthew Dillon {
3978e25f19bSMatthew Dillon 	int total;
3988e25f19bSMatthew Dillon 
3998e25f19bSMatthew Dillon 	initbulk(childGetPackageInfo, MaxBulk);
4008e25f19bSMatthew Dillon 	total = scan_and_queue_dir(DPortsPath, NULL, 1);
4018e25f19bSMatthew Dillon 	printf("Scanning %d ports\n", total);
4028e25f19bSMatthew Dillon 
4038e25f19bSMatthew Dillon 	return processPackageListBulk(total);
4048e25f19bSMatthew Dillon }
4058e25f19bSMatthew Dillon 
4068e25f19bSMatthew Dillon /*
4078e25f19bSMatthew Dillon  * Caller has queued the process list for bulk operation.  We retrieve
4088e25f19bSMatthew Dillon  * the results and clean up the bulk operation (we may have to do a second
4098e25f19bSMatthew Dillon  * bulk operation so we have to be the ones to clean it up).
4108e25f19bSMatthew Dillon  */
4118e25f19bSMatthew Dillon static pkg_t *
4128e25f19bSMatthew Dillon processPackageListBulk(int total)
4138e25f19bSMatthew Dillon {
4148e25f19bSMatthew Dillon 	bulk_t *bulk;
4158e25f19bSMatthew Dillon 	pkg_t *scan;
4168e25f19bSMatthew Dillon 	pkg_t *list;
4178e25f19bSMatthew Dillon 	pkg_t *dep_list;
4188e25f19bSMatthew Dillon 	pkg_t **list_tail;
4198e25f19bSMatthew Dillon 	int count;
420927e4e3eSMatthew Dillon 	int stop_fail;
421eea2aa9aSMatthew Dillon 	int stop_base_list;
422eea2aa9aSMatthew Dillon 	int remove_corrupt;
4238e25f19bSMatthew Dillon 
4248e25f19bSMatthew Dillon 	list = NULL;
4258e25f19bSMatthew Dillon 	list_tail = &list;
4268e25f19bSMatthew Dillon 	count = 0;
427eea2aa9aSMatthew Dillon 	remove_corrupt = 0;
4288e25f19bSMatthew Dillon 
4298e25f19bSMatthew Dillon 	while ((bulk = getbulk()) != NULL) {
4308e25f19bSMatthew Dillon 		++count;
4318e25f19bSMatthew Dillon 		if ((count & 255) == 0) {
4328e25f19bSMatthew Dillon 			printf("%6.2f%%\r",
4338e25f19bSMatthew Dillon 				(double)count * 100.0 / (double)total + 0.001);
4348e25f19bSMatthew Dillon 			fflush(stdout);
4358e25f19bSMatthew Dillon 		}
4368e25f19bSMatthew Dillon 		if (bulk->list) {
4378e25f19bSMatthew Dillon 			*list_tail = bulk->list;
4388e25f19bSMatthew Dillon 			bulk->list = NULL;
439f4094b20SMatthew Dillon 			while ((scan = *list_tail) != NULL) {
440710838f7SMatthew Dillon 				if (bulk->s4 == NULL || bulk->s4[0] != 'x')
441f4094b20SMatthew Dillon 					scan->flags |= PKGF_MANUALSEL;
442f4094b20SMatthew Dillon 				pkg_enter(scan);
443f4094b20SMatthew Dillon 				list_tail = &scan->bnext;
4448e25f19bSMatthew Dillon 			}
4458e25f19bSMatthew Dillon 		}
4468e25f19bSMatthew Dillon 		freebulk(bulk);
4478e25f19bSMatthew Dillon 	}
4481645cafeSMatthew Dillon 	printf("100.00%%\n");
4498e25f19bSMatthew Dillon 	printf("\nTotal %d\n", count);
4508e25f19bSMatthew Dillon 	fflush(stdout);
4518e25f19bSMatthew Dillon 
4528e25f19bSMatthew Dillon 	/*
4538e25f19bSMatthew Dillon 	 * Resolve all dependencies for the related packages, potentially
4548e25f19bSMatthew Dillon 	 * adding anything that could not be found to the list.  This will
4558e25f19bSMatthew Dillon 	 * continue to issue bulk operations and process the result until
4568e25f19bSMatthew Dillon 	 * no dependencies are left.
4578e25f19bSMatthew Dillon 	 */
4588e25f19bSMatthew Dillon 	printf("Resolving dependencies...");
4598e25f19bSMatthew Dillon 	fflush(stdout);
4608e25f19bSMatthew Dillon 	dep_list = list;
4618e25f19bSMatthew Dillon 	while (dep_list) {
4628e25f19bSMatthew Dillon 		dep_list = resolveDeps(dep_list, &list_tail, 0);
4638e25f19bSMatthew Dillon 	}
4648e25f19bSMatthew Dillon 	printf("done\n");
4658e25f19bSMatthew Dillon 
4668e25f19bSMatthew Dillon 	donebulk();
4678e25f19bSMatthew Dillon 
4688e25f19bSMatthew Dillon 	/*
4698e25f19bSMatthew Dillon 	 * Generate the topology
4708e25f19bSMatthew Dillon 	 */
4718e25f19bSMatthew Dillon 	resolveDeps(list, NULL, 1);
4728e25f19bSMatthew Dillon 
4738e25f19bSMatthew Dillon 	/*
4748e25f19bSMatthew Dillon 	 * Do a final count, ignore place holders.
475927e4e3eSMatthew Dillon 	 *
476927e4e3eSMatthew Dillon 	 * Also set stop_fail if appropriate.  Check for direct specifications
477927e4e3eSMatthew Dillon 	 * which fail to probe and any direct dependencies of those
478927e4e3eSMatthew Dillon 	 * specifications, but don't recurse (for now)... don't check indirect
479927e4e3eSMatthew Dillon 	 * dependencies (i.e. A -> B -> C where A is directly specified, B
480927e4e3eSMatthew Dillon 	 * is adirect dependency, and C fails to probe).
4818e25f19bSMatthew Dillon 	 */
4828e25f19bSMatthew Dillon 	count = 0;
483927e4e3eSMatthew Dillon 	stop_fail = 0;
484eea2aa9aSMatthew Dillon 	stop_base_list = 0;
4858e25f19bSMatthew Dillon 	for (scan = list; scan; scan = scan->bnext) {
4868e25f19bSMatthew Dillon 		if ((scan->flags & PKGF_ERROR) == 0) {
4878e25f19bSMatthew Dillon 			++count;
4888e25f19bSMatthew Dillon 		}
489927e4e3eSMatthew Dillon 		if ((scan->flags & PKGF_MANUALSEL) && MaskProbeAbort == 0) {
490927e4e3eSMatthew Dillon 			pkglink_t *link;
491927e4e3eSMatthew Dillon 
492927e4e3eSMatthew Dillon 			/*
493927e4e3eSMatthew Dillon 			 * Directly specified package failed to probe
494927e4e3eSMatthew Dillon 			 */
495eea2aa9aSMatthew Dillon 			if (scan->flags & PKGF_CORRUPT) {
496927e4e3eSMatthew Dillon 				++stop_fail;
497eea2aa9aSMatthew Dillon 				++stop_base_list;
498eea2aa9aSMatthew Dillon 			}
499927e4e3eSMatthew Dillon 
500927e4e3eSMatthew Dillon 			/*
501927e4e3eSMatthew Dillon 			 * Directly specified package had a direct dependency
502927e4e3eSMatthew Dillon 			 * that failed to probe (don't go further).
503927e4e3eSMatthew Dillon 			 */
504927e4e3eSMatthew Dillon 			PKGLIST_FOREACH(link, &scan->idepon_list) {
505927e4e3eSMatthew Dillon 				if (link->pkg &&
506927e4e3eSMatthew Dillon 				    (link->pkg->flags & PKGF_CORRUPT)) {
507927e4e3eSMatthew Dillon 					++stop_fail;
508927e4e3eSMatthew Dillon 				}
509927e4e3eSMatthew Dillon 			}
510927e4e3eSMatthew Dillon 		}
5118e25f19bSMatthew Dillon 	}
5128e25f19bSMatthew Dillon 	printf("Total Returned %d\n", count);
5138e25f19bSMatthew Dillon 
5148e25f19bSMatthew Dillon 	/*
515927e4e3eSMatthew Dillon 	 * Check to see if any PKGF_MANUALSEL packages
516927e4e3eSMatthew Dillon 	 */
517927e4e3eSMatthew Dillon 	if (stop_fail) {
518eea2aa9aSMatthew Dillon 		printf("%d packages failed to probe\n", stop_fail);
519eea2aa9aSMatthew Dillon 		if (PrepareSystemFlag) {
520eea2aa9aSMatthew Dillon 			if (stop_fail == stop_base_list) {
521eea2aa9aSMatthew Dillon 				printf(
522eea2aa9aSMatthew Dillon   "prepare-system: Some of your installed packages no longer exist in\n"
523eea2aa9aSMatthew Dillon   "dports, do you wish to continue rebuilding what does exist?\n");
524eea2aa9aSMatthew Dillon 			        if (askyn("Continue anyway? "))
525eea2aa9aSMatthew Dillon 					remove_corrupt = 1;
526eea2aa9aSMatthew Dillon 			} else {
527eea2aa9aSMatthew Dillon 				printf(
528eea2aa9aSMatthew Dillon   "prepare-system: Some of your installed packages have dependencies\n"
529eea2aa9aSMatthew Dillon   "which could not be found in dports, cannot continue, aborting\n");
530eea2aa9aSMatthew Dillon 			}
531eea2aa9aSMatthew Dillon 		} else {
532eea2aa9aSMatthew Dillon 			printf("unable to continue, aborting\n");
533eea2aa9aSMatthew Dillon 		}
534eea2aa9aSMatthew Dillon 		if (remove_corrupt == 0)
535927e4e3eSMatthew Dillon 			exit(1);
536927e4e3eSMatthew Dillon 	}
537927e4e3eSMatthew Dillon 
538927e4e3eSMatthew Dillon 	/*
539eea2aa9aSMatthew Dillon 	 * Remove corrupt packages before continuing
540eea2aa9aSMatthew Dillon 	 */
541eea2aa9aSMatthew Dillon 	if (remove_corrupt) {
542eea2aa9aSMatthew Dillon 		list_tail = &list;
543eea2aa9aSMatthew Dillon 		while ((scan = *list_tail) != NULL) {
544eea2aa9aSMatthew Dillon 			if (scan->flags & PKGF_CORRUPT)
545eea2aa9aSMatthew Dillon 				*list_tail = scan->bnext;
546eea2aa9aSMatthew Dillon 			else
547eea2aa9aSMatthew Dillon 				list_tail = &scan->bnext;
548eea2aa9aSMatthew Dillon 		}
549eea2aa9aSMatthew Dillon 	}
550eea2aa9aSMatthew Dillon 
551eea2aa9aSMatthew Dillon 	/*
5528e25f19bSMatthew Dillon 	 * Scan our binary distributions and related dependencies looking
5538e25f19bSMatthew Dillon 	 * for any packages that have already been built.
5548e25f19bSMatthew Dillon 	 */
5558e25f19bSMatthew Dillon 	initbulk(childGetBinaryDistInfo, MaxBulk);
5568e25f19bSMatthew Dillon 	total = scan_binary_repo(RepositoryPath);
5578e25f19bSMatthew Dillon 	count = 0;
5588e25f19bSMatthew Dillon 	printf("Scanning %d packages\n", total);
5598e25f19bSMatthew Dillon 
5608e25f19bSMatthew Dillon 	while ((bulk = getbulk()) != NULL) {
5618e25f19bSMatthew Dillon 		++count;
5628e25f19bSMatthew Dillon 		if ((count & 255) == 0) {
5638e25f19bSMatthew Dillon 			printf("%6.2f%%\r",
5648e25f19bSMatthew Dillon 				(double)count * 100.0 / (double)total + 0.001);
5658e25f19bSMatthew Dillon 			fflush(stdout);
5668e25f19bSMatthew Dillon 		}
5678e25f19bSMatthew Dillon 		freebulk(bulk);
5688e25f19bSMatthew Dillon 	}
5691645cafeSMatthew Dillon 	printf("100.00%%\n");
5708e25f19bSMatthew Dillon 	printf("\nTotal %d\n", count);
5718e25f19bSMatthew Dillon 	fflush(stdout);
5728e25f19bSMatthew Dillon 	donebulk();
5738e25f19bSMatthew Dillon 
5748e25f19bSMatthew Dillon 	printf("all done\n");
5758e25f19bSMatthew Dillon 
5768e25f19bSMatthew Dillon 	return list;
5778e25f19bSMatthew Dillon }
5788e25f19bSMatthew Dillon 
5798e25f19bSMatthew Dillon pkg_t *
580549987f1SMatthew Dillon GetPkgPkg(pkg_t **listp)
5818e25f19bSMatthew Dillon {
5828e25f19bSMatthew Dillon 	bulk_t *bulk;
5838e25f19bSMatthew Dillon 	pkg_t *scan;
584549987f1SMatthew Dillon 	pkg_t *s2;
5858e25f19bSMatthew Dillon 
586549987f1SMatthew Dillon 	for (scan = *listp; scan; scan = scan->bnext) {
5878e25f19bSMatthew Dillon 		if (strcmp(scan->portdir, "ports-mgmt/pkg") == 0)
5888e25f19bSMatthew Dillon 			return scan;
5898e25f19bSMatthew Dillon 	}
5908e25f19bSMatthew Dillon 
591f4094b20SMatthew Dillon 	/*
592f4094b20SMatthew Dillon 	 * This will force pkg to be built, but generally this code
593f4094b20SMatthew Dillon 	 * is not reached because the package list processing code
594f4094b20SMatthew Dillon 	 * adds ports-mgmt/pkg unconditionally.
595f4094b20SMatthew Dillon 	 */
5968e25f19bSMatthew Dillon 	initbulk(childGetPackageInfo, MaxBulk);
597f4094b20SMatthew Dillon 	queuebulk("ports-mgmt", "pkg", NULL, "x");
5988e25f19bSMatthew Dillon 	bulk = getbulk();
5998e25f19bSMatthew Dillon 	dassert(bulk, "Cannot find ports-mgmt/pkg");
6008e25f19bSMatthew Dillon 	scan = bulk->list;
6018e25f19bSMatthew Dillon 	bulk->list = NULL;
6028e25f19bSMatthew Dillon 	freebulk(bulk);
6038e25f19bSMatthew Dillon 	donebulk();
6048e25f19bSMatthew Dillon 
605549987f1SMatthew Dillon 
606549987f1SMatthew Dillon 	/*
607549987f1SMatthew Dillon 	 * Include added packages to the total and add the initial bulk
608549987f1SMatthew Dillon 	 * built packages to the list so they get counted.
609549987f1SMatthew Dillon 	 */
610549987f1SMatthew Dillon 	for (s2 = scan; s2->bnext; s2 = s2->bnext)
611549987f1SMatthew Dillon 		++BuildTotal;
612549987f1SMatthew Dillon 	for (s2 = scan; s2->bnext; s2 = s2->bnext)
613549987f1SMatthew Dillon 		;
614549987f1SMatthew Dillon 	s2->bnext = *listp;
615549987f1SMatthew Dillon 	*listp = scan;
616549987f1SMatthew Dillon 	++BuildTotal;
617549987f1SMatthew Dillon 
6188e25f19bSMatthew Dillon 	return scan;
6198e25f19bSMatthew Dillon }
6208e25f19bSMatthew Dillon 
6218e25f19bSMatthew Dillon /*
622a67bf8dbSMatthew Dillon  * Try to optimize the environment by supplying information that
623a67bf8dbSMatthew Dillon  * the ports system would generally have to run stuff to get on
624a67bf8dbSMatthew Dillon  * every package.
625a67bf8dbSMatthew Dillon  *
626a67bf8dbSMatthew Dillon  * See childOptimizeEnv() for the actual handling.  We execute
627a67bf8dbSMatthew Dillon  * a single make -V... -V... for ports-mgmt/pkg from within the
628a67bf8dbSMatthew Dillon  * bulk system (which handles the environment and disables
629a67bf8dbSMatthew Dillon  * /etc/make.conf), and we then call addbuildenv() as appropriate.
630a67bf8dbSMatthew Dillon  *
631a67bf8dbSMatthew Dillon  * _PERL5_FROM_BIN
632a67bf8dbSMatthew Dillon  * add others...
633a67bf8dbSMatthew Dillon  */
634a67bf8dbSMatthew Dillon void
635a67bf8dbSMatthew Dillon OptimizeEnv(void)
636a67bf8dbSMatthew Dillon {
637a67bf8dbSMatthew Dillon 	bulk_t *bulk;
638a67bf8dbSMatthew Dillon 
639a67bf8dbSMatthew Dillon 	initbulk(childOptimizeEnv, MaxBulk);
640a67bf8dbSMatthew Dillon 	queuebulk("ports-mgmt", "pkg", NULL, NULL);
641a67bf8dbSMatthew Dillon 	bulk = getbulk();
642a67bf8dbSMatthew Dillon 	freebulk(bulk);
643a67bf8dbSMatthew Dillon 	donebulk();
644a67bf8dbSMatthew Dillon }
645a67bf8dbSMatthew Dillon 
646a67bf8dbSMatthew Dillon /*
6478e25f19bSMatthew Dillon  * Run through the list resolving dependencies and constructing the topology
64877ac77e7SMatthew Dillon  * linkages.   This may append packages to the list.  Dependencies to dummy
64977ac77e7SMatthew Dillon  * nodes which do not specify a flavor do not need special handling, the
65077ac77e7SMatthew Dillon  * search code in build.c will properly follow the first flavor.
6518e25f19bSMatthew Dillon  */
6528e25f19bSMatthew Dillon static pkg_t *
6538e25f19bSMatthew Dillon resolveDeps(pkg_t *list, pkg_t ***list_tailp, int gentopo)
6548e25f19bSMatthew Dillon {
6558e25f19bSMatthew Dillon 	pkg_t *ret_list = NULL;
65677ac77e7SMatthew Dillon 	pkg_t *scan;
65777ac77e7SMatthew Dillon 	pkg_t *use;
6588e25f19bSMatthew Dillon 	bulk_t *bulk;
6598e25f19bSMatthew Dillon 
6608e25f19bSMatthew Dillon 	for (scan = list; scan; scan = scan->bnext) {
66177ac77e7SMatthew Dillon 		use = pkg_find(scan->portdir);
66277ac77e7SMatthew Dillon 		resolveFlavors(use, scan->flavors, gentopo);
66377ac77e7SMatthew Dillon 		resolveDepString(use, scan->fetch_deps,
66463fcce5bSMatthew Dillon 				 gentopo, DEP_TYPE_FETCH);
66577ac77e7SMatthew Dillon 		resolveDepString(use, scan->ext_deps,
66663fcce5bSMatthew Dillon 				 gentopo, DEP_TYPE_EXT);
66777ac77e7SMatthew Dillon 		resolveDepString(use, scan->patch_deps,
66863fcce5bSMatthew Dillon 				 gentopo, DEP_TYPE_PATCH);
66977ac77e7SMatthew Dillon 		resolveDepString(use, scan->build_deps,
67063fcce5bSMatthew Dillon 				 gentopo, DEP_TYPE_BUILD);
67177ac77e7SMatthew Dillon 		resolveDepString(use, scan->lib_deps,
67263fcce5bSMatthew Dillon 				 gentopo, DEP_TYPE_LIB);
67377ac77e7SMatthew Dillon 		resolveDepString(use, scan->run_deps,
67463fcce5bSMatthew Dillon 				 gentopo, DEP_TYPE_RUN);
6758e25f19bSMatthew Dillon 	}
6768e25f19bSMatthew Dillon 
6778e25f19bSMatthew Dillon 	/*
6788e25f19bSMatthew Dillon 	 * No bulk ops are queued when doing the final topology
6798e25f19bSMatthew Dillon 	 * generation.
68077ac77e7SMatthew Dillon 	 *
68177ac77e7SMatthew Dillon 	 * Avoid entering duplicate results from the bulk ops.  Duplicate
68277ac77e7SMatthew Dillon 	 * results are mostly filtered out, but not always.  A dummy node
68377ac77e7SMatthew Dillon 	 * representing multiple flavors will parse-out the flavors
6848e25f19bSMatthew Dillon 	 */
6858e25f19bSMatthew Dillon 	if (gentopo)
6868e25f19bSMatthew Dillon 		return NULL;
6878e25f19bSMatthew Dillon 	while ((bulk = getbulk()) != NULL) {
6888e25f19bSMatthew Dillon 		if (bulk->list) {
6898e25f19bSMatthew Dillon 			if (ret_list == NULL)
6908e25f19bSMatthew Dillon 				ret_list = bulk->list;
6918e25f19bSMatthew Dillon 			**list_tailp = bulk->list;
6928e25f19bSMatthew Dillon 			bulk->list = NULL;
69377ac77e7SMatthew Dillon 			while ((scan = **list_tailp) != NULL) {
69477ac77e7SMatthew Dillon 				pkg_enter(scan);
69577ac77e7SMatthew Dillon 				*list_tailp = &scan->bnext;
6968e25f19bSMatthew Dillon 			}
6978e25f19bSMatthew Dillon 		}
6988e25f19bSMatthew Dillon 		freebulk(bulk);
6998e25f19bSMatthew Dillon 	}
7008e25f19bSMatthew Dillon 	return (ret_list);
7018e25f19bSMatthew Dillon }
7028e25f19bSMatthew Dillon 
70377ac77e7SMatthew Dillon /*
70477ac77e7SMatthew Dillon  * Resolve a generic node that has flavors, queue to retrieve info for
70577ac77e7SMatthew Dillon  * each flavor and setup linkages as appropriate.
70677ac77e7SMatthew Dillon  */
70777ac77e7SMatthew Dillon static void
70877ac77e7SMatthew Dillon resolveFlavors(pkg_t *pkg, char *flavors, int gentopo)
70977ac77e7SMatthew Dillon {
71077ac77e7SMatthew Dillon 	char *flavor_base;
71177ac77e7SMatthew Dillon 	char *flavor_scan;
71277ac77e7SMatthew Dillon 	char *flavor;
71377ac77e7SMatthew Dillon 	char *portdir;
71477ac77e7SMatthew Dillon 	char *s1;
71577ac77e7SMatthew Dillon 	char *s2;
71677ac77e7SMatthew Dillon 	pkg_t *dpkg;
71777ac77e7SMatthew Dillon 	pkglink_t *link;
71877ac77e7SMatthew Dillon 
71977ac77e7SMatthew Dillon 	if ((pkg->flags & PKGF_DUMMY) == 0)
72077ac77e7SMatthew Dillon 		return;
72177ac77e7SMatthew Dillon 	if (pkg->flavors == NULL || pkg->flavors[0] == 0)
72277ac77e7SMatthew Dillon 		return;
72377ac77e7SMatthew Dillon 	flavor_base = strdup(flavors);
72477ac77e7SMatthew Dillon 	flavor_scan = flavor_base;
72577ac77e7SMatthew Dillon 
72677ac77e7SMatthew Dillon 	for (;;) {
72777ac77e7SMatthew Dillon 		do {
72877ac77e7SMatthew Dillon 			flavor = strsep(&flavor_scan, " \t");
72977ac77e7SMatthew Dillon 		} while (flavor && *flavor == 0);
73077ac77e7SMatthew Dillon 		if (flavor == NULL)
73177ac77e7SMatthew Dillon 			break;
73277ac77e7SMatthew Dillon 
73377ac77e7SMatthew Dillon 		/*
73477ac77e7SMatthew Dillon 		 * Iterate each flavor generating "s1/s2@flavor".
73577ac77e7SMatthew Dillon 		 *
73677ac77e7SMatthew Dillon 		 * queuebulk() info for each flavor, and set-up the
73777ac77e7SMatthew Dillon 		 * linkages in the topology generation pass.
73877ac77e7SMatthew Dillon 		 */
73977ac77e7SMatthew Dillon 		asprintf(&portdir, "%s@%s", pkg->portdir, flavor);
74077ac77e7SMatthew Dillon 		s1 = strdup(pkg->portdir);
74177ac77e7SMatthew Dillon 		s2 = strchr(s1, '/');
74277ac77e7SMatthew Dillon 		*s2++ = 0;
74377ac77e7SMatthew Dillon 
74477ac77e7SMatthew Dillon 		dpkg = pkg_find(portdir);
74577ac77e7SMatthew Dillon 		if (dpkg && gentopo) {
74677ac77e7SMatthew Dillon 			/*
74777ac77e7SMatthew Dillon 			 * Setup linkages
74877ac77e7SMatthew Dillon 			 */
74977ac77e7SMatthew Dillon 			free(portdir);
75077ac77e7SMatthew Dillon 
75177ac77e7SMatthew Dillon 			link = calloc(1, sizeof(*link));
75277ac77e7SMatthew Dillon 			link->pkg = dpkg;
75377ac77e7SMatthew Dillon 			link->next = &pkg->idepon_list;
75477ac77e7SMatthew Dillon 			link->prev = pkg->idepon_list.prev;
75577ac77e7SMatthew Dillon 			link->next->prev = link;
75677ac77e7SMatthew Dillon 			link->prev->next = link;
75777ac77e7SMatthew Dillon 			link->dep_type = DEP_TYPE_BUILD;
75877ac77e7SMatthew Dillon 
75977ac77e7SMatthew Dillon 			link = calloc(1, sizeof(*link));
76077ac77e7SMatthew Dillon 			link->pkg = pkg;
76177ac77e7SMatthew Dillon 			link->next = &dpkg->deponi_list;
76277ac77e7SMatthew Dillon 			link->prev = dpkg->deponi_list.prev;
76377ac77e7SMatthew Dillon 			link->next->prev = link;
76477ac77e7SMatthew Dillon 			link->prev->next = link;
76577ac77e7SMatthew Dillon 			link->dep_type = DEP_TYPE_BUILD;
76677ac77e7SMatthew Dillon 			++dpkg->depi_count;
76777ac77e7SMatthew Dillon 		} else if (gentopo == 0 && dpkg == NULL) {
76877ac77e7SMatthew Dillon 			/*
76977ac77e7SMatthew Dillon 			 * Use a place-holder to prevent duplicate
77077ac77e7SMatthew Dillon 			 * dependencies from being processed.  The placeholder
77177ac77e7SMatthew Dillon 			 * will be replaced by the actual dependency.
77277ac77e7SMatthew Dillon 			 */
77377ac77e7SMatthew Dillon 			dpkg = allocpkg();
77477ac77e7SMatthew Dillon 			dpkg->portdir = portdir;
77577ac77e7SMatthew Dillon 			dpkg->flags = PKGF_PLACEHOLD;
77677ac77e7SMatthew Dillon 			pkg_enter(dpkg);
77777ac77e7SMatthew Dillon 			queuebulk(s1, s2, flavor, NULL);
77877ac77e7SMatthew Dillon 		}
77977ac77e7SMatthew Dillon 		free(s1);
78077ac77e7SMatthew Dillon 	}
78177ac77e7SMatthew Dillon 	free(flavor_base);
78277ac77e7SMatthew Dillon }
78377ac77e7SMatthew Dillon 
7848e25f19bSMatthew Dillon static void
78563fcce5bSMatthew Dillon resolveDepString(pkg_t *pkg, char *depstr, int gentopo, int dep_type)
7868e25f19bSMatthew Dillon {
7878e25f19bSMatthew Dillon 	char *copy_base;
7888e25f19bSMatthew Dillon 	char *copy;
7898e25f19bSMatthew Dillon 	char *dep;
79024b60d12SMatthew Dillon 	char *log_component;
7918e25f19bSMatthew Dillon 	char *sep;
7928e25f19bSMatthew Dillon 	char *tag;
7938e25f19bSMatthew Dillon 	char *flavor;
7948e25f19bSMatthew Dillon 	pkg_t *dpkg;
7958e25f19bSMatthew Dillon 
7968e25f19bSMatthew Dillon 	if (depstr == NULL || depstr[0] == 0)
7978e25f19bSMatthew Dillon 		return;
7988e25f19bSMatthew Dillon 
7998e25f19bSMatthew Dillon 	copy_base = strdup(depstr);
8008e25f19bSMatthew Dillon 	copy = copy_base;
80124b60d12SMatthew Dillon 	log_component = copy;
8028e25f19bSMatthew Dillon 
8038e25f19bSMatthew Dillon 	for (;;) {
8048e25f19bSMatthew Dillon 		do {
8058e25f19bSMatthew Dillon 			dep = strsep(&copy, " \t");
8068e25f19bSMatthew Dillon 		} while (dep && *dep == 0);
8078e25f19bSMatthew Dillon 		if (dep == NULL)
8088e25f19bSMatthew Dillon 			break;
8096fd67931SMatthew Dillon 
8106fd67931SMatthew Dillon 		/*
8116fd67931SMatthew Dillon 		 * Ignore dependencies prefixed with ${NONEXISTENT}
8126fd67931SMatthew Dillon 		 */
8136fd67931SMatthew Dillon 		if (strncmp(dep, "/nonexistent:", 13) == 0)
8146fd67931SMatthew Dillon 			continue;
8156fd67931SMatthew Dillon 
81624b60d12SMatthew Dillon 		log_component = dep;
8178e25f19bSMatthew Dillon 		dep = strchr(dep, ':');
8188e25f19bSMatthew Dillon 		if (dep == NULL || *dep != ':') {
81993fe0327SMatthew Dillon 			printf("Error parsing %s dependency for "
82024b60d12SMatthew Dillon 			       "%s: '%s' at index %zd '%s' "
82124b60d12SMatthew Dillon 			       "(looking for ':')\n",
82293fe0327SMatthew Dillon 			       deptype2str(dep_type),
823baf7c614SMatthew Dillon 			       pkg->portdir, depstr,
82424b60d12SMatthew Dillon 			       log_component - copy_base,
82524b60d12SMatthew Dillon 			       log_component);
8268e25f19bSMatthew Dillon 			continue;
8278e25f19bSMatthew Dillon 		}
8288e25f19bSMatthew Dillon 		++dep;
8298e25f19bSMatthew Dillon 
8308e25f19bSMatthew Dillon 		/*
8318e25f19bSMatthew Dillon 		 * Strip-off any DPortsPath prefix.  EXTRACT_DEPENDS
8328e25f19bSMatthew Dillon 		 * often (always?) generates this prefix.
8338e25f19bSMatthew Dillon 		 */
8348e25f19bSMatthew Dillon 		if (strncmp(dep, DPortsPath, strlen(DPortsPath)) == 0) {
8358e25f19bSMatthew Dillon 			dep += strlen(DPortsPath);
8368e25f19bSMatthew Dillon 			if (*dep == '/')
8378e25f19bSMatthew Dillon 				++dep;
8388e25f19bSMatthew Dillon 		}
8398e25f19bSMatthew Dillon 
8408e25f19bSMatthew Dillon 		/*
8418e25f19bSMatthew Dillon 		 * Strip-off any tag (such as :patch).  We don't try to
8428e25f19bSMatthew Dillon 		 * organize dependencies at this fine a grain (for now).
8438e25f19bSMatthew Dillon 		 */
8448e25f19bSMatthew Dillon 		tag = strchr(dep, ':');
8458e25f19bSMatthew Dillon 		if (tag)
8468e25f19bSMatthew Dillon 			*tag++ = 0;
84724b60d12SMatthew Dillon 		log_component = dep;
8488e25f19bSMatthew Dillon 
8498e25f19bSMatthew Dillon 		/*
8508e25f19bSMatthew Dillon 		 * Locate the dependency
8518e25f19bSMatthew Dillon 		 */
8528e25f19bSMatthew Dillon 		if ((dpkg = pkg_find(dep)) != NULL) {
8538e25f19bSMatthew Dillon 			if (gentopo) {
8548e25f19bSMatthew Dillon 				pkglink_t *link;
8558e25f19bSMatthew Dillon 
8568e25f19bSMatthew Dillon 				/*
8578e25f19bSMatthew Dillon 				 * NOTE: idep_count is calculated recursively
8588e25f19bSMatthew Dillon 				 *	 at build-time
8598e25f19bSMatthew Dillon 				 */
8608e25f19bSMatthew Dillon 				ddprintf(0, "Add Dependency %s -> %s\n",
8618e25f19bSMatthew Dillon 					pkg->portdir, dpkg->portdir);
8628e25f19bSMatthew Dillon 				link = calloc(1, sizeof(*link));
8638e25f19bSMatthew Dillon 				link->pkg = dpkg;
8648e25f19bSMatthew Dillon 				link->next = &pkg->idepon_list;
8658e25f19bSMatthew Dillon 				link->prev = pkg->idepon_list.prev;
8668e25f19bSMatthew Dillon 				link->next->prev = link;
8678e25f19bSMatthew Dillon 				link->prev->next = link;
86863fcce5bSMatthew Dillon 				link->dep_type = dep_type;
8698e25f19bSMatthew Dillon 
8708e25f19bSMatthew Dillon 				link = calloc(1, sizeof(*link));
8718e25f19bSMatthew Dillon 				link->pkg = pkg;
8728e25f19bSMatthew Dillon 				link->next = &dpkg->deponi_list;
8738e25f19bSMatthew Dillon 				link->prev = dpkg->deponi_list.prev;
8748e25f19bSMatthew Dillon 				link->next->prev = link;
8758e25f19bSMatthew Dillon 				link->prev->next = link;
87663fcce5bSMatthew Dillon 				link->dep_type = dep_type;
8778e25f19bSMatthew Dillon 				++dpkg->depi_count;
8788e25f19bSMatthew Dillon 			}
8798e25f19bSMatthew Dillon 			continue;
8808e25f19bSMatthew Dillon 		}
8818e25f19bSMatthew Dillon 
8828e25f19bSMatthew Dillon 		/*
8838e25f19bSMatthew Dillon 		 * This shouldn't happen because we already took a first
8848e25f19bSMatthew Dillon 		 * pass and should have generated the pkgs.
8858e25f19bSMatthew Dillon 		 */
8868e25f19bSMatthew Dillon 		if (gentopo) {
8878e25f19bSMatthew Dillon 			printf("Topology Generate failed for %s: %s\n",
8888e25f19bSMatthew Dillon 				pkg->portdir, copy_base);
8898e25f19bSMatthew Dillon 			continue;
8908e25f19bSMatthew Dillon 		}
8918e25f19bSMatthew Dillon 
8928e25f19bSMatthew Dillon 		/*
8938e25f19bSMatthew Dillon 		 * Separate out the two dports directory components and
8948e25f19bSMatthew Dillon 		 * extract the optional '@flavor' specification.
8958e25f19bSMatthew Dillon 		 */
8968e25f19bSMatthew Dillon 		sep = strchr(dep, '/');
8978e25f19bSMatthew Dillon 		if (sep == NULL) {
89893fe0327SMatthew Dillon 			printf("Error parsing %s dependency for "
89924b60d12SMatthew Dillon 			       "%s: '%s' at index %zd '%s' "
90024b60d12SMatthew Dillon 			       "(looking for '/')\n",
90193fe0327SMatthew Dillon 			       deptype2str(dep_type),
902baf7c614SMatthew Dillon 			       pkg->portdir, depstr,
90324b60d12SMatthew Dillon 			       log_component - copy_base,
90424b60d12SMatthew Dillon 			       log_component);
9058e25f19bSMatthew Dillon 			continue;
9068e25f19bSMatthew Dillon 		}
9078e25f19bSMatthew Dillon 		*sep++ = 0;
9088e25f19bSMatthew Dillon 
90995f08ce8SMatthew Dillon 		/*
91095f08ce8SMatthew Dillon 		 * The flavor hangs off the separator, not the tag
91195f08ce8SMatthew Dillon 		 */
91295f08ce8SMatthew Dillon 		flavor = strrchr(sep, '@');
91395f08ce8SMatthew Dillon #if 0
9148e25f19bSMatthew Dillon 		if (tag)
9158e25f19bSMatthew Dillon 			flavor = strrchr(tag, '@');
9168e25f19bSMatthew Dillon 		else
9178e25f19bSMatthew Dillon 			flavor = strrchr(sep, '@');
91895f08ce8SMatthew Dillon #endif
9198e25f19bSMatthew Dillon 		if (flavor)
9208e25f19bSMatthew Dillon 			*flavor++ = 0;
9218e25f19bSMatthew Dillon 
9228e25f19bSMatthew Dillon 		if (flavor)
9238e25f19bSMatthew Dillon 			ddprintf(0, "QUEUE DEPENDENCY FROM PKG %s: %s/%s@%s\n",
9248e25f19bSMatthew Dillon 			       pkg->portdir, dep, sep, flavor);
9258e25f19bSMatthew Dillon 		else
9268e25f19bSMatthew Dillon 			ddprintf(0, "QUEUE DEPENDENCY FROM PKG %s: %s/%s\n",
9278e25f19bSMatthew Dillon 			       pkg->portdir, dep, sep);
9288e25f19bSMatthew Dillon 
9298e25f19bSMatthew Dillon 		/*
9308e25f19bSMatthew Dillon 		 * Use a place-holder to prevent duplicate dependencies from
9318e25f19bSMatthew Dillon 		 * being processed.  The placeholder will be replaced by
9328e25f19bSMatthew Dillon 		 * the actual dependency.
9338e25f19bSMatthew Dillon 		 */
9348e25f19bSMatthew Dillon 		dpkg = allocpkg();
9358e25f19bSMatthew Dillon 		if (flavor)
9368e25f19bSMatthew Dillon 			asprintf(&dpkg->portdir, "%s/%s@%s", dep, sep, flavor);
9378e25f19bSMatthew Dillon 		else
9388e25f19bSMatthew Dillon 			asprintf(&dpkg->portdir, "%s/%s", dep, sep);
9398e25f19bSMatthew Dillon 		dpkg->flags = PKGF_PLACEHOLD;
9408e25f19bSMatthew Dillon 		pkg_enter(dpkg);
9418e25f19bSMatthew Dillon 
9428e25f19bSMatthew Dillon 		queuebulk(dep, sep, flavor, NULL);
9438e25f19bSMatthew Dillon 	}
9448e25f19bSMatthew Dillon 	free(copy_base);
9458e25f19bSMatthew Dillon }
9468e25f19bSMatthew Dillon 
9478e25f19bSMatthew Dillon void
9488e25f19bSMatthew Dillon FreePackageList(pkg_t *pkgs __unused)
9498e25f19bSMatthew Dillon {
9508e25f19bSMatthew Dillon 	dfatal("not implemented");
9518e25f19bSMatthew Dillon }
9528e25f19bSMatthew Dillon 
9538e25f19bSMatthew Dillon /*
9548e25f19bSMatthew Dillon  * Scan some or all dports to allocate the related pkg structure.  Dependencies
9558e25f19bSMatthew Dillon  * are stored but not processed.
9568e25f19bSMatthew Dillon  *
9578e25f19bSMatthew Dillon  * Threaded function
9588e25f19bSMatthew Dillon  */
9598e25f19bSMatthew Dillon static void
9608e25f19bSMatthew Dillon childGetPackageInfo(bulk_t *bulk)
9618e25f19bSMatthew Dillon {
9628e25f19bSMatthew Dillon 	pkg_t *pkg;
9638e25f19bSMatthew Dillon 	char *flavor;
9648e25f19bSMatthew Dillon 	char *ptr;
9658e25f19bSMatthew Dillon 	FILE *fp;
9668e25f19bSMatthew Dillon 	int line;
9678e25f19bSMatthew Dillon 	size_t len;
9686fd67931SMatthew Dillon 	char *portpath;
9696fd67931SMatthew Dillon 	char *flavarg;
970*5d0718a8SMatthew Dillon 	char *localbase;
9716fd67931SMatthew Dillon 	const char *cav[MAXCAC];
9726fd67931SMatthew Dillon 	pid_t pid;
9736fd67931SMatthew Dillon 	int cac;
9748e25f19bSMatthew Dillon 
9758e25f19bSMatthew Dillon 	/*
9768e25f19bSMatthew Dillon 	 * If the package has flavors we will loop on each one.  If a flavor
9778e25f19bSMatthew Dillon 	 * is not passed in s3 we will loop on all flavors, otherwise we will
9788e25f19bSMatthew Dillon 	 * only process the passed-in flavor.
9798e25f19bSMatthew Dillon 	 */
9808e25f19bSMatthew Dillon 	flavor = bulk->s3;	/* usually NULL */
9818e25f19bSMatthew Dillon 
9828e25f19bSMatthew Dillon 	bulk->list = NULL;
98377ac77e7SMatthew Dillon 
9846fd67931SMatthew Dillon 	asprintf(&portpath, "%s/%s/%s", DPortsPath, bulk->s1, bulk->s2);
9856fd67931SMatthew Dillon 	if (flavor)
9866fd67931SMatthew Dillon 		asprintf(&flavarg, "FLAVOR=%s", flavor);
9876fd67931SMatthew Dillon 	else
9886fd67931SMatthew Dillon 		flavarg = NULL;
9896fd67931SMatthew Dillon 
9906fd67931SMatthew Dillon 	cac = 0;
9916fd67931SMatthew Dillon 	cav[cac++] = MAKE_BINARY;
9926fd67931SMatthew Dillon 	cav[cac++] = "-C";
9936fd67931SMatthew Dillon 	cav[cac++] = portpath;
9946fd67931SMatthew Dillon 	if (flavarg)
9956fd67931SMatthew Dillon 		cav[cac++] = flavarg;
996*5d0718a8SMatthew Dillon 
997*5d0718a8SMatthew Dillon 	/*
998*5d0718a8SMatthew Dillon 	 * Prevent postgresql, mysql, and other package Makefile tests
999*5d0718a8SMatthew Dillon 	 * from accessing the host system's /usr/local by setting LOCALBASE
1000*5d0718a8SMatthew Dillon 	 * to an empty directory.
1001*5d0718a8SMatthew Dillon 	 */
1002*5d0718a8SMatthew Dillon 	asprintf(&localbase, "LOCALBASE=%s/empty", BuildBase);
1003*5d0718a8SMatthew Dillon 	cav[cac++] = localbase;
1004*5d0718a8SMatthew Dillon 
1005*5d0718a8SMatthew Dillon 	/*
1006*5d0718a8SMatthew Dillon 	 * Variables we need to retrieve (order is specific to the switch
1007*5d0718a8SMatthew Dillon 	 * below)
1008*5d0718a8SMatthew Dillon 	 */
10096fd67931SMatthew Dillon 	cav[cac++] = "-VPKGVERSION";
10106fd67931SMatthew Dillon 	cav[cac++] = "-VPKGFILE:T";
10116ec1f604SMatthew Dillon 	cav[cac++] = "-VALLFILES";
10126fd67931SMatthew Dillon 	cav[cac++] = "-VDIST_SUBDIR";
10136fd67931SMatthew Dillon 	cav[cac++] = "-VMAKE_JOBS_NUMBER";
10146fd67931SMatthew Dillon 	cav[cac++] = "-VIGNORE";
10156fd67931SMatthew Dillon 	cav[cac++] = "-VFETCH_DEPENDS";
10166fd67931SMatthew Dillon 	cav[cac++] = "-VEXTRACT_DEPENDS";
10176fd67931SMatthew Dillon 	cav[cac++] = "-VPATCH_DEPENDS";
10186fd67931SMatthew Dillon 	cav[cac++] = "-VBUILD_DEPENDS";
10196fd67931SMatthew Dillon 	cav[cac++] = "-VLIB_DEPENDS";
10206fd67931SMatthew Dillon 	cav[cac++] = "-VRUN_DEPENDS";
10216fd67931SMatthew Dillon 	cav[cac++] = "-VSELECTED_OPTIONS";
10226fd67931SMatthew Dillon 	cav[cac++] = "-VDESELECTED_OPTIONS";
10236fd67931SMatthew Dillon 	cav[cac++] = "-VUSE_LINUX";
10246fd67931SMatthew Dillon 	cav[cac++] = "-VFLAVORS";
1025f4094b20SMatthew Dillon 	cav[cac++] = "-VUSES";
10266fd67931SMatthew Dillon 
1027f9d29536SMatthew Dillon 	fp = dexec_open(portpath + strlen(DPortsPath) + 1, cav, cac,
1028f9d29536SMatthew Dillon 			&pid, NULL, 1, 1);
10296fd67931SMatthew Dillon 	freestrp(&flavarg);
1030*5d0718a8SMatthew Dillon 	freestrp(&localbase);
10318e25f19bSMatthew Dillon 
10328e25f19bSMatthew Dillon 	pkg = allocpkg();
10338e25f19bSMatthew Dillon 	if (flavor)
10348e25f19bSMatthew Dillon 		asprintf(&pkg->portdir, "%s/%s@%s", bulk->s1, bulk->s2, flavor);
10358e25f19bSMatthew Dillon 	else
10368e25f19bSMatthew Dillon 		asprintf(&pkg->portdir, "%s/%s", bulk->s1, bulk->s2);
10378e25f19bSMatthew Dillon 
10386fd67931SMatthew Dillon 	line = 1;
10398e25f19bSMatthew Dillon 	while ((ptr = fgetln(fp, &len)) != NULL) {
10408e25f19bSMatthew Dillon 		if (len == 0 || ptr[len-1] != '\n') {
10418e25f19bSMatthew Dillon 			dfatal("Bad package info for %s/%s response line %d",
10428e25f19bSMatthew Dillon 			       bulk->s1, bulk->s2, line);
10438e25f19bSMatthew Dillon 		}
10448e25f19bSMatthew Dillon 		ptr[--len] = 0;
10458e25f19bSMatthew Dillon 
10468e25f19bSMatthew Dillon 		switch(line) {
10478e25f19bSMatthew Dillon 		case 1:		/* PKGVERSION */
10488e25f19bSMatthew Dillon 			asprintf(&pkg->version, "%s", ptr);
10498e25f19bSMatthew Dillon 			break;
10508e25f19bSMatthew Dillon 		case 2:		/* PKGFILE */
10518e25f19bSMatthew Dillon 			asprintf(&pkg->pkgfile, "%s", ptr);
10528e25f19bSMatthew Dillon 			break;
10536ec1f604SMatthew Dillon 		case 3:		/* ALLFILES (aka DISTFILES + patch files) */
10541645cafeSMatthew Dillon 			asprintf(&pkg->distfiles, "%s", ptr);
10551645cafeSMatthew Dillon 			break;
10561645cafeSMatthew Dillon 		case 4:		/* DIST_SUBDIR */
10574ea2ee4dSMatthew Dillon 			pkg->distsubdir = strdup_or_null(ptr);
10581645cafeSMatthew Dillon 			break;
10591645cafeSMatthew Dillon 		case 5:		/* MAKE_JOBS_NUMBER */
10608e25f19bSMatthew Dillon 			pkg->make_jobs_number = strtol(ptr, NULL, 0);
10618e25f19bSMatthew Dillon 			break;
10621645cafeSMatthew Dillon 		case 6:		/* IGNORE */
10634ea2ee4dSMatthew Dillon 			pkg->ignore = strdup_or_null(ptr);
10648e25f19bSMatthew Dillon 			break;
10651645cafeSMatthew Dillon 		case 7:		/* FETCH_DEPENDS */
10664ea2ee4dSMatthew Dillon 			pkg->fetch_deps = strdup_or_null(ptr);
10678e25f19bSMatthew Dillon 			break;
10681645cafeSMatthew Dillon 		case 8:		/* EXTRACT_DEPENDS */
10694ea2ee4dSMatthew Dillon 			pkg->ext_deps = strdup_or_null(ptr);
10708e25f19bSMatthew Dillon 			break;
10711645cafeSMatthew Dillon 		case 9:		/* PATCH_DEPENDS */
10724ea2ee4dSMatthew Dillon 			pkg->patch_deps = strdup_or_null(ptr);
10738e25f19bSMatthew Dillon 			break;
10741645cafeSMatthew Dillon 		case 10:	/* BUILD_DEPENDS */
10754ea2ee4dSMatthew Dillon 			pkg->build_deps = strdup_or_null(ptr);
10768e25f19bSMatthew Dillon 			break;
10771645cafeSMatthew Dillon 		case 11:	/* LIB_DEPENDS */
10784ea2ee4dSMatthew Dillon 			pkg->lib_deps = strdup_or_null(ptr);
10798e25f19bSMatthew Dillon 			break;
10801645cafeSMatthew Dillon 		case 12:	/* RUN_DEPENDS */
10814ea2ee4dSMatthew Dillon 			pkg->run_deps = strdup_or_null(ptr);
10828e25f19bSMatthew Dillon 			break;
10831645cafeSMatthew Dillon 		case 13:	/* SELECTED_OPTIONS */
10844ea2ee4dSMatthew Dillon 			pkg->pos_options = strdup_or_null(ptr);
10858e25f19bSMatthew Dillon 			break;
10861645cafeSMatthew Dillon 		case 14:	/* DESELECTED_OPTIONS */
10874ea2ee4dSMatthew Dillon 			pkg->neg_options = strdup_or_null(ptr);
10888e25f19bSMatthew Dillon 			break;
10891645cafeSMatthew Dillon 		case 15:	/* USE_LINUX */
10908e25f19bSMatthew Dillon 			if (ptr[0])
10918e25f19bSMatthew Dillon 				pkg->use_linux = 1;
10928e25f19bSMatthew Dillon 			break;
10931645cafeSMatthew Dillon 		case 16:	/* FLAVORS */
10948e25f19bSMatthew Dillon 			asprintf(&pkg->flavors, "%s", ptr);
10958e25f19bSMatthew Dillon 			break;
1096f4094b20SMatthew Dillon 		case 17:	/* USES */
1097f4094b20SMatthew Dillon 			asprintf(&pkg->uses, "%s", ptr);
1098f4094b20SMatthew Dillon 			if (strstr(pkg->uses, "metaport"))
1099f4094b20SMatthew Dillon 				pkg->flags |= PKGF_META;
1100f4094b20SMatthew Dillon 			break;
11018e25f19bSMatthew Dillon 		default:
11028e25f19bSMatthew Dillon 			printf("EXTRA LINE: %s\n", ptr);
11038e25f19bSMatthew Dillon 			break;
11048e25f19bSMatthew Dillon 		}
11058e25f19bSMatthew Dillon 		++line;
11068e25f19bSMatthew Dillon 	}
11078e25f19bSMatthew Dillon 	if (line == 1) {
11088e25f19bSMatthew Dillon 		printf("DPort not found: %s/%s\n", bulk->s1, bulk->s2);
11098e25f19bSMatthew Dillon 		pkg->flags |= PKGF_NOTFOUND;
1110f4094b20SMatthew Dillon 	} else if (line != 17 + 1) {
11118e25f19bSMatthew Dillon 		printf("DPort corrupt: %s/%s\n", bulk->s1, bulk->s2);
11128e25f19bSMatthew Dillon 		pkg->flags |= PKGF_CORRUPT;
11138e25f19bSMatthew Dillon 	}
11146fd67931SMatthew Dillon 	if (dexec_close(fp, pid)) {
11156fd67931SMatthew Dillon 		printf("make -V* command for %s/%s failed\n",
11166fd67931SMatthew Dillon 			bulk->s1, bulk->s2);
11176fd67931SMatthew Dillon 		pkg->flags |= PKGF_CORRUPT;
11186fd67931SMatthew Dillon 	}
11198e25f19bSMatthew Dillon 	ddassert(bulk->s1);
11208e25f19bSMatthew Dillon 
11218e25f19bSMatthew Dillon 	/*
1122710838f7SMatthew Dillon 	 * DEBUGSTOP mode
1123710838f7SMatthew Dillon 	 */
1124710838f7SMatthew Dillon 	if (bulk->s4 && bulk->s4[0] == 'd')
1125710838f7SMatthew Dillon 		pkg->flags |= PKGF_DEBUGSTOP;
1126710838f7SMatthew Dillon 
1127710838f7SMatthew Dillon 	/*
112877ac77e7SMatthew Dillon 	 * Mark as a dummy node, the front-end will iterate the flavors
112977ac77e7SMatthew Dillon 	 * and create sub-nodes for us.
11308e25f19bSMatthew Dillon 	 *
113177ac77e7SMatthew Dillon 	 * Get rid of elements returned that are for the first flavor.
113277ac77e7SMatthew Dillon 	 * We are creating a dummy node here, not the node for the first
113377ac77e7SMatthew Dillon 	 * flavor.
11348e25f19bSMatthew Dillon 	 */
113577ac77e7SMatthew Dillon 	if (flavor == NULL && pkg->flavors && pkg->flavors[0]) {
11368e25f19bSMatthew Dillon 		pkg->flags |= PKGF_DUMMY;
11378e25f19bSMatthew Dillon 		freestrp(&pkg->fetch_deps);
11388e25f19bSMatthew Dillon 		freestrp(&pkg->ext_deps);
11398e25f19bSMatthew Dillon 		freestrp(&pkg->patch_deps);
11408e25f19bSMatthew Dillon 		freestrp(&pkg->build_deps);
11418e25f19bSMatthew Dillon 		freestrp(&pkg->lib_deps);
11428e25f19bSMatthew Dillon 		freestrp(&pkg->run_deps);
11438e25f19bSMatthew Dillon 		freestrp(&pkg->pkgfile);
11448e25f19bSMatthew Dillon 	}
11458e25f19bSMatthew Dillon 
11468e25f19bSMatthew Dillon 	/*
1147b6bd007bSMatthew Dillon 	 * Checksum the port directory tree.  This just rollsup crcs of the
1148b6bd007bSMatthew Dillon 	 * path names and a few stat fields (mtime, size) in order to detect
1149b6bd007bSMatthew Dillon 	 * if any modification has been made to the port.
1150b6bd007bSMatthew Dillon 	 */
1151b6bd007bSMatthew Dillon 	pkg->crc32 = crcDirTree(portpath);
1152b6bd007bSMatthew Dillon 
1153b6bd007bSMatthew Dillon 	/*
115477ac77e7SMatthew Dillon 	 * Only one pkg is put on the return list now.  This code no
115577ac77e7SMatthew Dillon 	 * longer creates pseudo-nodes for flavors (the frontend requests
115677ac77e7SMatthew Dillon 	 * each flavor instead).
11578e25f19bSMatthew Dillon 	 */
115877ac77e7SMatthew Dillon 	bulk->list = pkg;
1159b6bd007bSMatthew Dillon 	free(portpath);
11608e25f19bSMatthew Dillon }
11618e25f19bSMatthew Dillon 
11628e25f19bSMatthew Dillon /*
11638e25f19bSMatthew Dillon  * Query the package (at least to make sure it hasn't been truncated)
11648e25f19bSMatthew Dillon  * and mark it as PACKAGED if found.
11658e25f19bSMatthew Dillon  *
1166753e4c44SMatthew Dillon  * This is a pre-req prior to doing builds, so we cannot assume that
1167753e4c44SMatthew Dillon  * the template has its pkg-static binary yet.
1168753e4c44SMatthew Dillon  *
11698e25f19bSMatthew Dillon  * Threaded function
11708e25f19bSMatthew Dillon  */
11718e25f19bSMatthew Dillon static void
11728e25f19bSMatthew Dillon childGetBinaryDistInfo(bulk_t *bulk)
11738e25f19bSMatthew Dillon {
11748e25f19bSMatthew Dillon 	char *ptr;
11758e25f19bSMatthew Dillon 	FILE *fp;
11768e25f19bSMatthew Dillon 	size_t len;
11778e25f19bSMatthew Dillon 	pkg_t *pkg;
11786fd67931SMatthew Dillon 	const char *cav[MAXCAC];
11796fd67931SMatthew Dillon 	char *repopath;
11806fd67931SMatthew Dillon 	char buf[1024];
11816fd67931SMatthew Dillon 	pid_t pid;
11826fd67931SMatthew Dillon 	int cac;
1183dc46751bSMatthew Dillon 	int deleteme;
11848e25f19bSMatthew Dillon 
11856fd67931SMatthew Dillon 	asprintf(&repopath, "%s/%s", RepositoryPath, bulk->s1);
11866fd67931SMatthew Dillon 
11876fd67931SMatthew Dillon 	cac = 0;
11886fd67931SMatthew Dillon 	cav[cac++] = PKG_BINARY;
11896fd67931SMatthew Dillon 	cav[cac++] = "query";
11906fd67931SMatthew Dillon 	cav[cac++] = "-F";
11916fd67931SMatthew Dillon 	cav[cac++] = repopath;
11926fd67931SMatthew Dillon 	cav[cac++] = "%n-%v";
11936fd67931SMatthew Dillon 
1194f9d29536SMatthew Dillon 	fp = dexec_open(NULL, cav, cac, &pid, NULL, 1, 0);
1195dc46751bSMatthew Dillon 	deleteme = DeleteObsoletePkgs;
11966fd67931SMatthew Dillon 
11978e25f19bSMatthew Dillon 	while ((ptr = fgetln(fp, &len)) != NULL) {
11988e25f19bSMatthew Dillon 		if (len == 0 || ptr[len-1] != '\n')
11998e25f19bSMatthew Dillon 			continue;
12008e25f19bSMatthew Dillon 		ptr[len-1] = 0;
12018e25f19bSMatthew Dillon 
1202753e4c44SMatthew Dillon 		/*
1203753e4c44SMatthew Dillon 		 * As of pkg 1.17 the binary dist files use a .pkg suffix
1204753e4c44SMatthew Dillon 		 * regardless of the compression format, so always check
1205753e4c44SMatthew Dillon 		 * those.
1206753e4c44SMatthew Dillon 		 */
1207753e4c44SMatthew Dillon 		snprintf(buf, sizeof(buf), "%s%s", ptr, ".pkg");
12088e25f19bSMatthew Dillon 		pkg = pkg_find(buf);
1209753e4c44SMatthew Dillon 		if (pkg == NULL) {
1210753e4c44SMatthew Dillon 			snprintf(buf, sizeof(buf), "%s%s", ptr, UsePkgSufx);
1211753e4c44SMatthew Dillon 			pkg = pkg_find(buf);
1212753e4c44SMatthew Dillon 		}
12138d9409b8SMatthew Dillon 		if (pkg) {
1214325ef124SMatthew Dillon 			if (FetchOnlyOpt) {
1215325ef124SMatthew Dillon 			    ddprintf(0, "Note: Package is already packaged, ignore for -f: %s\n", ptr);
1216325ef124SMatthew Dillon 			    deleteme = 0;
1217325ef124SMatthew Dillon 			} else {
12188e25f19bSMatthew Dillon 			    pkg->flags |= PKGF_PACKAGED;
1219dc46751bSMatthew Dillon 			    deleteme = 0;
1220325ef124SMatthew Dillon 			}
12218d9409b8SMatthew Dillon 		} else {
12228e25f19bSMatthew Dillon 			ddprintf(0, "Note: package scan, not in list, "
1223753e4c44SMatthew Dillon 				    "skipping %s{.%s,.pkg}\n", ptr, UsePkgSufx);
12248e25f19bSMatthew Dillon 		}
12258d9409b8SMatthew Dillon 	}
12266fd67931SMatthew Dillon 	if (dexec_close(fp, pid)) {
12276fd67931SMatthew Dillon 		printf("pkg query command failed for %s\n", repopath);
12286fd67931SMatthew Dillon 	}
1229dc46751bSMatthew Dillon 	if (deleteme) {
1230dc46751bSMatthew Dillon 		dlog(DLOG_ALL | DLOG_STDOUT,
1231dc46751bSMatthew Dillon 		     "Deleting obsolete package %s\n", repopath);
1232dc46751bSMatthew Dillon 		remove(repopath);
1233dc46751bSMatthew Dillon 	}
12346fd67931SMatthew Dillon 	free(repopath);
12358e25f19bSMatthew Dillon }
12368e25f19bSMatthew Dillon 
1237a67bf8dbSMatthew Dillon static void
1238a67bf8dbSMatthew Dillon childOptimizeEnv(bulk_t *bulk)
1239a67bf8dbSMatthew Dillon {
1240a67bf8dbSMatthew Dillon 	char *portpath;
1241*5d0718a8SMatthew Dillon 	char *localbase;
1242a67bf8dbSMatthew Dillon 	char *ptr;
1243a67bf8dbSMatthew Dillon 	FILE *fp;
1244a67bf8dbSMatthew Dillon 	int line;
1245a67bf8dbSMatthew Dillon 	size_t len;
1246a67bf8dbSMatthew Dillon 	const char *cav[MAXCAC];
1247a67bf8dbSMatthew Dillon 	pid_t pid;
1248a67bf8dbSMatthew Dillon 	int cac;
1249a67bf8dbSMatthew Dillon 
1250a67bf8dbSMatthew Dillon 	asprintf(&portpath, "%s/%s/%s", DPortsPath, bulk->s1, bulk->s2);
1251a67bf8dbSMatthew Dillon 
1252*5d0718a8SMatthew Dillon 	/*
1253*5d0718a8SMatthew Dillon 	 * Prevent postgresql, mysql, and other package Makefile tests
1254*5d0718a8SMatthew Dillon 	 * from accessing the host system's /usr/local by setting LOCALBASE
1255*5d0718a8SMatthew Dillon 	 * to an empty directory.
1256*5d0718a8SMatthew Dillon 	 */
1257*5d0718a8SMatthew Dillon 	asprintf(&localbase, "LOCALBASE=%s/empty", BuildBase);
1258*5d0718a8SMatthew Dillon 
1259a67bf8dbSMatthew Dillon 	cac = 0;
1260a67bf8dbSMatthew Dillon 	cav[cac++] = MAKE_BINARY;
1261a67bf8dbSMatthew Dillon 	cav[cac++] = "-C";
1262a67bf8dbSMatthew Dillon 	cav[cac++] = portpath;
1263*5d0718a8SMatthew Dillon 	cav[cac++] = localbase;
1264a67bf8dbSMatthew Dillon 	cav[cac++] = "-V_PERL5_FROM_BIN";
1265a67bf8dbSMatthew Dillon 
1266f9d29536SMatthew Dillon 	fp = dexec_open(portpath + strlen(DPortsPath) + 1, cav, cac,
1267f9d29536SMatthew Dillon 			&pid, NULL, 1, 1);
1268*5d0718a8SMatthew Dillon 	free(localbase);
1269a67bf8dbSMatthew Dillon 	free(portpath);
1270a67bf8dbSMatthew Dillon 
1271a67bf8dbSMatthew Dillon 	line = 1;
1272a67bf8dbSMatthew Dillon 	while ((ptr = fgetln(fp, &len)) != NULL) {
1273a67bf8dbSMatthew Dillon 		if (len == 0 || ptr[len-1] != '\n') {
1274a67bf8dbSMatthew Dillon 			dfatal("Bad package info for %s/%s response line %d",
1275a67bf8dbSMatthew Dillon 			       bulk->s1, bulk->s2, line);
1276a67bf8dbSMatthew Dillon 		}
1277a67bf8dbSMatthew Dillon 		ptr[--len] = 0;
1278a67bf8dbSMatthew Dillon 
1279a67bf8dbSMatthew Dillon 		switch(line) {
1280a67bf8dbSMatthew Dillon 		case 1:		/* _PERL5_FROM_BIN */
1281a67bf8dbSMatthew Dillon 			addbuildenv("_PERL5_FROM_BIN", ptr, BENV_ENVIRONMENT);
1282a67bf8dbSMatthew Dillon 			break;
1283a67bf8dbSMatthew Dillon 		default:
1284a67bf8dbSMatthew Dillon 			printf("childOptimizeEnv: EXTRA LINE: %s\n", ptr);
1285a67bf8dbSMatthew Dillon 			break;
1286a67bf8dbSMatthew Dillon 		}
1287a67bf8dbSMatthew Dillon 		++line;
1288a67bf8dbSMatthew Dillon 	}
1289a67bf8dbSMatthew Dillon 	if (line == 1) {
1290a67bf8dbSMatthew Dillon 		printf("DPort not found: %s/%s\n", bulk->s1, bulk->s2);
1291a67bf8dbSMatthew Dillon 	} else if (line != 1 + 1) {
1292a67bf8dbSMatthew Dillon 		printf("DPort corrupt: %s/%s\n", bulk->s1, bulk->s2);
1293a67bf8dbSMatthew Dillon 	}
1294a67bf8dbSMatthew Dillon 	if (dexec_close(fp, pid)) {
1295a67bf8dbSMatthew Dillon 		printf("childOptimizeEnv() failed\n");
1296a67bf8dbSMatthew Dillon 	}
1297a67bf8dbSMatthew Dillon }
1298a67bf8dbSMatthew Dillon 
12998e25f19bSMatthew Dillon static int
13008e25f19bSMatthew Dillon scan_and_queue_dir(const char *path, const char *level1, int level)
13018e25f19bSMatthew Dillon {
13028e25f19bSMatthew Dillon 	DIR *dir;
13038e25f19bSMatthew Dillon 	char *s1;
13048e25f19bSMatthew Dillon 	char *s2;
13058e25f19bSMatthew Dillon 	struct dirent *den;
13068e25f19bSMatthew Dillon 	struct stat st;
13078e25f19bSMatthew Dillon 	int count = 0;
13088e25f19bSMatthew Dillon 
13098e25f19bSMatthew Dillon 	dir = opendir(path);
13108e25f19bSMatthew Dillon 	dassert(dir, "Cannot open dports path \"%s\"", path);
13118e25f19bSMatthew Dillon 
13128e25f19bSMatthew Dillon 	while ((den = readdir(dir)) != NULL) {
13138e25f19bSMatthew Dillon 		if (den->d_namlen == 1 && den->d_name[0] == '.')
13148e25f19bSMatthew Dillon 			continue;
13158e25f19bSMatthew Dillon 		if (den->d_namlen == 2 &&
13168e25f19bSMatthew Dillon 		    den->d_name[0] == '.' && den->d_name[1] == '.')
13178e25f19bSMatthew Dillon 			continue;
13188e25f19bSMatthew Dillon 		asprintf(&s1, "%s/%s", path, den->d_name);
13198e25f19bSMatthew Dillon 		if (lstat(s1, &st) < 0 || !S_ISDIR(st.st_mode)) {
13208e25f19bSMatthew Dillon 			free(s1);
13218e25f19bSMatthew Dillon 			continue;
13228e25f19bSMatthew Dillon 		}
13238e25f19bSMatthew Dillon 		if (level == 1) {
13248e25f19bSMatthew Dillon 			count += scan_and_queue_dir(s1, den->d_name, 2);
13258e25f19bSMatthew Dillon 			free(s1);
13268e25f19bSMatthew Dillon 			continue;
13278e25f19bSMatthew Dillon 		}
13288e25f19bSMatthew Dillon 		asprintf(&s2, "%s/Makefile", s1);
13298e25f19bSMatthew Dillon 		if (lstat(s2, &st) == 0) {
13308e25f19bSMatthew Dillon 			queuebulk(level1, den->d_name, NULL, NULL);
13318e25f19bSMatthew Dillon 			++count;
13328e25f19bSMatthew Dillon 		}
13338e25f19bSMatthew Dillon 		free(s1);
13348e25f19bSMatthew Dillon 		free(s2);
13358e25f19bSMatthew Dillon 	}
13368e25f19bSMatthew Dillon 	closedir(dir);
13378e25f19bSMatthew Dillon 
13388e25f19bSMatthew Dillon 	return count;
13398e25f19bSMatthew Dillon }
13408e25f19bSMatthew Dillon 
13418e25f19bSMatthew Dillon static int
13428e25f19bSMatthew Dillon scan_binary_repo(const char *path)
13438e25f19bSMatthew Dillon {
13448e25f19bSMatthew Dillon 	DIR *dir;
13458e25f19bSMatthew Dillon 	struct dirent *den;
13468e25f19bSMatthew Dillon 	int count;
13478e25f19bSMatthew Dillon 
13488e25f19bSMatthew Dillon 	count = 0;
13498e25f19bSMatthew Dillon 	dir = opendir(path);
13508e25f19bSMatthew Dillon 	dassert(dir, "Cannot open repository path \"%s\"", path);
13518e25f19bSMatthew Dillon 
13528d9409b8SMatthew Dillon 	/*
13538d9409b8SMatthew Dillon 	 * NOTE: Test includes the '.' in the suffix.
13548d9409b8SMatthew Dillon 	 */
13558e25f19bSMatthew Dillon 	while ((den = readdir(dir)) != NULL) {
13568d6cd058SMatthew Dillon 		const char *suffix;
13578d6cd058SMatthew Dillon 
13588d6cd058SMatthew Dillon 		suffix = strrchr(den->d_name, '.');
13598d6cd058SMatthew Dillon 		if (suffix && suffix != den->d_name &&
1360753e4c44SMatthew Dillon 		    strcmp(suffix, UsePkgSufx) == 0)
1361753e4c44SMatthew Dillon 		{
1362753e4c44SMatthew Dillon 			queuebulk(den->d_name, NULL, NULL, NULL);
1363753e4c44SMatthew Dillon 			++count;
1364753e4c44SMatthew Dillon 		}
1365753e4c44SMatthew Dillon 
1366753e4c44SMatthew Dillon 		/*
1367753e4c44SMatthew Dillon 		 * As of 1.17, pkg generates .pkg files.
1368753e4c44SMatthew Dillon 		 */
1369753e4c44SMatthew Dillon 		if (suffix && suffix != den->d_name &&
1370753e4c44SMatthew Dillon 		    strcmp(suffix, ".pkg") == 0)
1371753e4c44SMatthew Dillon 		{
13728e25f19bSMatthew Dillon 			queuebulk(den->d_name, NULL, NULL, NULL);
13738e25f19bSMatthew Dillon 			++count;
13748e25f19bSMatthew Dillon 		}
13758e25f19bSMatthew Dillon 	}
13768e25f19bSMatthew Dillon 	closedir(dir);
13778e25f19bSMatthew Dillon 
13788e25f19bSMatthew Dillon 	return count;
13798e25f19bSMatthew Dillon }
13808e25f19bSMatthew Dillon 
13818e25f19bSMatthew Dillon #if 0
13828e25f19bSMatthew Dillon static void
13838e25f19bSMatthew Dillon pkgfree(pkg_t *pkg)
13848e25f19bSMatthew Dillon {
13858e25f19bSMatthew Dillon 	freestrp(&pkg->portdir);
13868e25f19bSMatthew Dillon 	freestrp(&pkg->version);
13878e25f19bSMatthew Dillon 	freestrp(&pkg->pkgfile);
13888e25f19bSMatthew Dillon 	freestrp(&pkg->ignore);
13898e25f19bSMatthew Dillon 	freestrp(&pkg->fetch_deps);
13908e25f19bSMatthew Dillon 	freestrp(&pkg->ext_deps);
13918e25f19bSMatthew Dillon 	freestrp(&pkg->patch_deps);
13928e25f19bSMatthew Dillon 	freestrp(&pkg->build_deps);
13938e25f19bSMatthew Dillon 	freestrp(&pkg->lib_deps);
13948e25f19bSMatthew Dillon 	freestrp(&pkg->run_deps);
13958e25f19bSMatthew Dillon 	freestrp(&pkg->pos_options);
13968e25f19bSMatthew Dillon 	freestrp(&pkg->neg_options);
13978e25f19bSMatthew Dillon 	freestrp(&pkg->flavors);
13988e25f19bSMatthew Dillon 	free(pkg);
13998e25f19bSMatthew Dillon }
14008e25f19bSMatthew Dillon #endif
1401