Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Merge remote-tracking branch 'upstream/master'
Matthew Seaman committed 13 years ago
commit b882cc8b3f6ed35b10746da7e56b32952791cb3a
parent f4383e7
17 files changed +175 -65
modified libpkg/pkg.c
@@ -1,6 +1,7 @@
/*
 * Copyright (c) 2011-2012 Baptiste Daroussin <bapt@FreeBSD.org>
 * Copyright (c) 2011-2012 Julien Laffaye <jlaffaye@FreeBSD.org>
+
 * Copyright (c) 2012 Bryan Drewery <bryan@shatow.net>
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
modified libpkg/pkg.h
@@ -722,7 +722,7 @@ struct pkgdb_it * pkgdb_search(struct pkgdb *db, const char *pattern,
/**
 * 
 */
-
struct pkgdb_it *pkgdb_query_installs(struct pkgdb *db, match_t type, int nbpkgs, char **pkgs, const char *reponame, bool force);
+
struct pkgdb_it *pkgdb_query_installs(struct pkgdb *db, match_t type, int nbpkgs, char **pkgs, const char *reponame, bool force, bool recursive);
struct pkgdb_it *pkgdb_query_upgrades(struct pkgdb *db, const char *reponame, bool all);
struct pkgdb_it *pkgdb_query_downgrades(struct pkgdb *db, const char *reponame);
struct pkgdb_it *pkgdb_query_delete(struct pkgdb *db, match_t type, int nbpkgs, char **pkgs, int recursive);
@@ -977,6 +977,7 @@ int pkg_shutdown(void);

void pkg_test_filesum(struct pkg *);
void pkg_recompute(struct pkgdb *, struct pkg *);
+
int pkgdb_reanalyse_shlibs(struct pkgdb *, struct pkg *);

int pkg_get_myarch(char *pkgarch, size_t sz);

modified libpkg/pkgdb.c
@@ -5,6 +5,7 @@
 * Copyright (c) 2011 Philippe Pepiot <phil@philpep.org>
 * Copyright (c) 2011-2012 Marin Atanasov Nikolov <dnaeon@gmail.com>
 * Copyright (c) 2012 Matthew Seaman <matthew@FreeBSD.org>
+
 * Copyright (c) 2012 Bryan Drewery <bryan@shatow.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
@@ -1726,7 +1727,6 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg, int complete)
	struct pkg_license *license = NULL;
	struct pkg_user *user = NULL;
	struct pkg_group *group = NULL;
-
	struct pkg_shlib *shlib = NULL;
	struct pkgdb_it *it = NULL;

	sqlite3 *s;
@@ -1866,7 +1866,7 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg, int complete)
	while (pkg_categories(pkg, &category) == EPKG_OK) {
		if (run_prstmt(CATEGORY1, pkg_category_name(category))
		    != SQLITE_DONE
-
		    &&
+
		    ||
		    run_prstmt(CATEGORY2, package_id, pkg_category_name(category))
		    != SQLITE_DONE) {
			ERROR_SQLITE(s);
@@ -1881,7 +1881,7 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg, int complete)
	while (pkg_licenses(pkg, &license) == EPKG_OK) {
		if (run_prstmt(LICENSES1, pkg_license_name(license))
		    != SQLITE_DONE
-
		    &&
+
		    ||
		    run_prstmt(LICENSES2, package_id, pkg_license_name(license))
		    != SQLITE_DONE) {
			ERROR_SQLITE(s);
@@ -1896,7 +1896,7 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg, int complete)
	while (pkg_users(pkg, &user) == EPKG_OK) {
		if (run_prstmt(USERS1, pkg_user_name(user))
		    != SQLITE_DONE
-
		    &&
+
		    ||
		    run_prstmt(USERS2, package_id, pkg_user_name(user))
		    != SQLITE_DONE) {
			ERROR_SQLITE(s);
@@ -1911,7 +1911,7 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg, int complete)
	while (pkg_groups(pkg, &group) == EPKG_OK) {
		if (run_prstmt(GROUPS1, pkg_group_name(group))
		    != SQLITE_DONE
-
		    &&
+
		    ||
		    run_prstmt(GROUPS2, package_id, pkg_group_name(group))
		    != SQLITE_DONE)
		{
@@ -1950,25 +1950,85 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg, int complete)
	/*
	 * Insert shlibs
	 */
+
	if (pkgdb_update_shlibs(pkg, package_id, s) != EPKG_OK)
+
		goto cleanup;
+

+
	retcode = EPKG_OK;
+

+
	cleanup:
+

+
	return (retcode);
+
}
+

+
int
+
pkgdb_update_shlibs(struct pkg *pkg, int64_t package_id, sqlite3 *s)
+
{
+
	struct pkg_shlib *shlib = NULL;

	while (pkg_shlibs(pkg, &shlib) == EPKG_OK) {
		if (run_prstmt(SHLIBS1, pkg_shlib_name(shlib))
		    != SQLITE_DONE
-
		    &&
+
		    ||
		    run_prstmt(SHLIBS2, package_id, pkg_shlib_name(shlib))
		    != SQLITE_DONE) {
			ERROR_SQLITE(s);
-
			goto cleanup;
+
			return (EPKG_FATAL);
		}
	}

-
	retcode = EPKG_OK;
+
	return (EPKG_OK);
+
}

-
	cleanup:
+
int
+
pkgdb_reanalyse_shlibs(struct pkgdb *db, struct pkg *pkg)
+
{
+
	sqlite3 *s;
+
	int64_t package_id;
+
	int ret = EPKG_OK;
+
	const char sql[] = "DELETE FROM pkg_shlibs WHERE package_id = ?1;";
+
	sqlite3_stmt *stmt_del;

-
	return (retcode);
+
	assert(db != NULL);
+

+
	if (pkg_is_valid(pkg) != EPKG_OK) {
+
		pkg_emit_error("the package is not valid");
+
		return (EPKG_FATAL);
+
	}
+

+
	if ((ret = pkg_analyse_files(db, pkg)) == EPKG_OK) {
+
		if (!db->prstmt_initialized && prstmt_initialize(db) != EPKG_OK)
+
			return (EPKG_FATAL);
+

+
		s = db->sqlite;
+
		pkg_get(pkg, PKG_ROWID, &package_id);
+

+
		/* Clean out old shlibs first */
+
		if (sqlite3_prepare_v2(db->sqlite, sql, -1, &stmt_del, NULL) != SQLITE_OK) {
+
			ERROR_SQLITE(db->sqlite);
+
			return (EPKG_FATAL);
+
		}
+

+
		sqlite3_bind_int64(stmt_del, 1, package_id);
+

+
		ret = sqlite3_step(stmt_del);
+
		sqlite3_finalize(stmt_del);
+

+
		if (ret != SQLITE_DONE) {
+
			ERROR_SQLITE(db->sqlite);
+
			return (EPKG_FATAL);
+
		}
+

+
		if (sql_exec(db->sqlite, "DELETE FROM shlibs WHERE id NOT IN (SELECT DISTINCT shlib_id FROM pkg_shlibs);") != EPKG_OK)
+
			return (EPKG_FATAL);
+

+
		/* Save shlibs */
+
		ret = pkgdb_update_shlibs(pkg, package_id, s);
+
	}
+

+
	return (ret);
}

+

int
pkgdb_register_finale(struct pkgdb *db, int retcode)
{
@@ -2343,7 +2403,7 @@ cleanup:
}

struct pkgdb_it *
-
pkgdb_query_installs(struct pkgdb *db, match_t match, int nbpkgs, char **pkgs, const char *repo, bool force)
+
pkgdb_query_installs(struct pkgdb *db, match_t match, int nbpkgs, char **pkgs, const char *repo, bool force, bool recursive)
{
	sqlite3_stmt *stmt = NULL;
	struct pkgdb_it *it;
@@ -2382,6 +2442,16 @@ pkgdb_query_installs(struct pkgdb *db, match_t match, int nbpkgs, char **pkgs, c
				"(SELECT d.origin FROM '%s'.deps AS d, pkgjobs AS j WHERE d.package_id = j.pkgid) "
				"AND (SELECT origin FROM main.packages WHERE origin=r.origin AND version=r.version) IS NULL;";

+
	const char upwards_deps_sql[] = "INSERT OR IGNORE INTO pkgjobs (pkgid, origin, name, version, comment, desc, arch, "
+
				"maintainer, www, prefix, flatsize, pkgsize, "
+
				"cksum, repopath, automatic) "
+
				"SELECT DISTINCT r.id, r.origin, r.name, r.version, r.comment, r.desc, "
+
				"r.arch, r.maintainer, r.www, r.prefix, r.flatsize, r.pkgsize, "
+
				"r.cksum, r.path, p.automatic "
+
				"FROM '%s'.packages AS r "
+
				"INNER JOIN main.packages p ON (p.origin = r.origin) "
+
				"WHERE r.id IN (SELECT d.package_id FROM '%s'.deps AS d, pkgjobs AS j WHERE d.origin = j.origin);";
+

	const char weight_sql[] = "UPDATE pkgjobs SET weight=("
		"SELECT COUNT(*) FROM '%s'.deps AS d, '%s'.packages AS p, pkgjobs AS j "
			"WHERE d.origin = pkgjobs.origin "
@@ -2449,6 +2519,11 @@ pkgdb_query_installs(struct pkgdb *db, match_t match, int nbpkgs, char **pkgs, c
		sql_exec(db->sqlite, sbuf_get(sql));
	} while (sqlite3_changes(db->sqlite) != 0);

+
	if (recursive) {
+
		do {
+
			sql_exec(db->sqlite, upwards_deps_sql);
+
		} while (sqlite3_changes(db->sqlite) != 0);
+
	}

	/* Determine if there is an upgrade needed */
	sql_exec(db->sqlite, "INSERT OR REPLACE INTO pkgjobs (pkgid, origin, name, version, comment, desc, message, arch, "
@@ -2506,19 +2581,19 @@ pkgdb_query_upgrades(struct pkgdb *db, const char *repo, bool all)
		"'%s' AS dbname FROM pkgjobs order by weight DESC;";

	const char pkgjobs_sql_1[] = "INSERT OR IGNORE INTO pkgjobs (pkgid, origin, name, version, comment, desc, arch, "
-
			"maintainer, www, prefix, flatsize, pkgsize, "
+
			"maintainer, www, prefix, flatsize, newversion, pkgsize, "
			"cksum, repopath, automatic, opts) "
			"SELECT id, origin, name, version, comment, desc, "
-
			"arch, maintainer, www, prefix, flatsize, pkgsize, "
+
			"arch, maintainer, www, prefix, flatsize, version AS newversion, pkgsize, "
			"cksum, path, 0 ,"
			"(select group_concat(option) from (select option from '%s'.options WHERE package_id=id AND value='on' ORDER BY option)) "
			"FROM '%s'.packages WHERE origin IN (select origin from main.packages)";

	const char pkgjobs_sql_2[] = "INSERT OR IGNORE INTO pkgjobs (pkgid, origin, name, version, comment, desc, arch, "
-
				"maintainer, www, prefix, flatsize, pkgsize, "
+
				"maintainer, www, prefix, flatsize, newversion, pkgsize, "
				"cksum, repopath, automatic, opts) "
				"SELECT DISTINCT r.id, r.origin, r.name, r.version, r.comment, r.desc, "
-
				"r.arch, r.maintainer, r.www, r.prefix, r.flatsize, r.pkgsize, "
+
				"r.arch, r.maintainer, r.www, r.prefix, r.flatsize, r.version AS newversion, r.pkgsize, "
				"r.cksum, r.path, 1, "
				"(select group_concat(option) from (select option from '%s'.options WHERE package_id=r.id AND value='on' ORDER BY option)) "
				"FROM '%s'.packages AS r where r.origin IN "
modified libpkg/private/pkg.h
@@ -270,6 +270,7 @@ int pkgdb_load_group(struct pkgdb *db, struct pkg *pkg);
int pkgdb_load_shlib(struct pkgdb *db, struct pkg *pkg);

int pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg, int complete);
+
int pkgdb_update_shlibs(struct pkg *pkg, int64_t package_id, sqlite3 *s);
int pkgdb_register_finale(struct pkgdb *db, int retcode);

#endif
modified pkg/check.c
@@ -148,7 +148,7 @@ fix_deps(struct pkgdb *db, struct deps_head *dh, int nbpkgs, bool yes)
	if (pkg_jobs_new(&jobs, PKG_JOBS_INSTALL, db) != EPKG_OK)
		free(pkgs);

-
	if ((it = pkgdb_query_installs(db, MATCH_EXACT, nbpkgs, pkgs, NULL, false)) == NULL) {
+
	if ((it = pkgdb_query_installs(db, MATCH_EXACT, nbpkgs, pkgs, NULL, false, false)) == NULL) {
		free(pkgs);
		pkg_jobs_free(jobs);
	}
@@ -221,7 +221,7 @@ check_summary(struct pkgdb *db, struct deps_head *dh)
void
usage_check(void)
{
-
	fprintf(stderr, "usage: pkg check [-dsr] [-vy] [-a | -gxX <pattern>]\n\n");
+
	fprintf(stderr, "usage: pkg check [-dlsr] [-vy] [-a | -gxX <pattern>]\n\n");
	fprintf(stderr, "For more information see 'pkg help check'.\n");
}

@@ -239,13 +239,15 @@ exec_check(int argc, char **argv)
	bool dcheck = false;
	bool checksums = false;
	bool recompute = false;
+
	bool reanalyse_shlibs = false;
+
	bool shlibs;
	int nbpkgs = 0;
	int i;
	int verbose = 0;

	struct deps_head dh = STAILQ_HEAD_INITIALIZER(dh);

-
	while ((ch = getopt(argc, argv, "yagdxXsrv")) != -1) {
+
	while ((ch = getopt(argc, argv, "yagdlxXsrv")) != -1) {
		switch (ch) {
			case 'a':
				match = MATCH_ALL;
@@ -266,6 +268,14 @@ exec_check(int argc, char **argv)
				dcheck = true;
				flags |= PKG_LOAD_DEPS;
				break;
+
			case 'l':
+
				pkg_config_bool(PKG_CONFIG_SHLIBS, &shlibs);
+
				if (!shlibs)
+
					errx(EX_USAGE, "reanalyzing shlibs requires SHLIBS"
+
						       " in pkg.conf.");
+
				reanalyse_shlibs = true;
+
				flags |= PKG_LOAD_FILES;
+
				break;
			case 's':
				checksums = true;
				flags |= PKG_LOAD_FILES;
@@ -289,9 +299,9 @@ exec_check(int argc, char **argv)
	argv += optind;

	/* Default to all packages if no pkg provided */
-
	if (argc == 0 && (dcheck || checksums || recompute)) {
+
	if (argc == 0 && (dcheck || checksums || recompute || reanalyse_shlibs)) {
		match = MATCH_ALL;
-
	} else if ((argc == 0 && match != MATCH_ALL) || !(dcheck || checksums || recompute)) {
+
	} else if ((argc == 0 && match != MATCH_ALL) || !(dcheck || checksums || recompute || reanalyse_shlibs)) {
		usage_check();
		return (EX_USAGE);
	}
@@ -333,6 +343,12 @@ exec_check(int argc, char **argv)
					printf("Recomputing size and checksums: %s\n", pkgname);
				pkg_recompute(db, pkg);
			}
+
			if (reanalyse_shlibs) {
+
				if (verbose)
+
					printf("Reanalyzing files for shlibs: %s\n", pkgname);
+
				if (pkgdb_reanalyse_shlibs(db, pkg) != EPKG_OK)
+
					printf("Failed to reanalyse for shlibs: %s\n", pkgname);
+
			}
		}

		if (geteuid() == 0 && nbpkgs > 0) {
modified pkg/fetch.c
@@ -42,7 +42,7 @@
void
usage_fetch(void)
{
-
	fprintf(stderr, "usage: pkg fetch [-r reponame] [-yqgxXaRL] <pkg-name> <...>\n\n");
+
	fprintf(stderr, "usage: pkg fetch [-r reponame] [-yqgxXadL] <pkg-name> <...>\n\n");
	fprintf(stderr, "For more information see 'pkg help fetch'.\n");
}

@@ -61,7 +61,7 @@ exec_fetch(int argc, char **argv)
	bool auto_update = true;
	match_t match = MATCH_EXACT;

-
	while ((ch = getopt(argc, argv, "ygxXr:qaLR")) != -1) {
+
	while ((ch = getopt(argc, argv, "ygxXr:qaLd")) != -1) {
		switch (ch) {
		case 'y':
			yes = true;
@@ -87,7 +87,7 @@ exec_fetch(int argc, char **argv)
		case 'L':
			auto_update = false;
			break;
-
		case 'R':
+
		case 'd':
			flags |= PKG_LOAD_DEPS;
			break;
		default:
modified pkg/install.c
@@ -44,7 +44,7 @@
void
usage_install(void)
{
-
	fprintf(stderr, "usage: pkg install [-r reponame] [-yqfgxXL] <pkg-name> <...>\n\n");
+
	fprintf(stderr, "usage: pkg install [-r reponame] [-yqfgxXRL] <pkg-name> <...>\n\n");
	fprintf(stderr, "For more information see 'pkg help install'.\n");
}

@@ -60,11 +60,12 @@ exec_install(int argc, char **argv)
	int ch;
	bool yes = false;
	bool auto_update = true;
+
	bool recursive = false;

	match_t match = MATCH_EXACT;
	bool force = false;

-
	while ((ch = getopt(argc, argv, "yfgxXr:qL")) != -1) {
+
	while ((ch = getopt(argc, argv, "yfgxXr:qLR")) != -1) {
		switch (ch) {
			case 'y':
				yes = true;
@@ -90,6 +91,9 @@ exec_install(int argc, char **argv)
			case 'L':
				auto_update = false;
				break;
+
			case 'R':
+
				recursive = true;
+
				break;
			default:
				usage_install();
				return (EX_USAGE);
@@ -120,7 +124,7 @@ exec_install(int argc, char **argv)
		goto cleanup;
	}

-
	if ((it = pkgdb_query_installs(db, match, argc, argv, reponame, force)) == NULL)
+
	if ((it = pkgdb_query_installs(db, match, argc, argv, reponame, force, recursive)) == NULL)
		goto cleanup;

	while (pkgdb_it_next(it, &pkg, PKG_LOAD_BASIC|PKG_LOAD_DEPS) == EPKG_OK) {
modified pkg/pkg-check.8
@@ -15,7 +15,7 @@
.\"     @(#)pkg.8
.\" $FreeBSD$
.\"
-
.Dd May 30, 2012
+
.Dd July 9, 2012
.Dt PKG-CHECK 8
.Os
.Sh NAME
@@ -23,7 +23,7 @@
.Nd sanity checks installed packages
.Sh SYNOPSIS
.Nm
-
.Op Fl dsr
+
.Op Fl dlsr
.Op Fl vy
.Op Fl a | gxX Ar <pattern>
.Sh DESCRIPTION
@@ -32,6 +32,13 @@
is used to check for and install missing dependencies.
.Pp
.Nm
+
.Fl l
+
is used to reanalyse SHLIBS of installed packages.
+
See
+
.Xr pkg.conf 5
+
for more information on SHLIBS.
+
.Pp
+
.Nm
.Fl r
is used to recompute sizes and checksums of installed packages.
.Pp
modified pkg/pkg-fetch.8
@@ -15,7 +15,7 @@
.\"     @(#)pkg.8
.\" $FreeBSD$
.\"
-
.Dd July 2, 2012
+
.Dd May 24, 2012
.Dt PKG-FETCH 8
.Os
.Sh NAME
@@ -24,7 +24,7 @@
.Sh SYNOPSIS
.Nm
.Op Fl r Ar reponame
-
.Op Fl yqgxXaRL
+
.Op Fl yqgxXadL
.Ar <pkg-name>
.Op ...
.Sh DESCRIPTION
@@ -71,8 +71,8 @@ as an extended regular expression.
Don't auto update the remote database with
.Xr pkg-update 8 .
Use the local cache only.
-
.It Fl R
-
Recursively fetch the package and its dependencies as well.
+
.It Fl d
+
Fetch the package and it's dependencies as well.
.El
.Sh ENVIRONMENT
The following environment variables affect the execution of
modified pkg/pkg-install.8
@@ -24,7 +24,7 @@
.Sh SYNOPSIS
.Nm
.Op Fl r Ar reponame
-
.Op Fl yqfgxXL
+
.Op Fl yqfgxXRL
.Ar <pkg-origin> <...>
.Sh DESCRIPTION
.Nm
@@ -35,7 +35,7 @@ explicitly or by matching against package names in the repository
catalogues using shell globbing; standard- or extended regular
expressions.
.Pp
-
.Nm 
+
.Nm
creates a work-list of all the package installations to do.
Any already installed and up to date packages will be dropped from the
list unless the
@@ -58,7 +58,7 @@ will present it to the user for approval before proceeding, unless
overridden by the
.Fl y
option or the
-
.Cm ASSUME_ALWAYS_YES 
+
.Cm ASSUME_ALWAYS_YES
setting in
.Fa pkg.conf .
.Pp
@@ -106,7 +106,7 @@ package installation with
The following options are supported by
.Nm :
.Bl -tag -width F1
-
.It Fl r Op reponame
+
.It Fl r Ar reponame
In multi-repo mode, override the
.Fa pkg.conf
ordering and only attempt to download packages from the named
@@ -127,6 +127,10 @@ Force quiet output.
Don't auto update repository catalogues with
.Xr pkg-update 8 .
Use the locally cached copies only.
+
.It Fl R
+
When used with
+
.Fl f ,
+
recursively reinstalls any packages depending on the given package.
.El
.Sh ENVIRONMENT
The following environment variables affect the execution of
modified pkg/pkg-query.8
@@ -177,7 +177,7 @@ by the
(also listed below).
Expressions can be combined using && (for and) and || (for or).
Parentheses can be used for grouping in the usual manner.
-

+
.Pp
String values are either any text not containing whitespace (possibly
followed by but not including whitespace) or any text enclosed in single or
double quotes.
modified pkg/pkg-stats.8
@@ -45,8 +45,6 @@ The following environment variables affect the execution of
See
.Xr pkg.conf 5
for further description.
-
.Bl -tag -width ".Ev NO_DESCRIPTIONS"
-
.El
.Sh FILES
See
.Xr pkg.conf 5 .
modified pkg/pkgcli.h
@@ -164,6 +164,7 @@ bool query_yesno(const char *msg, ...);
void print_info(struct pkg * const pkg, unsigned int opt);
char *absolutepath(const char *src, char *dest, size_t dest_len);
void print_jobs_summary(struct pkg_jobs *j, pkg_jobs_t type, const char *msg, ...);
+
struct sbuf *exec_buf(const char *cmd);

int event_callback(void *data, struct pkg_event *ev);

modified pkg/query.c
@@ -1,6 +1,7 @@
/*
 * Copyright (c) 2011-2012 Baptiste Daroussin <bapt@FreeBSD.org>
 * Copyright (c) 2011-2012 Marin Atanasov Nikolov <dnaeon@gmail.com>
+
 * Copyright (c) 2012 Bryan Drewery <bryan@shatow.net>
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
modified pkg/rquery.c
@@ -1,6 +1,7 @@
/*
 * Copyright (c) 2011-2012 Baptiste Daroussin <bapt@FreeBSD.org>
 * Copyright (c) 2011-2012 Marin Atanasov Nikolov <dnaeon@gmail.com>
+
 * Copyright (c) 2012 Bryan Drewery <bryan@shatow.net>
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
modified pkg/utils.c
@@ -398,3 +398,28 @@ print_jobs_summary(struct pkg_jobs *jobs, pkg_jobs_t type, const char *msg, ...)
		printf("\n%s to be downloaded\n", size);
	}
}
+

+
struct sbuf *
+
exec_buf(const char *cmd) {
+
	FILE *fp;
+
	char buf[BUFSIZ];
+
	struct sbuf *res;
+

+
	if ((fp = popen(cmd, "r")) == NULL)
+
		return (NULL);
+

+
	res = sbuf_new_auto();
+
	while (fgets(buf, BUFSIZ, fp) != NULL)
+
		sbuf_cat(res, buf);
+

+
	pclose(fp);
+

+
	if (sbuf_len(res) == 0) {
+
		sbuf_delete(res);
+
		return (NULL);
+
	}
+

+
	sbuf_finish(res);
+

+
	return (res);
+
}
modified pkg/version.c
@@ -61,31 +61,6 @@ usage_version(void)
	fprintf(stderr, "For more information see 'pkg help version'.\n");
}

-
static struct sbuf *
-
exec_buf(const char *cmd) {
-
	FILE *fp;
-
	char buf[BUFSIZ];
-
	struct sbuf *res;
-

-
	if ((fp = popen(cmd, "r")) == NULL)
-
		return (NULL);
-

-
	res = sbuf_new_auto();
-
	while (fgets(buf, BUFSIZ, fp) != NULL)
-
		sbuf_cat(res, buf);
-

-
	pclose(fp);
-

-
	if (sbuf_len(res) == 0) {
-
		sbuf_delete(res);
-
		return (NULL);
-
	}
-

-
	sbuf_finish(res);
-

-
	return (res);
-
}
-

static void
print_version(struct pkg *pkg, const char *source, const char *ver, char limchar, unsigned int opt)
{