summaryrefslogtreecommitdiffstats
path: root/usr.sbin
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/pkg_install/Makefile4
-rw-r--r--usr.sbin/pkg_install/Makefile.inc13
-rw-r--r--usr.sbin/pkg_install/add/Makefile7
-rw-r--r--usr.sbin/pkg_install/add/extract.c2
-rw-r--r--usr.sbin/pkg_install/add/futil.c2
-rw-r--r--usr.sbin/pkg_install/add/main.c4
-rw-r--r--usr.sbin/pkg_install/add/perform.c2
-rw-r--r--usr.sbin/pkg_install/create/Makefile6
-rw-r--r--usr.sbin/pkg_install/create/main.c4
-rw-r--r--usr.sbin/pkg_install/create/perform.c2
-rw-r--r--usr.sbin/pkg_install/create/pl.c2
-rw-r--r--usr.sbin/pkg_install/delete/Makefile5
-rw-r--r--usr.sbin/pkg_install/delete/main.c4
-rw-r--r--usr.sbin/pkg_install/delete/perform.c2
-rw-r--r--usr.sbin/pkg_install/info/Makefile6
-rw-r--r--usr.sbin/pkg_install/info/info.h39
-rw-r--r--usr.sbin/pkg_install/info/main.c14
-rw-r--r--usr.sbin/pkg_install/info/perform.c2
-rw-r--r--usr.sbin/pkg_install/info/show.c2
-rw-r--r--usr.sbin/pkg_install/lib/Makefile11
-rw-r--r--usr.sbin/pkg_install/lib/deps.c241
-rw-r--r--usr.sbin/pkg_install/lib/exec.c106
-rw-r--r--usr.sbin/pkg_install/lib/file.c436
-rw-r--r--usr.sbin/pkg_install/lib/global.c32
-rw-r--r--usr.sbin/pkg_install/lib/lib.h242
-rw-r--r--usr.sbin/pkg_install/lib/match.c603
-rw-r--r--usr.sbin/pkg_install/lib/msg.c75
-rw-r--r--usr.sbin/pkg_install/lib/pen.c186
-rw-r--r--usr.sbin/pkg_install/lib/pkgwrap.c89
-rw-r--r--usr.sbin/pkg_install/lib/plist.c592
-rw-r--r--usr.sbin/pkg_install/lib/str.c129
-rw-r--r--usr.sbin/pkg_install/lib/url.c171
-rw-r--r--usr.sbin/pkg_install/lib/version.c328
-rw-r--r--usr.sbin/pkg_install/updating/Makefile5
-rw-r--r--usr.sbin/pkg_install/updating/main.c4
-rw-r--r--usr.sbin/pkg_install/version/Makefile5
-rw-r--r--usr.sbin/pkg_install/version/main.c4
-rw-r--r--usr.sbin/pkg_install/version/perform.c2
38 files changed, 3315 insertions, 68 deletions
diff --git a/usr.sbin/pkg_install/Makefile b/usr.sbin/pkg_install/Makefile
index 0aa1941..bf1a213 100644
--- a/usr.sbin/pkg_install/Makefile
+++ b/usr.sbin/pkg_install/Makefile
@@ -2,11 +2,11 @@
.include <bsd.own.mk>
-SUBDIR= add create delete info updating version
+SUBDIR= lib add create delete info updating version
.include <bsd.subdir.mk>
-DATE!= grep PKG_INSTALL_VERSION ${.CURDIR}/Makefile.inc | sed 's|.*=||'
+DATE!= grep PKG_INSTALL_VERSION ${.CURDIR}/lib/lib.h | sed 's|.*[ ]||'
distfile: clean
@(cd ${.CURDIR}/..; \
diff --git a/usr.sbin/pkg_install/Makefile.inc b/usr.sbin/pkg_install/Makefile.inc
index d929f24..2fa20aa 100644
--- a/usr.sbin/pkg_install/Makefile.inc
+++ b/usr.sbin/pkg_install/Makefile.inc
@@ -2,11 +2,16 @@
.include <bsd.own.mk>
-CFLAGS+= -DPKG_INSTALL_VERSION=20101012
-CFLAGS+= -DYES_I_KNOW_THE_API_IS_RUBBISH_AND_IS_DOOMED_TO_CHANGE
+LIBINSTALL= ${.OBJDIR}/../lib/libinstall.a
-DPADD+= ${LIBPKG}
-LDADD+= -lpkg
+DPADD+= ${LIBUTIL}
+LDADD+= -lutil
+
+.if ${MK_OPENSSL} != "no" && \
+ defined(LDADD) && ${LDADD:M-lfetch} != ""
+DPADD+= ${LIBSSL} ${LIBCRYPTO}
+LDADD+= -lssl -lcrypto
+.endif
# Inherit BINDIR from one level up.
.include "../Makefile.inc"
diff --git a/usr.sbin/pkg_install/add/Makefile b/usr.sbin/pkg_install/add/Makefile
index 03a43f0..89988e7 100644
--- a/usr.sbin/pkg_install/add/Makefile
+++ b/usr.sbin/pkg_install/add/Makefile
@@ -1,11 +1,14 @@
# $FreeBSD$
-.include <bsd.own.mk>
-
PROG= pkg_add
SRCS= main.c perform.c futil.c extract.c
+CFLAGS+= -I${.CURDIR}/../lib
+
WARNS?= 3
WFORMAT?= 1
+DPADD= ${LIBINSTALL} ${LIBFETCH} ${LIBMD}
+LDADD= ${LIBINSTALL} -lfetch -lmd
+
.include <bsd.prog.mk>
diff --git a/usr.sbin/pkg_install/add/extract.c b/usr.sbin/pkg_install/add/extract.c
index 6c2c4fc..732a13f 100644
--- a/usr.sbin/pkg_install/add/extract.c
+++ b/usr.sbin/pkg_install/add/extract.c
@@ -23,7 +23,7 @@ __FBSDID("$FreeBSD$");
#include <ctype.h>
#include <err.h>
-#include <pkg.h>
+#include "lib.h"
#include "add.h"
diff --git a/usr.sbin/pkg_install/add/futil.c b/usr.sbin/pkg_install/add/futil.c
index c525320..ca095ea 100644
--- a/usr.sbin/pkg_install/add/futil.c
+++ b/usr.sbin/pkg_install/add/futil.c
@@ -22,7 +22,7 @@
__FBSDID("$FreeBSD$");
#include <err.h>
-#include <pkg.h>
+#include "lib.h"
#include "add.h"
/*
diff --git a/usr.sbin/pkg_install/add/main.c b/usr.sbin/pkg_install/add/main.c
index b8b9b54..f73312a 100644
--- a/usr.sbin/pkg_install/add/main.c
+++ b/usr.sbin/pkg_install/add/main.c
@@ -26,7 +26,7 @@ __FBSDID("$FreeBSD$");
#include <err.h>
#include <getopt.h>
-#include <pkg.h>
+#include "lib.h"
#include "add.h"
char *Prefix = NULL;
@@ -132,8 +132,6 @@ main(int argc, char **argv)
static char temppackageroot[MAXPATHLEN];
static char pkgaddpath[MAXPATHLEN];
- pkg_wrap(PKG_INSTALL_VERSION, argv);
-
if (*argv[0] != '/' && strchr(argv[0], '/') != NULL)
PkgAddCmd = realpath(argv[0], pkgaddpath);
else
diff --git a/usr.sbin/pkg_install/add/perform.c b/usr.sbin/pkg_install/add/perform.c
index 653a1d6..b23cd52 100644
--- a/usr.sbin/pkg_install/add/perform.c
+++ b/usr.sbin/pkg_install/add/perform.c
@@ -23,7 +23,7 @@ __FBSDID("$FreeBSD$");
#include <err.h>
#include <paths.h>
-#include <pkg.h>
+#include "lib.h"
#include "add.h"
#include <libgen.h>
diff --git a/usr.sbin/pkg_install/create/Makefile b/usr.sbin/pkg_install/create/Makefile
index 3334037..42718c6 100644
--- a/usr.sbin/pkg_install/create/Makefile
+++ b/usr.sbin/pkg_install/create/Makefile
@@ -3,10 +3,12 @@
PROG= pkg_create
SRCS= main.c perform.c pl.c
+CFLAGS+= -I${.CURDIR}/../lib
+
WARNS?= 3
WFORMAT?= 1
-DPADD= ${LIBMD}
-LDADD= -lmd
+DPADD= ${LIBINSTALL} ${LIBMD}
+LDADD= ${LIBINSTALL} -lmd
.include <bsd.prog.mk>
diff --git a/usr.sbin/pkg_install/create/main.c b/usr.sbin/pkg_install/create/main.c
index 5e999da..e4af621 100644
--- a/usr.sbin/pkg_install/create/main.c
+++ b/usr.sbin/pkg_install/create/main.c
@@ -15,7 +15,7 @@ __FBSDID("$FreeBSD$");
#include <getopt.h>
#include <err.h>
-#include <pkg.h>
+#include "lib.h"
#include "create.h"
match_t MatchType = MATCH_GLOB;
@@ -72,8 +72,6 @@ main(int argc, char **argv)
int ch;
char **pkgs, **start, *tmp;
- pkg_wrap(PKG_INSTALL_VERSION, argv);
-
pkgs = start = argv;
while ((ch = getopt_long(argc, argv, opts, longopts, NULL)) != -1)
switch(ch) {
diff --git a/usr.sbin/pkg_install/create/perform.c b/usr.sbin/pkg_install/create/perform.c
index 149bcbd..45786b6 100644
--- a/usr.sbin/pkg_install/create/perform.c
+++ b/usr.sbin/pkg_install/create/perform.c
@@ -21,7 +21,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include <pkg.h>
+#include "lib.h"
#include "create.h"
#include <err.h>
diff --git a/usr.sbin/pkg_install/create/pl.c b/usr.sbin/pkg_install/create/pl.c
index fe62d42..18bbaf2 100644
--- a/usr.sbin/pkg_install/create/pl.c
+++ b/usr.sbin/pkg_install/create/pl.c
@@ -21,7 +21,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include <pkg.h>
+#include "lib.h"
#include "create.h"
#include <errno.h>
#include <err.h>
diff --git a/usr.sbin/pkg_install/delete/Makefile b/usr.sbin/pkg_install/delete/Makefile
index 4f3b390..c9a0fde 100644
--- a/usr.sbin/pkg_install/delete/Makefile
+++ b/usr.sbin/pkg_install/delete/Makefile
@@ -3,6 +3,11 @@
PROG= pkg_delete
SRCS= main.c perform.c
+CFLAGS+= -I${.CURDIR}/../lib
+
WFORMAT?= 1
+DPADD= ${LIBINSTALL} ${LIBMD}
+LDADD= ${LIBINSTALL} -lmd
+
.include <bsd.prog.mk>
diff --git a/usr.sbin/pkg_install/delete/main.c b/usr.sbin/pkg_install/delete/main.c
index 7677fe9..f09a432 100644
--- a/usr.sbin/pkg_install/delete/main.c
+++ b/usr.sbin/pkg_install/delete/main.c
@@ -27,7 +27,7 @@ __FBSDID("$FreeBSD$");
#include <getopt.h>
#include <err.h>
-#include <pkg.h>
+#include "lib.h"
#include "delete.h"
char *Prefix = NULL;
@@ -67,8 +67,6 @@ main(int argc, char **argv)
const char *tmp;
struct stat stat_s;
- pkg_wrap(PKG_INSTALL_VERSION, argv);
-
pkgs = start = argv;
while ((ch = getopt_long(argc, argv, opts, longopts, NULL)) != -1)
switch(ch) {
diff --git a/usr.sbin/pkg_install/delete/perform.c b/usr.sbin/pkg_install/delete/perform.c
index 02f9717..2557dbc 100644
--- a/usr.sbin/pkg_install/delete/perform.c
+++ b/usr.sbin/pkg_install/delete/perform.c
@@ -22,7 +22,7 @@
__FBSDID("$FreeBSD$");
#include <err.h>
-#include <pkg.h>
+#include "lib.h"
#include "delete.h"
static int pkg_do(char *);
diff --git a/usr.sbin/pkg_install/info/Makefile b/usr.sbin/pkg_install/info/Makefile
index ba3909d..485cb22 100644
--- a/usr.sbin/pkg_install/info/Makefile
+++ b/usr.sbin/pkg_install/info/Makefile
@@ -3,9 +3,11 @@
PROG= pkg_info
SRCS= main.c perform.c show.c
+CFLAGS+= -I${.CURDIR}/../lib
+
WFORMAT?= 1
-DPADD= ${LIBMD}
-LDADD= -lmd
+DPADD= ${LIBINSTALL} ${LIBFETCH} ${LIBMD}
+LDADD= ${LIBINSTALL} -lfetch -lmd
.include <bsd.prog.mk>
diff --git a/usr.sbin/pkg_install/info/info.h b/usr.sbin/pkg_install/info/info.h
index 68ec710..46e29b1 100644
--- a/usr.sbin/pkg_install/info/info.h
+++ b/usr.sbin/pkg_install/info/info.h
@@ -33,26 +33,25 @@
#define MAXNAMESIZE 20
#endif
-#define SHOW_COMMENT 0x000001
-#define SHOW_DESC 0x000002
-#define SHOW_PLIST 0x000004
-#define SHOW_INSTALL 0x000008
-#define SHOW_DEINSTALL 0x000010
-#define SHOW_REQUIRE 0x000020
-#define SHOW_PREFIX 0x000040
-#define SHOW_INDEX 0x000080
-#define SHOW_FILES 0x000100
-#define SHOW_DISPLAY 0x000200
-#define SHOW_REQBY 0x000400
-#define SHOW_MTREE 0x000800
-#define SHOW_SIZE 0x001000
-#define SHOW_ORIGIN 0x002000
-#define SHOW_CKSUM 0x004000
-#define SHOW_FMTREV 0x008000
-#define SHOW_PTREV 0x010000
-#define SHOW_DEPEND 0x020000
-#define SHOW_PKGNAME 0x040000
-#define SHOW_LPREV 0x100000
+#define SHOW_COMMENT 0x00001
+#define SHOW_DESC 0x00002
+#define SHOW_PLIST 0x00004
+#define SHOW_INSTALL 0x00008
+#define SHOW_DEINSTALL 0x00010
+#define SHOW_REQUIRE 0x00020
+#define SHOW_PREFIX 0x00040
+#define SHOW_INDEX 0x00080
+#define SHOW_FILES 0x00100
+#define SHOW_DISPLAY 0x00200
+#define SHOW_REQBY 0x00400
+#define SHOW_MTREE 0x00800
+#define SHOW_SIZE 0x01000
+#define SHOW_ORIGIN 0x02000
+#define SHOW_CKSUM 0x04000
+#define SHOW_FMTREV 0x08000
+#define SHOW_PTREV 0x10000
+#define SHOW_DEPEND 0x20000
+#define SHOW_PKGNAME 0x40000
struct which_entry {
TAILQ_ENTRY(which_entry) next;
diff --git a/usr.sbin/pkg_install/info/main.c b/usr.sbin/pkg_install/info/main.c
index ca4e477..2de638e 100644
--- a/usr.sbin/pkg_install/info/main.c
+++ b/usr.sbin/pkg_install/info/main.c
@@ -25,7 +25,7 @@ __FBSDID("$FreeBSD$");
#include <getopt.h>
#include <err.h>
-#include <pkg.h>
+#include "lib.h"
#include "info.h"
int Flags = 0;
@@ -68,8 +68,6 @@ main(int argc, char **argv)
char **pkgs, **start;
char *pkgs_split;
- pkg_wrap(PKG_INSTALL_VERSION, argv);
-
whead = malloc(sizeof(struct which_head));
if (whead == NULL)
err(2, NULL);
@@ -227,10 +225,7 @@ main(int argc, char **argv)
}
case 'P':
- if (Flags & SHOW_PTREV)
- Flags |= SHOW_LPREV;
- else
- Flags = SHOW_PTREV;
+ Flags = SHOW_PTREV;
break;
case 'h':
@@ -247,11 +242,6 @@ main(int argc, char **argv)
if (!Quiet)
printf("Package tools revision: ");
printf("%d\n", PKG_INSTALL_VERSION);
- if (Flags & SHOW_LPREV) {
- if (!Quiet)
- printf("Libpkg revision: ");
- printf("%d\n", libpkg_version());
- }
exit(0);
}
diff --git a/usr.sbin/pkg_install/info/perform.c b/usr.sbin/pkg_install/info/perform.c
index d295612..09cad78 100644
--- a/usr.sbin/pkg_install/info/perform.c
+++ b/usr.sbin/pkg_install/info/perform.c
@@ -21,7 +21,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include <pkg.h>
+#include "lib.h"
#include "info.h"
#include <err.h>
#include <signal.h>
diff --git a/usr.sbin/pkg_install/info/show.c b/usr.sbin/pkg_install/info/show.c
index 0d3b4ad..c65c312 100644
--- a/usr.sbin/pkg_install/info/show.c
+++ b/usr.sbin/pkg_install/info/show.c
@@ -21,7 +21,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include <pkg.h>
+#include "lib.h"
#include "info.h"
#include <err.h>
#include <stdlib.h>
diff --git a/usr.sbin/pkg_install/lib/Makefile b/usr.sbin/pkg_install/lib/Makefile
new file mode 100644
index 0000000..84a41b8
--- /dev/null
+++ b/usr.sbin/pkg_install/lib/Makefile
@@ -0,0 +1,11 @@
+# $FreeBSD$
+
+LIB= install
+INTERNALLIB=
+SRCS= file.c msg.c plist.c str.c exec.c global.c pen.c match.c \
+ deps.c version.c pkgwrap.c url.c
+
+WARNS?= 3
+WFORMAT?= 1
+
+.include <bsd.lib.mk>
diff --git a/usr.sbin/pkg_install/lib/deps.c b/usr.sbin/pkg_install/lib/deps.c
new file mode 100644
index 0000000..66f44a9
--- /dev/null
+++ b/usr.sbin/pkg_install/lib/deps.c
@@ -0,0 +1,241 @@
+/*
+ * FreeBSD install - a package for the installation and maintainance
+ * of non-core utilities.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Maxim Sobolev
+ * 14 March 2001
+ *
+ * Routines used to do various operations with dependencies
+ * among installed packages.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "lib.h"
+#include <err.h>
+#include <stdio.h>
+
+void list_deps(const char *pkgname, char **pkgs, char *listed,
+ char *check_loop, char **newpkgs, int *nrnewpkgs,
+ int *err_cnt);
+
+/*
+ * Sort given NULL-terminated list of installed packages (pkgs) in
+ * such a way that if package A depends on package B then after
+ * sorting A will be listed before B no matter how they were
+ * originally positioned in the list.
+ *
+ * Works by performing a recursive depth-first search on the
+ * required-by lists.
+ */
+
+int
+sortdeps(char **pkgs)
+{
+ int i, err_cnt=0;
+ int nrpkgs, nrnewpkgs;
+ char *listed, *check_loop, **newpkgs;
+ char *cp;
+
+ if (pkgs[0] == NULL || pkgs[1] == NULL)
+ return (0);
+
+ nrpkgs = 0;
+ while (pkgs[nrpkgs]) nrpkgs++;
+ listed = alloca(nrpkgs);
+ if (listed == NULL) {
+ warnx("%s(): alloca() failed", __func__);
+ return 1;
+ }
+ bzero(listed,nrpkgs);
+ check_loop = alloca(nrpkgs);
+ if (check_loop == NULL) {
+ warnx("%s(): alloca() failed", __func__);
+ return 1;
+ }
+ bzero(check_loop,nrpkgs);
+ newpkgs = alloca(nrpkgs*sizeof(char*));
+ if (newpkgs == NULL) {
+ warnx("%s(): alloca() failed", __func__);
+ return 1;
+ }
+ nrnewpkgs = 0;
+
+ for (i = 0; pkgs[i]; i++) if (!listed[i]) {
+ check_loop[i] = 1;
+ cp = strchr(pkgs[i], ':');
+ if (cp != NULL)
+ *cp = '\0';
+ list_deps(pkgs[i],pkgs,listed,check_loop,newpkgs,&nrnewpkgs,&err_cnt);
+ if (cp != NULL)
+ *cp = ':';
+ listed[i] = 1;
+ newpkgs[nrnewpkgs] = pkgs[i];
+ nrnewpkgs++;
+ }
+
+ if (nrnewpkgs != nrpkgs) {
+ fprintf(stderr,"This shouldn't happen, and indicates a huge error in the code.\n");
+ exit(1);
+ }
+ for (i = 0; i < nrnewpkgs; i++) pkgs[i] = newpkgs[i];
+
+ return err_cnt;
+}
+
+/*
+ * This recursive function lists the dependencies (that is, the
+ * "required-by"s) for pkgname, putting them into newpkgs.
+ */
+
+void list_deps(const char *pkgname, char **pkgs, char *listed,
+ char *check_loop, char **newpkgs, int *nrnewpkgs,
+ int *err_cnt) {
+ char **rb, **rbtmp;
+ char *cp;
+ int errcode, i, j;
+ struct reqr_by_entry *rb_entry;
+ struct reqr_by_head *rb_list;
+
+ if (isinstalledpkg(pkgname) <= 0)
+ return;
+
+ errcode = requiredby(pkgname, &rb_list, FALSE, TRUE);
+ if (errcode < 0)
+ return;
+ /*
+ * We put rb_list into an argv style NULL terminated list,
+ * because requiredby uses some static storage, and list_deps
+ * is a recursive function.
+ */
+
+ rbtmp = rb = alloca((errcode + 1) * sizeof(*rb));
+ if (rb == NULL) {
+ warnx("%s(): alloca() failed", __func__);
+ (*err_cnt)++;
+ return;
+ }
+ STAILQ_FOREACH(rb_entry, rb_list, link) {
+ *rbtmp = alloca(strlen(rb_entry->pkgname) + 1);
+ if (*rbtmp == NULL) {
+ warnx("%s(): alloca() failed", __func__);
+ (*err_cnt)++;
+ return;
+ }
+ strcpy(*rbtmp, rb_entry->pkgname);
+ rbtmp++;
+ }
+ *rbtmp = NULL;
+
+ for (i = 0; rb[i]; i++)
+ for (j = 0; pkgs[j]; j++) if (!listed[j]) {
+ cp = strchr(pkgs[j], ':');
+ if (cp != NULL)
+ *cp = '\0';
+ if (strcmp(rb[i], pkgs[j]) == 0) { /*match */
+ /*
+ * Try to avoid deadlock if package A depends on B which in
+ * turn depends on C and C due to an error depends on A.
+ * It Should Never Happen[tm] in real life.
+ */
+ if (check_loop[j]) {
+ warnx("dependency loop detected for package %s", pkgs[j]);
+ (*err_cnt)++;
+ }
+ else {
+ check_loop[j] = 1;
+ list_deps(pkgs[j],pkgs,listed,check_loop,newpkgs,nrnewpkgs,err_cnt);
+ listed[j] = 1;
+ newpkgs[*nrnewpkgs] = pkgs[j];
+ (*nrnewpkgs)++;
+ }
+ }
+ if (cp != NULL)
+ *cp = ':';
+ }
+}
+
+/*
+ * Load +REQUIRED_BY file and return a list with names of
+ * packages that require package reffered to by `pkgname'.
+ *
+ * Optionally check that packages listed there are actually
+ * installed and filter out those that don't (filter == TRUE).
+ *
+ * strict argument controls whether the caller want warnings
+ * to be emitted when there are some non-fatal conditions,
+ * i.e. package doesn't have +REQUIRED_BY file or some packages
+ * listed in +REQUIRED_BY don't exist.
+ *
+ * Result returned in the **list, while return value is equal
+ * to the number of entries in the resulting list. Print error
+ * message and return -1 on error.
+ */
+int
+requiredby(const char *pkgname, struct reqr_by_head **list, Boolean strict, Boolean filter)
+{
+ FILE *fp;
+ char fbuf[FILENAME_MAX], fname[FILENAME_MAX];
+ int retval;
+ struct reqr_by_entry *rb_entry;
+ static struct reqr_by_head rb_list = STAILQ_HEAD_INITIALIZER(rb_list);
+
+ *list = &rb_list;
+ /* Deallocate any previously allocated space */
+ while (!STAILQ_EMPTY(&rb_list)) {
+ rb_entry = STAILQ_FIRST(&rb_list);
+ STAILQ_REMOVE_HEAD(&rb_list, link);
+ free(rb_entry);
+ }
+
+ if (isinstalledpkg(pkgname) <= 0) {
+ if (strict == TRUE)
+ warnx("no such package '%s' installed", pkgname);
+ return -1;
+ }
+
+ snprintf(fname, sizeof(fname), "%s/%s/%s", LOG_DIR, pkgname,
+ REQUIRED_BY_FNAME);
+ fp = fopen(fname, "r");
+ if (fp == NULL) {
+ /* Probably pkgname doesn't have any packages that depend on it */
+ if (strict == TRUE)
+ warnx("couldn't open dependency file '%s'", fname);
+ return 0;
+ }
+
+ retval = 0;
+ while (fgets(fbuf, sizeof(fbuf), fp) != NULL) {
+ if (fbuf[strlen(fbuf) - 1] == '\n')
+ fbuf[strlen(fbuf) - 1] = '\0';
+ if (filter == TRUE && isinstalledpkg(fbuf) <= 0) {
+ if (strict == TRUE)
+ warnx("package '%s' is recorded in the '%s' but isn't "
+ "actually installed", fbuf, fname);
+ continue;
+ }
+ retval++;
+ rb_entry = malloc(sizeof(*rb_entry));
+ if (rb_entry == NULL) {
+ warnx("%s(): malloc() failed", __func__);
+ retval = -1;
+ break;
+ }
+ strlcpy(rb_entry->pkgname, fbuf, sizeof(rb_entry->pkgname));
+ STAILQ_INSERT_TAIL(&rb_list, rb_entry, link);
+ }
+ fclose(fp);
+
+ return retval;
+}
diff --git a/usr.sbin/pkg_install/lib/exec.c b/usr.sbin/pkg_install/lib/exec.c
new file mode 100644
index 0000000..fc8220c
--- /dev/null
+++ b/usr.sbin/pkg_install/lib/exec.c
@@ -0,0 +1,106 @@
+/*
+ * FreeBSD install - a package for the installation and maintainance
+ * of non-core utilities.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Jordan K. Hubbard
+ * 18 July 1993
+ *
+ * Miscellaneous system routines.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "lib.h"
+#include <err.h>
+
+/*
+ * Unusual system() substitute. Accepts format string and args,
+ * builds and executes command. Returns exit code.
+ */
+
+int
+vsystem(const char *fmt, ...)
+{
+ va_list args;
+ char *cmd;
+ int ret, maxargs;
+
+ maxargs = sysconf(_SC_ARG_MAX);
+ maxargs -= 32; /* some slop for the sh -c */
+ cmd = malloc(maxargs);
+ if (!cmd) {
+ warnx("vsystem can't alloc arg space");
+ return 1;
+ }
+
+ va_start(args, fmt);
+ if (vsnprintf(cmd, maxargs, fmt, args) > maxargs) {
+ warnx("vsystem args are too long");
+ return 1;
+ }
+#ifdef DEBUG
+printf("Executing %s\n", cmd);
+#endif
+ ret = system(cmd);
+ va_end(args);
+ free(cmd);
+ return ret;
+}
+
+char *
+vpipe(const char *fmt, ...)
+{
+ FILE *fp;
+ char *cmd, *rp;
+ int maxargs;
+ va_list args;
+
+ rp = malloc(MAXPATHLEN);
+ if (!rp) {
+ warnx("vpipe can't alloc buffer space");
+ return NULL;
+ }
+ maxargs = sysconf(_SC_ARG_MAX);
+ maxargs -= 32; /* some slop for the sh -c */
+ cmd = alloca(maxargs);
+ if (!cmd) {
+ warnx("vpipe can't alloc arg space");
+ return NULL;
+ }
+
+ va_start(args, fmt);
+ if (vsnprintf(cmd, maxargs, fmt, args) > maxargs) {
+ warnx("vsystem args are too long");
+ return NULL;
+ }
+#ifdef DEBUG
+ fprintf(stderr, "Executing %s\n", cmd);
+#endif
+ fflush(NULL);
+ fp = popen(cmd, "r");
+ if (fp == NULL) {
+ warnx("popen() failed");
+ return NULL;
+ }
+ get_string(rp, MAXPATHLEN, fp);
+#ifdef DEBUG
+ fprintf(stderr, "Returned %s\n", rp);
+#endif
+ va_end(args);
+ if (pclose(fp) || (strlen(rp) == 0)) {
+ free(rp);
+ return NULL;
+ }
+ return rp;
+}
diff --git a/usr.sbin/pkg_install/lib/file.c b/usr.sbin/pkg_install/lib/file.c
new file mode 100644
index 0000000..c7ab9d6
--- /dev/null
+++ b/usr.sbin/pkg_install/lib/file.c
@@ -0,0 +1,436 @@
+/*
+ * FreeBSD install - a package for the installation and maintainance
+ * of non-core utilities.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Jordan K. Hubbard
+ * 18 July 1993
+ *
+ * Miscellaneous file access utilities.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "lib.h"
+#include <err.h>
+#include <pwd.h>
+#include <time.h>
+#include <sys/wait.h>
+
+/* Quick check to see if a file exists */
+Boolean
+fexists(const char *fname)
+{
+ int fd;
+
+ if ((fd = open(fname, O_RDONLY)) == -1)
+ return FALSE;
+
+ close(fd);
+ return TRUE;
+}
+
+/* Quick check to see if something is a directory or symlink to a directory */
+Boolean
+isdir(const char *fname)
+{
+ struct stat sb;
+
+ if (lstat(fname, &sb) != FAIL && S_ISDIR(sb.st_mode))
+ return TRUE;
+ else if (lstat(strconcat(fname, "/."), &sb) != FAIL && S_ISDIR(sb.st_mode))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+/* Check to see if file is a dir or symlink to a dir, and is empty */
+Boolean
+isemptydir(const char *fname)
+{
+ if (isdir(fname)) {
+ DIR *dirp;
+ struct dirent *dp;
+
+ dirp = opendir(fname);
+ if (!dirp)
+ return FALSE; /* no perms, leave it alone */
+ for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
+ if (strcmp(dp->d_name, ".") && strcmp(dp->d_name, "..")) {
+ closedir(dirp);
+ return FALSE;
+ }
+ }
+ (void)closedir(dirp);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*
+ * Returns TRUE if file is a regular file or symlink pointing to a regular
+ * file
+ */
+Boolean
+isfile(const char *fname)
+{
+ struct stat sb;
+ if (stat(fname, &sb) != FAIL && S_ISREG(sb.st_mode))
+ return TRUE;
+ return FALSE;
+}
+
+/*
+ * Check to see if file is a file or symlink pointing to a file and is empty.
+ * If nonexistent or not a file, say "it's empty", otherwise return TRUE if
+ * zero sized.
+ */
+Boolean
+isemptyfile(const char *fname)
+{
+ struct stat sb;
+ if (stat(fname, &sb) != FAIL && S_ISREG(sb.st_mode)) {
+ if (sb.st_size != 0)
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/* Returns TRUE if file is a symbolic link. */
+Boolean
+issymlink(const char *fname)
+{
+ struct stat sb;
+ if (lstat(fname, &sb) != FAIL && S_ISLNK(sb.st_mode))
+ return TRUE;
+ return FALSE;
+}
+
+/* Returns TRUE if file is a URL specification */
+Boolean
+isURL(const char *fname)
+{
+ /*
+ * I'm sure there are other types of URL specifications that I could
+ * also be looking for here, but for now I'll just be happy to get ftp
+ * and http working.
+ */
+ if (!fname)
+ return FALSE;
+ while (isspace(*fname))
+ ++fname;
+ if (!strncmp(fname, "ftp://", 6) || !strncmp(fname, "http://", 7) ||
+ !strncmp(fname, "https://", 8) || !strncmp(fname, "file://", 7))
+ return TRUE;
+ return FALSE;
+}
+
+char *
+fileFindByPath(const char *base, const char *fname)
+{
+ static char tmp[FILENAME_MAX];
+ char *cp;
+ const char *suffixes[] = {".tbz", ".tgz", ".tar", NULL};
+ int i;
+
+ if (fexists(fname) && isfile(fname)) {
+ strcpy(tmp, fname);
+ return tmp;
+ }
+ if (base) {
+ strcpy(tmp, base);
+
+ cp = strrchr(tmp, '/');
+ if (cp) {
+ *cp = '\0'; /* chop name */
+ cp = strrchr(tmp, '/');
+ }
+ if (cp)
+ for (i = 0; suffixes[i] != NULL; i++) {
+ *(cp + 1) = '\0';
+ strcat(cp, "All/");
+ strcat(cp, fname);
+ strcat(cp, suffixes[i]);
+ if (fexists(tmp))
+ return tmp;
+ }
+ }
+
+ cp = getenv("PKG_PATH");
+ while (cp) {
+ char *cp2 = strsep(&cp, ":");
+
+ for (i = 0; suffixes[i] != NULL; i++) {
+ snprintf(tmp, FILENAME_MAX, "%s/%s%s", cp2 ? cp2 : cp, fname, suffixes[i]);
+ if (fexists(tmp) && isfile(tmp))
+ return tmp;
+ }
+ }
+ return NULL;
+}
+
+char *
+fileGetContents(const char *fname)
+{
+ char *contents;
+ struct stat sb;
+ int fd;
+
+ if (stat(fname, &sb) == FAIL) {
+ cleanup(0);
+ errx(2, "%s: can't stat '%s'", __func__, fname);
+ }
+
+ contents = (char *)malloc(sb.st_size + 1);
+ fd = open(fname, O_RDONLY, 0);
+ if (fd == FAIL) {
+ cleanup(0);
+ errx(2, "%s: unable to open '%s' for reading", __func__, fname);
+ }
+ if (read(fd, contents, sb.st_size) != sb.st_size) {
+ cleanup(0);
+ errx(2, "%s: short read on '%s' - did not get %lld bytes", __func__,
+ fname, (long long)sb.st_size);
+ }
+ close(fd);
+ contents[sb.st_size] = '\0';
+ return contents;
+}
+
+/*
+ * Takes a filename and package name, returning (in "try") the
+ * canonical "preserve" name for it.
+ */
+Boolean
+make_preserve_name(char *try, int max, const char *name, const char *file)
+{
+ int len, i;
+
+ if ((len = strlen(file)) == 0)
+ return FALSE;
+ else
+ i = len - 1;
+ strncpy(try, file, max);
+ if (try[i] == '/') /* Catch trailing slash early and save checking in the loop */
+ --i;
+ for (; i; i--) {
+ if (try[i] == '/') {
+ try[i + 1]= '.';
+ strncpy(&try[i + 2], &file[i + 1], max - i - 2);
+ break;
+ }
+ }
+ if (!i) {
+ try[0] = '.';
+ strncpy(try + 1, file, max - 1);
+ }
+ /* I should probably be called rude names for these inline assignments */
+ strncat(try, ".", max -= strlen(try));
+ strncat(try, name, max -= strlen(name));
+ strncat(try, ".", max--);
+ strncat(try, "backup", max -= 6);
+ return TRUE;
+}
+
+/* Write the contents of "str" to a file */
+void
+write_file(const char *name, const char *str)
+{
+ FILE *fp;
+ size_t len;
+
+ fp = fopen(name, "w");
+ if (!fp) {
+ cleanup(0);
+ errx(2, "%s: cannot fopen '%s' for writing", __func__, name);
+ }
+ len = strlen(str);
+ if (fwrite(str, 1, len, fp) != len) {
+ cleanup(0);
+ errx(2, "%s: short fwrite on '%s', tried to write %ld bytes",
+ __func__, name, (long)len);
+ }
+ if (fclose(fp)) {
+ cleanup(0);
+ errx(2, "%s: failure to fclose '%s'", __func__, name);
+ }
+}
+
+void
+copy_file(const char *dir, const char *fname, const char *to)
+{
+ char cmd[FILENAME_MAX];
+
+ if (fname[0] == '/')
+ snprintf(cmd, FILENAME_MAX, "/bin/cp -r %s %s", fname, to);
+ else
+ snprintf(cmd, FILENAME_MAX, "/bin/cp -r %s/%s %s", dir, fname, to);
+ if (vsystem(cmd)) {
+ cleanup(0);
+ errx(2, "%s: could not perform '%s'", __func__, cmd);
+ }
+}
+
+void
+move_file(const char *dir, const char *fname, const char *tdir)
+{
+ char from[FILENAME_MAX];
+ char to[FILENAME_MAX];
+
+ if (fname[0] == '/')
+ strncpy(from, fname, FILENAME_MAX);
+ else
+ snprintf(from, FILENAME_MAX, "%s/%s", dir, fname);
+
+ snprintf(to, FILENAME_MAX, "%s/%s", tdir, fname);
+
+ if (rename(from, to) == -1) {
+ if (vsystem("/bin/mv %s %s", from, to)) {
+ cleanup(0);
+ errx(2, "%s: could not move '%s' to '%s'", __func__, from, to);
+ }
+ }
+}
+
+/*
+ * Copy a hierarchy (possibly from dir) to the current directory, or
+ * if "to" is TRUE, from the current directory to a location someplace
+ * else.
+ *
+ * Though slower, using tar to copy preserves symlinks and everything
+ * without me having to write some big hairy routine to do it.
+ */
+void
+copy_hierarchy(const char *dir, const char *fname, Boolean to)
+{
+ char cmd[FILENAME_MAX * 3];
+
+ if (!to) {
+ /* If absolute path, use it */
+ if (*fname == '/')
+ dir = "/";
+ snprintf(cmd, FILENAME_MAX * 3, "/usr/bin/tar cf - -C %s %s | /usr/bin/tar xpf -",
+ dir, fname);
+ }
+ else
+ snprintf(cmd, FILENAME_MAX * 3, "/usr/bin/tar cf - %s | /usr/bin/tar xpf - -C %s",
+ fname, dir);
+#ifdef DEBUG
+ printf("Using '%s' to copy trees.\n", cmd);
+#endif
+ if (system(cmd)) {
+ cleanup(0);
+ errx(2, "%s: could not perform '%s'", __func__, cmd);
+ }
+}
+
+/* Unpack a tar file */
+int
+unpack(const char *pkg, const char *flist)
+{
+ const char *comp, *cp;
+ char suff[80];
+
+ comp = "";
+ /*
+ * Figure out by a crude heuristic whether this or not this is probably
+ * compressed and whichever compression utility was used (gzip or bzip2).
+ */
+ if (strcmp(pkg, "-")) {
+ cp = strrchr(pkg, '.');
+ if (cp) {
+ strcpy(suff, cp + 1);
+ if (strchr(suff, 'z') || strchr(suff, 'Z')) {
+ if (strchr(suff, 'b'))
+ comp = "-j";
+ else
+ comp = "-z";
+ }
+ }
+ }
+ else
+ comp = "-j";
+ if (vsystem("/usr/bin/tar -xp %s -f '%s' %s", comp, pkg, flist ? flist : "")) {
+ warnx("tar extract of %s failed!", pkg);
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Using fmt, replace all instances of:
+ *
+ * %F With the parameter "name"
+ * %D With the parameter "dir"
+ * %B Return the directory part ("base") of %D/%F
+ * %f Return the filename part of %D/%F
+ *
+ * Does not check for overflow - caution!
+ *
+ */
+void
+format_cmd(char *buf, int max, const char *fmt, const char *dir, const char *name)
+{
+ char *cp, scratch[FILENAME_MAX * 2];
+ int l;
+
+ while (*fmt && max > 0) {
+ if (*fmt == '%') {
+ switch (*++fmt) {
+ case 'F':
+ strncpy(buf, name, max);
+ l = strlen(name);
+ buf += l, max -= l;
+ break;
+
+ case 'D':
+ strncpy(buf, dir, max);
+ l = strlen(dir);
+ buf += l, max -= l;
+ break;
+
+ case 'B':
+ snprintf(scratch, FILENAME_MAX * 2, "%s/%s", dir, name);
+ cp = &scratch[strlen(scratch) - 1];
+ while (cp != scratch && *cp != '/')
+ --cp;
+ *cp = '\0';
+ strncpy(buf, scratch, max);
+ l = strlen(scratch);
+ buf += l, max -= l;
+ break;
+
+ case 'f':
+ snprintf(scratch, FILENAME_MAX * 2, "%s/%s", dir, name);
+ cp = &scratch[strlen(scratch) - 1];
+ while (cp != scratch && *(cp - 1) != '/')
+ --cp;
+ strncpy(buf, cp, max);
+ l = strlen(cp);
+ buf += l, max -= l;
+ break;
+
+ default:
+ *buf++ = *fmt;
+ --max;
+ break;
+ }
+ ++fmt;
+ }
+ else {
+ *buf++ = *fmt++;
+ --max;
+ }
+ }
+ *buf = '\0';
+}
diff --git a/usr.sbin/pkg_install/lib/global.c b/usr.sbin/pkg_install/lib/global.c
new file mode 100644
index 0000000..e136ec8
--- /dev/null
+++ b/usr.sbin/pkg_install/lib/global.c
@@ -0,0 +1,32 @@
+/*
+ * FreeBSD install - a package for the installation and maintainance
+ * of non-core utilities.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Jordan K. Hubbard
+
+ * 18 July 1993
+ *
+ * Semi-convenient place to stick some needed globals.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "lib.h"
+
+/* These are global for all utils */
+Boolean Quiet = FALSE;
+Boolean Fake = FALSE;
+Boolean Force = FALSE;
+int AutoAnswer = FALSE;
+int Verbose = 0; /* Allow multiple levels of verbose. */
diff --git a/usr.sbin/pkg_install/lib/lib.h b/usr.sbin/pkg_install/lib/lib.h
new file mode 100644
index 0000000..089bfa3
--- /dev/null
+++ b/usr.sbin/pkg_install/lib/lib.h
@@ -0,0 +1,242 @@
+/* $FreeBSD$ */
+
+/*
+ * FreeBSD install - a package for the installation and maintainance
+ * of non-core utilities.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Jordan K. Hubbard
+ * 18 July 1993
+ *
+ * Include and define various things wanted by the library routines.
+ *
+ */
+
+#ifndef _INST_LIB_LIB_H_
+#define _INST_LIB_LIB_H_
+
+/* Includes */
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/queue.h>
+#include <sys/utsname.h>
+#include <ctype.h>
+#include <dirent.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/* Macros */
+#define SUCCESS (0)
+#define FAIL (-1)
+
+#ifndef TRUE
+#define TRUE (1)
+#endif
+
+#ifndef FALSE
+#define FALSE (0)
+#endif
+
+#define YES 2
+#define NO 1
+
+/* Some more stat macros. */
+#define S_IRALL 0000444
+#define S_IWALL 0000222
+#define S_IXALL 0000111
+
+/* Usually "rm", but often "echo" during debugging! */
+#define REMOVE_CMD "/bin/rm"
+
+/* Usually "rm", but often "echo" during debugging! */
+#define RMDIR_CMD "/bin/rmdir"
+
+/* Where the ports lives by default */
+#define DEF_PORTS_DIR "/usr/ports"
+/* just in case we change the environment variable name */
+#define PORTSDIR "PORTSDIR"
+/* macro to get name of directory where the ports lives */
+#define PORTS_DIR (getenv(PORTSDIR) ? getenv(PORTSDIR) : DEF_PORTS_DIR)
+
+/* Where we put logging information by default, else ${PKG_DBDIR} if set */
+#define DEF_LOG_DIR "/var/db/pkg"
+/* just in case we change the environment variable name */
+#define PKG_DBDIR "PKG_DBDIR"
+/* macro to get name of directory where we put logging information */
+#define LOG_DIR (getenv(PKG_DBDIR) ? getenv(PKG_DBDIR) : DEF_LOG_DIR)
+
+/* The names of our "special" files */
+#define CONTENTS_FNAME "+CONTENTS"
+#define COMMENT_FNAME "+COMMENT"
+#define DESC_FNAME "+DESC"
+#define INSTALL_FNAME "+INSTALL"
+#define POST_INSTALL_FNAME "+POST-INSTALL"
+#define DEINSTALL_FNAME "+DEINSTALL"
+#define POST_DEINSTALL_FNAME "+POST-DEINSTALL"
+#define REQUIRE_FNAME "+REQUIRE"
+#define REQUIRED_BY_FNAME "+REQUIRED_BY"
+#define DISPLAY_FNAME "+DISPLAY"
+#define MTREE_FNAME "+MTREE_DIRS"
+
+#define CMD_CHAR '@' /* prefix for extended PLIST cmd */
+
+/* The name of the "prefix" environment variable given to scripts */
+#define PKG_PREFIX_VNAME "PKG_PREFIX"
+
+/*
+ * Version of the package tools - increase whenever you make a change
+ * in the code that is not cosmetic only.
+ */
+#define PKG_INSTALL_VERSION 20100403
+
+#define PKG_WRAPCONF_FNAME "/var/db/pkg_install.conf"
+#define main(argc, argv) real_main(argc, argv)
+
+/* Version numbers to assist with changes in package file format */
+#define PLIST_FMT_VER_MAJOR 1
+#define PLIST_FMT_VER_MINOR 1
+
+enum _plist_t {
+ PLIST_FILE, PLIST_CWD, PLIST_CMD, PLIST_CHMOD,
+ PLIST_CHOWN, PLIST_CHGRP, PLIST_COMMENT, PLIST_IGNORE,
+ PLIST_NAME, PLIST_UNEXEC, PLIST_SRC, PLIST_DISPLAY,
+ PLIST_PKGDEP, PLIST_CONFLICTS, PLIST_MTREE, PLIST_DIR_RM,
+ PLIST_IGNORE_INST, PLIST_OPTION, PLIST_ORIGIN, PLIST_DEPORIGIN,
+ PLIST_NOINST
+};
+typedef enum _plist_t plist_t;
+
+enum _match_t {
+ MATCH_ALL, MATCH_EXACT, MATCH_GLOB, MATCH_NGLOB, MATCH_EREGEX, MATCH_REGEX
+};
+typedef enum _match_t match_t;
+
+/* Types */
+typedef unsigned int Boolean;
+
+struct _plist {
+ struct _plist *prev, *next;
+ char *name;
+ Boolean marked;
+ plist_t type;
+};
+typedef struct _plist *PackingList;
+
+struct _pack {
+ struct _plist *head, *tail;
+ const char *name;
+ const char *origin;
+ int fmtver_maj, fmtver_mnr;
+};
+typedef struct _pack Package;
+
+struct reqr_by_entry {
+ STAILQ_ENTRY(reqr_by_entry) link;
+ char pkgname[PATH_MAX];
+};
+STAILQ_HEAD(reqr_by_head, reqr_by_entry);
+
+/* Prototypes */
+/* Misc */
+int vsystem(const char *, ...);
+char *vpipe(const char *, ...);
+void cleanup(int);
+const char *make_playpen(char *, off_t);
+char *where_playpen(void);
+int leave_playpen(void);
+off_t min_free(const char *);
+
+/* String */
+char *get_dash_string(char **);
+char *copy_string(const char *);
+char *copy_string_adds_newline(const char *);
+Boolean suffix(const char *, const char *);
+void nuke_suffix(char *);
+void str_lowercase(char *);
+char *strconcat(const char *, const char *);
+char *get_string(char *, int, FILE *);
+
+/* File */
+Boolean fexists(const char *);
+Boolean isdir(const char *);
+Boolean isemptydir(const char *fname);
+Boolean isemptyfile(const char *fname);
+Boolean isfile(const char *);
+Boolean isempty(const char *);
+Boolean issymlink(const char *);
+Boolean isURL(const char *);
+const char *fileGetURL(const char *, const char *, int);
+char *fileFindByPath(const char *, const char *);
+char *fileGetContents(const char *);
+void write_file(const char *, const char *);
+void copy_file(const char *, const char *, const char *);
+void move_file(const char *, const char *, const char *);
+void copy_hierarchy(const char *, const char *, Boolean);
+int delete_hierarchy(const char *, Boolean, Boolean);
+int unpack(const char *, const char *);
+void format_cmd(char *, int, const char *, const char *, const char *);
+
+/* Msg */
+void upchuck(const char *);
+void barf(const char *, ...);
+void whinge(const char *, ...);
+Boolean y_or_n(Boolean, const char *, ...);
+
+/* Packing list */
+PackingList new_plist_entry(void);
+PackingList last_plist(Package *);
+PackingList find_plist(Package *, plist_t);
+char *find_plist_option(Package *, const char *name);
+void plist_delete(Package *, Boolean, plist_t, const char *);
+void free_plist(Package *);
+void mark_plist(Package *);
+void csum_plist_entry(char *, PackingList);
+void add_plist(Package *, plist_t, const char *);
+void add_plist_top(Package *, plist_t, const char *);
+void delete_plist(Package *pkg, Boolean all, plist_t type, const char *name);
+void write_plist(Package *, FILE *);
+void read_plist(Package *, FILE *);
+int plist_cmd(const char *, char **);
+int delete_package(Boolean, Boolean, Package *);
+Boolean make_preserve_name(char *, int, const char *, const char *);
+
+/* For all */
+int pkg_perform(char **);
+int real_main(int, char **);
+
+/* Query installed packages */
+char **matchinstalled(match_t, char **, int *);
+char **matchbyorigin(const char *, int *);
+char ***matchallbyorigin(const char **, int *);
+int isinstalledpkg(const char *name);
+int pattern_match(match_t MatchType, char *pattern, const char *pkgname);
+
+/* Dependencies */
+int sortdeps(char **);
+int chkifdepends(const char *, const char *);
+int requiredby(const char *, struct reqr_by_head **, Boolean, Boolean);
+
+/* Version */
+int verscmp(Package *, int, int);
+int version_cmp(const char *, const char *);
+
+/* Externs */
+extern Boolean Quiet;
+extern Boolean Fake;
+extern Boolean Force;
+extern int AutoAnswer;
+extern int Verbose;
+
+#endif /* _INST_LIB_LIB_H_ */
diff --git a/usr.sbin/pkg_install/lib/match.c b/usr.sbin/pkg_install/lib/match.c
new file mode 100644
index 0000000..6c1b2bf
--- /dev/null
+++ b/usr.sbin/pkg_install/lib/match.c
@@ -0,0 +1,603 @@
+/*
+ * FreeBSD install - a package for the installation and maintainance
+ * of non-core utilities.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Maxim Sobolev
+ * 24 February 2001
+ *
+ * Routines used to query installed packages.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "lib.h"
+#include <err.h>
+#include <fnmatch.h>
+#include <fts.h>
+#include <regex.h>
+
+/*
+ * Simple structure representing argv-like
+ * NULL-terminated list.
+ */
+struct store {
+ int currlen;
+ int used;
+ char **store;
+};
+
+static int rex_match(const char *, const char *, int);
+static int csh_match(const char *, const char *, int);
+struct store *storecreate(struct store *);
+static int storeappend(struct store *, const char *);
+static int fname_cmp(const FTSENT * const *, const FTSENT * const *);
+
+/*
+ * Function to query names of installed packages.
+ * MatchType - one of MATCH_ALL, MATCH_EREGEX, MATCH_REGEX, MATCH_GLOB, MATCH_NGLOB;
+ * patterns - NULL-terminated list of glob or regex patterns
+ * (could be NULL for MATCH_ALL);
+ * retval - return value (could be NULL if you don't want/need
+ * return value).
+ * Returns NULL-terminated list with matching names.
+ * Names in list returned are dynamically allocated and should
+ * not be altered by the caller.
+ */
+char **
+matchinstalled(match_t MatchType, char **patterns, int *retval)
+{
+ int i, errcode, len;
+ char *matched;
+ const char *paths[2] = {LOG_DIR, NULL};
+ static struct store *store = NULL;
+ FTS *ftsp;
+ FTSENT *f;
+ Boolean *lmatched = NULL;
+
+ store = storecreate(store);
+ if (store == NULL) {
+ if (retval != NULL)
+ *retval = 1;
+ return NULL;
+ }
+
+ if (retval != NULL)
+ *retval = 0;
+
+ if (!isdir(paths[0])) {
+ if (retval != NULL)
+ *retval = 1;
+ return NULL;
+ /* Not reached */
+ }
+
+ /* Count number of patterns */
+ if (patterns != NULL) {
+ for (len = 0; patterns[len]; len++) {}
+ lmatched = alloca(sizeof(*lmatched) * len);
+ if (lmatched == NULL) {
+ warnx("%s(): alloca() failed", __func__);
+ if (retval != NULL)
+ *retval = 1;
+ return NULL;
+ }
+ } else
+ len = 0;
+
+ for (i = 0; i < len; i++)
+ lmatched[i] = FALSE;
+
+ ftsp = fts_open((char * const *)(uintptr_t)paths, FTS_LOGICAL | FTS_NOCHDIR | FTS_NOSTAT, fname_cmp);
+ if (ftsp != NULL) {
+ while ((f = fts_read(ftsp)) != NULL) {
+ if (f->fts_info == FTS_D && f->fts_level == 1) {
+ fts_set(ftsp, f, FTS_SKIP);
+ matched = NULL;
+ errcode = 0;
+ if (MatchType == MATCH_ALL)
+ matched = f->fts_name;
+ else
+ for (i = 0; patterns[i]; i++) {
+ errcode = pattern_match(MatchType, patterns[i], f->fts_name);
+ if (errcode == 1) {
+ matched = f->fts_name;
+ lmatched[i] = TRUE;
+ errcode = 0;
+ }
+ if (matched != NULL || errcode != 0)
+ break;
+ }
+ if (errcode == 0 && matched != NULL)
+ errcode = storeappend(store, matched);
+ if (errcode != 0) {
+ if (retval != NULL)
+ *retval = 1;
+ return NULL;
+ /* Not reached */
+ }
+ }
+ }
+ fts_close(ftsp);
+ }
+
+ if (MatchType == MATCH_GLOB) {
+ for (i = 0; i < len; i++)
+ if (lmatched[i] == FALSE)
+ storeappend(store, patterns[i]);
+ }
+
+ if (store->used == 0)
+ return NULL;
+ else
+ return store->store;
+}
+
+int
+pattern_match(match_t MatchType, char *pattern, const char *pkgname)
+{
+ int errcode = 0;
+ const char *fname = pkgname;
+ char basefname[PATH_MAX];
+ char condchar = '\0';
+ char *condition;
+
+ /* do we have an appended condition? */
+ condition = strpbrk(pattern, "<>=");
+ if (condition) {
+ const char *ch;
+ /* yes, isolate the pattern from the condition ... */
+ if (condition > pattern && condition[-1] == '!')
+ condition--;
+ condchar = *condition;
+ *condition = '\0';
+ /* ... and compare the name without version */
+ ch = strrchr(fname, '-');
+ if (ch && ch - fname < PATH_MAX) {
+ strlcpy(basefname, fname, ch - fname + 1);
+ fname = basefname;
+ }
+ }
+
+ switch (MatchType) {
+ case MATCH_EREGEX:
+ case MATCH_REGEX:
+ errcode = rex_match(pattern, fname, MatchType == MATCH_EREGEX ? 1 : 0);
+ break;
+ case MATCH_NGLOB:
+ case MATCH_GLOB:
+ errcode = (csh_match(pattern, fname, 0) == 0) ? 1 : 0;
+ break;
+ case MATCH_EXACT:
+ errcode = (strcmp(pattern, fname) == 0) ? 1 : 0;
+ break;
+ case MATCH_ALL:
+ errcode = 1;
+ break;
+ default:
+ break;
+ }
+
+ /* loop over all appended conditions */
+ while (condition) {
+ /* restore the pattern */
+ *condition = condchar;
+ /* parse the condition (fun with bits) */
+ if (errcode == 1) {
+ char *nextcondition;
+ /* compare version numbers */
+ int match = 0;
+ if (*++condition == '=') {
+ match = 2;
+ condition++;
+ }
+ switch(condchar) {
+ case '<':
+ match |= 1;
+ break;
+ case '>':
+ match |= 4;
+ break;
+ case '=':
+ match |= 2;
+ break;
+ case '!':
+ match = 5;
+ break;
+ }
+ /* isolate the version number from the next condition ... */
+ nextcondition = strpbrk(condition, "<>=!");
+ if (nextcondition) {
+ condchar = *nextcondition;
+ *nextcondition = '\0';
+ }
+ /* and compare the versions (version_cmp removes the filename for us) */
+ if ((match & (1 << (version_cmp(pkgname, condition) + 1))) == 0)
+ errcode = 0;
+ condition = nextcondition;
+ } else {
+ break;
+ }
+ }
+
+ return errcode;
+}
+
+/*
+ * Synopsis is similar to matchinstalled(), but use origin
+ * as a key for matching packages.
+ */
+char ***
+matchallbyorigin(const char **origins, int *retval)
+{
+ char **installed, **allorigins = NULL;
+ char ***matches = NULL;
+ int i, j;
+
+ if (retval != NULL)
+ *retval = 0;
+
+ installed = matchinstalled(MATCH_ALL, NULL, retval);
+ if (installed == NULL)
+ return NULL;
+
+ /* Gather origins for all installed packages */
+ for (i = 0; installed[i] != NULL; i++) {
+ FILE *fp;
+ char *buf, *cp, tmp[PATH_MAX];
+ int cmd;
+
+ allorigins = realloc(allorigins, (i + 1) * sizeof(*allorigins));
+ allorigins[i] = NULL;
+
+ snprintf(tmp, PATH_MAX, "%s/%s", LOG_DIR, installed[i]);
+ /*
+ * SPECIAL CASE: ignore empty dirs, since we can can see them
+ * during port installation.
+ */
+ if (isemptydir(tmp))
+ continue;
+ strncat(tmp, "/" CONTENTS_FNAME, PATH_MAX);
+ fp = fopen(tmp, "r");
+ if (fp == NULL) {
+ warnx("the package info for package '%s' is corrupt", installed[i]);
+ continue;
+ }
+
+ cmd = -1;
+ while (fgets(tmp, sizeof(tmp), fp)) {
+ int len = strlen(tmp);
+
+ while (len && isspace(tmp[len - 1]))
+ tmp[--len] = '\0';
+ if (!len)
+ continue;
+ cp = tmp;
+ if (tmp[0] != CMD_CHAR)
+ continue;
+ cmd = plist_cmd(tmp + 1, &cp);
+ if (cmd == PLIST_ORIGIN) {
+ asprintf(&buf, "%s", cp);
+ allorigins[i] = buf;
+ break;
+ }
+ }
+ if (cmd != PLIST_ORIGIN && ( Verbose || 0 != strncmp("bsdpan-", installed[i], 7 ) ) )
+ warnx("package %s has no origin recorded", installed[i]);
+ fclose(fp);
+ }
+
+ /* Resolve origins into package names, retaining the sequence */
+ for (i = 0; origins[i] != NULL; i++) {
+ matches = realloc(matches, (i + 1) * sizeof(*matches));
+ struct store *store = NULL;
+ store = storecreate(store);
+
+ for (j = 0; installed[j] != NULL; j++) {
+ if (allorigins[j]) {
+ if (csh_match(origins[i], allorigins[j], FNM_PATHNAME) == 0) {
+ storeappend(store, installed[j]);
+ }
+ }
+ }
+ if (store->used == 0)
+ matches[i] = NULL;
+ else
+ matches[i] = store->store;
+ }
+
+ if (allorigins) {
+ for (i = 0; installed[i] != NULL; i++)
+ if (allorigins[i])
+ free(allorigins[i]);
+ free(allorigins);
+ }
+
+ return matches;
+}
+
+/*
+ * Synopsis is similar to matchinstalled(), but use origin
+ * as a key for matching packages.
+ */
+char **
+matchbyorigin(const char *origin, int *retval)
+{
+ const char *origins[2];
+ char ***tmp;
+
+ origins[0] = origin;
+ origins[1] = NULL;
+
+ tmp = matchallbyorigin(origins, retval);
+ if (tmp && tmp[0]) {
+ return tmp[0];
+ } else {
+ return NULL;
+ }
+}
+
+/*
+ * Small linked list to memoize results of isinstalledpkg(). A hash table
+ * would be faster but for n ~= 1000 may be overkill.
+ */
+struct iip_memo {
+ LIST_ENTRY(iip_memo) iip_link;
+ char *iip_name;
+ int iip_result;
+};
+LIST_HEAD(, iip_memo) iip_memo = LIST_HEAD_INITIALIZER(iip_memo);
+
+/*
+ *
+ * Return 1 if the specified package is installed,
+ * 0 if not, and -1 if an error occured.
+ */
+int
+isinstalledpkg(const char *name)
+{
+ int result;
+ char *buf, *buf2;
+ struct iip_memo *memo;
+
+ LIST_FOREACH(memo, &iip_memo, iip_link) {
+ if (strcmp(memo->iip_name, name) == 0)
+ return memo->iip_result;
+ }
+
+ buf2 = NULL;
+ asprintf(&buf, "%s/%s", LOG_DIR, name);
+ if (buf == NULL)
+ goto errout;
+ if (!isdir(buf) || access(buf, R_OK) == FAIL) {
+ result = 0;
+ } else {
+ asprintf(&buf2, "%s/%s", buf, CONTENTS_FNAME);
+ if (buf2 == NULL)
+ goto errout;
+
+ if (!isfile(buf2) || access(buf2, R_OK) == FAIL)
+ result = -1;
+ else
+ result = 1;
+ }
+
+ free(buf);
+ buf = strdup(name);
+ if (buf == NULL)
+ goto errout;
+ free(buf2);
+ buf2 = NULL;
+
+ memo = malloc(sizeof *memo);
+ if (memo == NULL)
+ goto errout;
+ memo->iip_name = buf;
+ memo->iip_result = result;
+ LIST_INSERT_HEAD(&iip_memo, memo, iip_link);
+ return result;
+
+errout:
+ if (buf != NULL)
+ free(buf);
+ if (buf2 != NULL)
+ free(buf2);
+ return -1;
+}
+
+/*
+ * Returns 1 if specified pkgname matches RE pattern.
+ * Otherwise returns 0 if doesn't match or -1 if RE
+ * engine reported an error (usually invalid syntax).
+ */
+static int
+rex_match(const char *pattern, const char *pkgname, int extended)
+{
+ char errbuf[128];
+ int errcode;
+ int retval;
+ regex_t rex;
+
+ retval = 0;
+
+ errcode = regcomp(&rex, pattern, (extended ? REG_EXTENDED : REG_BASIC) | REG_NOSUB);
+ if (errcode == 0)
+ errcode = regexec(&rex, pkgname, 0, NULL, 0);
+
+ if (errcode == 0) {
+ retval = 1;
+ } else if (errcode != REG_NOMATCH) {
+ regerror(errcode, &rex, errbuf, sizeof(errbuf));
+ warnx("%s: %s", pattern, errbuf);
+ retval = -1;
+ }
+
+ regfree(&rex);
+
+ return retval;
+}
+
+/*
+ * Match string by a csh-style glob pattern. Returns 0 on
+ * match and FNM_NOMATCH otherwise, to be compatible with
+ * fnmatch(3).
+ */
+static int
+csh_match(const char *pattern, const char *string, int flags)
+{
+ int ret = FNM_NOMATCH;
+
+
+ const char *nextchoice = pattern;
+ const char *current = NULL;
+
+ int prefixlen = -1;
+ int currentlen = 0;
+
+ int level = 0;
+
+ do {
+ const char *pos = nextchoice;
+ const char *postfix = NULL;
+
+ Boolean quoted = FALSE;
+
+ nextchoice = NULL;
+
+ do {
+ const char *eb;
+ if (!*pos) {
+ postfix = pos;
+ } else if (quoted) {
+ quoted = FALSE;
+ } else {
+ switch (*pos) {
+ case '{':
+ ++level;
+ if (level == 1) {
+ current = pos+1;
+ prefixlen = pos-pattern;
+ }
+ break;
+ case ',':
+ if (level == 1 && !nextchoice) {
+ nextchoice = pos+1;
+ currentlen = pos-current;
+ }
+ break;
+ case '}':
+ if (level == 1) {
+ postfix = pos+1;
+ if (!nextchoice)
+ currentlen = pos-current;
+ }
+ level--;
+ break;
+ case '[':
+ eb = pos+1;
+ if (*eb == '!' || *eb == '^')
+ eb++;
+ if (*eb == ']')
+ eb++;
+ while(*eb && *eb != ']')
+ eb++;
+ if (*eb)
+ pos=eb;
+ break;
+ case '\\':
+ quoted = TRUE;
+ break;
+ default:
+ ;
+ }
+ }
+ pos++;
+ } while (!postfix);
+
+ if (current) {
+ char buf[FILENAME_MAX];
+ snprintf(buf, sizeof(buf), "%.*s%.*s%s", prefixlen, pattern, currentlen, current, postfix);
+ ret = csh_match(buf, string, flags);
+ if (ret) {
+ current = nextchoice;
+ level = 1;
+ } else
+ current = NULL;
+ } else
+ ret = fnmatch(pattern, string, flags);
+ } while (current);
+
+ return ret;
+}
+
+/*
+ * Create an empty store, optionally deallocating
+ * any previously allocated space if store != NULL.
+ */
+struct store *
+storecreate(struct store *store)
+{
+ int i;
+
+ if (store == NULL) {
+ store = malloc(sizeof *store);
+ if (store == NULL) {
+ warnx("%s(): malloc() failed", __func__);
+ return NULL;
+ }
+ store->currlen = 0;
+ store->store = NULL;
+ } else if (store->store != NULL) {
+ /* Free previously allocated memory */
+ for (i = 0; store->store[i] != NULL; i++)
+ free(store->store[i]);
+ store->store[0] = NULL;
+ }
+ store->used = 0;
+
+ return store;
+}
+
+/*
+ * Append specified element to the provided store.
+ */
+static int
+storeappend(struct store *store, const char *item)
+{
+ if (store->used + 2 > store->currlen) {
+ store->currlen += 16;
+ store->store = reallocf(store->store,
+ store->currlen * sizeof(*(store->store)));
+ if (store->store == NULL) {
+ store->currlen = 0;
+ warnx("%s(): reallocf() failed", __func__);
+ return 1;
+ }
+ }
+
+ asprintf(&(store->store[store->used]), "%s", item);
+ if (store->store[store->used] == NULL) {
+ warnx("%s(): malloc() failed", __func__);
+ return 1;
+ }
+ store->used++;
+ store->store[store->used] = NULL;
+
+ return 0;
+}
+
+static int
+fname_cmp(const FTSENT * const *a, const FTSENT * const *b)
+{
+ return strcmp((*a)->fts_name, (*b)->fts_name);
+}
diff --git a/usr.sbin/pkg_install/lib/msg.c b/usr.sbin/pkg_install/lib/msg.c
new file mode 100644
index 0000000..5b17624
--- /dev/null
+++ b/usr.sbin/pkg_install/lib/msg.c
@@ -0,0 +1,75 @@
+/*
+ * FreeBSD install - a package for the installation and maintainance
+ * of non-core utilities.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Jordan K. Hubbard
+ * 18 July 1993
+ *
+ * Miscellaneous message routines.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "lib.h"
+#include <err.h>
+#include <paths.h>
+
+/* Die a relatively simple death */
+void
+upchuck(const char *message)
+{
+ cleanup(0);
+ errx(1, "fatal error during execution: %s", message);
+}
+
+/*
+ * As a yes/no question, prompting from the varargs string and using
+ * default if user just hits return.
+ */
+Boolean
+y_or_n(Boolean def, const char *msg, ...)
+{
+ va_list args;
+ int ch = 0;
+ FILE *tty;
+
+ va_start(args, msg);
+ /*
+ * Need to open /dev/tty because file collection may have been
+ * collected on stdin
+ */
+ tty = fopen(_PATH_TTY, "r");
+ if (!tty) {
+ cleanup(0);
+ errx(2, "can't open %s!", _PATH_TTY);
+ }
+ while (ch != 'Y' && ch != 'N') {
+ vfprintf(stderr, msg, args);
+ if (def)
+ fprintf(stderr, " [yes]? ");
+ else
+ fprintf(stderr, " [no]? ");
+ fflush(stderr);
+ if (AutoAnswer) {
+ ch = (AutoAnswer == YES) ? 'Y' : 'N';
+ fprintf(stderr, "%c\n", ch);
+ }
+ else
+ ch = toupper(fgetc(tty));
+ if (ch == '\n')
+ ch = (def) ? 'Y' : 'N';
+ }
+ fclose(tty) ;
+ return (ch == 'Y') ? TRUE : FALSE;
+}
diff --git a/usr.sbin/pkg_install/lib/pen.c b/usr.sbin/pkg_install/lib/pen.c
new file mode 100644
index 0000000..2b405a3
--- /dev/null
+++ b/usr.sbin/pkg_install/lib/pen.c
@@ -0,0 +1,186 @@
+/*
+ * FreeBSD install - a package for the installation and maintainance
+ * of non-core utilities.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Jordan K. Hubbard
+ * 18 July 1993
+ *
+ * Routines for managing the "play pen".
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "lib.h"
+#include <err.h>
+#include <libutil.h>
+#include <libgen.h>
+#include <sys/signal.h>
+#include <sys/param.h>
+#include <sys/mount.h>
+
+/* For keeping track of where we are */
+static char PenLocation[FILENAME_MAX];
+
+char *
+where_playpen(void)
+{
+ return PenLocation;
+}
+
+/* Find a good place to play. */
+static char *
+find_play_pen(char *pen, off_t sz)
+{
+ char *cp;
+ struct stat sb;
+ char humbuf[6];
+
+ if (pen[0] && isdir(dirname(pen)) == TRUE && (min_free(dirname(pen)) >= sz))
+ return pen;
+ else if ((cp = getenv("PKG_TMPDIR")) != NULL && stat(cp, &sb) != FAIL && (min_free(cp) >= sz))
+ sprintf(pen, "%s/instmp.XXXXXX", cp);
+ else if ((cp = getenv("TMPDIR")) != NULL && stat(cp, &sb) != FAIL && (min_free(cp) >= sz))
+ sprintf(pen, "%s/instmp.XXXXXX", cp);
+ else if (stat("/var/tmp", &sb) != FAIL && min_free("/var/tmp") >= sz)
+ strcpy(pen, "/var/tmp/instmp.XXXXXX");
+ else if (stat("/tmp", &sb) != FAIL && min_free("/tmp") >= sz)
+ strcpy(pen, "/tmp/instmp.XXXXXX");
+ else if ((stat("/usr/tmp", &sb) == SUCCESS || mkdir("/usr/tmp", 01777) == SUCCESS) && min_free("/usr/tmp") >= sz)
+ strcpy(pen, "/usr/tmp/instmp.XXXXXX");
+ else {
+ cleanup(0);
+ humanize_number(humbuf, sizeof humbuf, sz, "", HN_AUTOSCALE,
+ HN_NOSPACE);
+ errx(2,
+"%s: can't find enough temporary space to extract the files, please set your\n"
+"PKG_TMPDIR environment variable to a location with at least %s bytes\n"
+"free", __func__, humbuf);
+ return NULL;
+ }
+ return pen;
+}
+
+#define MAX_STACK 20
+static char *pstack[MAX_STACK];
+static int pdepth = -1;
+
+static const char *
+pushPen(const char *pen)
+{
+ if (++pdepth == MAX_STACK)
+ errx(2, "%s: stack overflow.\n", __func__);
+ pstack[pdepth] = strdup(pen);
+
+ return pstack[pdepth];
+}
+
+static void
+popPen(char *pen)
+{
+ if (pdepth == -1) {
+ pen[0] = '\0';
+ return;
+ }
+ strcpy(pen, pstack[pdepth]);
+ free(pstack[pdepth--]);
+}
+
+/*
+ * Make a temporary directory to play in and chdir() to it, returning
+ * pathname of previous working directory.
+ */
+const char *
+make_playpen(char *pen, off_t sz)
+{
+ char humbuf1[6], humbuf2[6];
+ char cwd[FILENAME_MAX];
+
+ if (!find_play_pen(pen, sz))
+ return NULL;
+
+ if (!mkdtemp(pen)) {
+ cleanup(0);
+ errx(2, "%s: can't mktemp '%s'", __func__, pen);
+ }
+
+ if (Verbose) {
+ if (sz) {
+ humanize_number(humbuf1, sizeof humbuf1, sz, "", HN_AUTOSCALE,
+ HN_NOSPACE);
+ humanize_number(humbuf2, sizeof humbuf2, min_free(pen),
+ "", HN_AUTOSCALE, HN_NOSPACE);
+ fprintf(stderr, "Requested space: %s bytes, free space: %s bytes in %s\n", humbuf1, humbuf2, pen);
+ }
+ }
+
+ if (min_free(pen) < sz) {
+ rmdir(pen);
+ cleanup(0);
+ errx(2, "%s: not enough free space to create '%s'.\n"
+ "Please set your PKG_TMPDIR environment variable to a location\n"
+ "with more space and\ntry the command again", __func__, pen);
+ }
+
+ if (!getcwd(cwd, FILENAME_MAX)) {
+ upchuck("getcwd");
+ return NULL;
+ }
+
+ if (chdir(pen) == FAIL) {
+ cleanup(0);
+ errx(2, "%s: can't chdir to '%s'", __func__, pen);
+ }
+
+ strcpy(PenLocation, pen);
+ return pushPen(cwd);
+}
+
+/* Convenience routine for getting out of playpen */
+int
+leave_playpen()
+{
+ static char left[FILENAME_MAX];
+ void (*oldsig)(int);
+
+ if (!PenLocation[0])
+ return 0;
+
+ /* Don't interrupt while we're cleaning up */
+ oldsig = signal(SIGINT, SIG_IGN);
+ strcpy(left, PenLocation);
+ popPen(PenLocation);
+
+ if (chdir(PenLocation) == FAIL) {
+ cleanup(0);
+ errx(2, "%s: can't chdir back to '%s'", __func__, PenLocation);
+ }
+
+ if (left[0] == '/' && vsystem("/bin/rm -rf %s", left))
+ warnx("couldn't remove temporary dir '%s'", left);
+ signal(SIGINT, oldsig);
+
+ return 1;
+}
+
+off_t
+min_free(const char *tmpdir)
+{
+ struct statfs buf;
+
+ if (statfs(tmpdir, &buf) != 0) {
+ warn("statfs");
+ return -1;
+ }
+ return (off_t)buf.f_bavail * (off_t)buf.f_bsize;
+}
diff --git a/usr.sbin/pkg_install/lib/pkgwrap.c b/usr.sbin/pkg_install/lib/pkgwrap.c
new file mode 100644
index 0000000..cbd15cd
--- /dev/null
+++ b/usr.sbin/pkg_install/lib/pkgwrap.c
@@ -0,0 +1,89 @@
+/*
+ * FreeBSD install - a package for the installation and maintenance
+ * of non-core utilities.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Maxim Sobolev
+ * 8 September 2002
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "lib.h"
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#undef main
+
+#define SEPARATORS " \t"
+
+extern char **environ;
+
+int
+main(int argc, char **argv)
+{
+ FILE *f;
+ char buffer[FILENAME_MAX], *cp, *verstr;
+ int len;
+
+ if (getenv("PKG_NOWRAP") != NULL)
+ goto nowrap;
+ f = fopen(PKG_WRAPCONF_FNAME, "r");
+ if (f == NULL)
+ goto nowrap;
+ cp = fgets(buffer, 256, f);
+ fclose(f);
+ if (cp == NULL)
+ goto nowrap;
+ len = strlen(cp);
+ if (cp[len - 1] == '\n')
+ cp[len - 1] = '\0';
+ while (strchr(SEPARATORS, *cp) != NULL)
+ cp++;
+ verstr = cp;
+ cp = strpbrk(cp, SEPARATORS);
+ if (cp == NULL)
+ goto nowrap;
+ *cp = '\0';
+ for (cp = verstr; *cp != '\0'; cp++)
+ if (isdigit(*cp) == 0)
+ goto nowrap;
+ if (atoi(verstr) < PKG_INSTALL_VERSION)
+ goto nowrap;
+ cp++;
+ while (*cp != '\0' && strchr(SEPARATORS, *cp) != NULL)
+ cp++;
+ if (*cp == '\0')
+ goto nowrap;
+ bcopy(cp, buffer, strlen(cp) + 1);
+ cp = strpbrk(buffer, SEPARATORS);
+ if (cp != NULL)
+ *cp = '\0';
+ if (!isdir(buffer))
+ goto nowrap;
+ cp = strrchr(argv[0], '/');
+ if (cp == NULL)
+ cp = argv[0];
+ else
+ cp++;
+ strlcat(buffer, "/", sizeof(buffer));
+ strlcat(buffer, cp, sizeof(buffer));
+ setenv("PKG_NOWRAP", "1", 1);
+ execve(buffer, argv, environ);
+
+nowrap:
+ unsetenv("PKG_NOWRAP");
+ return(real_main(argc, argv));
+}
diff --git a/usr.sbin/pkg_install/lib/plist.c b/usr.sbin/pkg_install/lib/plist.c
new file mode 100644
index 0000000..545b541
--- /dev/null
+++ b/usr.sbin/pkg_install/lib/plist.c
@@ -0,0 +1,592 @@
+/*
+ * FreeBSD install - a package for the installation and maintainance
+ * of non-core utilities.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Jordan K. Hubbard
+ * 18 July 1993
+ *
+ * General packing list routines.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "lib.h"
+#include <err.h>
+#include <md5.h>
+
+/* Add an item to a packing list */
+void
+add_plist(Package *p, plist_t type, const char *arg)
+{
+ PackingList tmp;
+
+ tmp = new_plist_entry();
+ tmp->name = copy_string(arg);
+ tmp->type = type;
+
+ if (!p->head)
+ p->head = p->tail = tmp;
+ else {
+ tmp->prev = p->tail;
+ p->tail->next = tmp;
+ p->tail = tmp;
+ }
+ switch (type) {
+ case PLIST_NAME:
+ p->name = tmp->name;
+ break;
+
+ case PLIST_ORIGIN:
+ p->origin = tmp->name;
+ break;
+
+ default:
+ break;
+ }
+}
+
+void
+add_plist_top(Package *p, plist_t type, const char *arg)
+{
+ PackingList tmp;
+
+ tmp = new_plist_entry();
+ tmp->name = copy_string(arg);
+ tmp->type = type;
+
+ if (!p->head)
+ p->head = p->tail = tmp;
+ else {
+ tmp->next = p->head;
+ p->head->prev = tmp;
+ p->head = tmp;
+ }
+}
+
+/* Return the last (most recent) entry in a packing list */
+PackingList
+last_plist(Package *p)
+{
+ return p->tail;
+}
+
+/* Mark all items in a packing list to prevent iteration over them */
+void
+mark_plist(Package *pkg)
+{
+ PackingList p = pkg->head;
+
+ while (p) {
+ p->marked = TRUE;
+ p = p->next;
+ }
+}
+
+/* Find a given item in a packing list and, if so, return it (else NULL) */
+PackingList
+find_plist(Package *pkg, plist_t type)
+{
+ PackingList p = pkg->head;
+
+ while (p) {
+ if (p->type == type)
+ return p;
+ p = p->next;
+ }
+ return NULL;
+}
+
+/* Look for a specific boolean option argument in the list */
+char *
+find_plist_option(Package *pkg, const char *name)
+{
+ PackingList p = pkg->head;
+
+ while (p) {
+ if (p->type == PLIST_OPTION && !strcmp(p->name, name))
+ return p->name;
+ p = p->next;
+ }
+ return NULL;
+}
+
+/*
+ * Delete plist item 'type' in the list (if 'name' is non-null, match it
+ * too.) If 'all' is set, delete all items, not just the first occurance.
+ */
+void
+delete_plist(Package *pkg, Boolean all, plist_t type, const char *name)
+{
+ PackingList p = pkg->head;
+
+ while (p) {
+ PackingList pnext = p->next;
+
+ if (p->type == type && (!name || !strcmp(name, p->name))) {
+ free(p->name);
+ if (p->prev)
+ p->prev->next = pnext;
+ else
+ pkg->head = pnext;
+ if (pnext)
+ pnext->prev = p->prev;
+ else
+ pkg->tail = p->prev;
+ free(p);
+ if (!all)
+ return;
+ p = pnext;
+ }
+ else
+ p = p->next;
+ }
+}
+
+/* Allocate a new packing list entry */
+PackingList
+new_plist_entry(void)
+{
+ PackingList ret;
+
+ ret = (PackingList)malloc(sizeof(struct _plist));
+ bzero(ret, sizeof(struct _plist));
+ return ret;
+}
+
+/* Free an entire packing list */
+void
+free_plist(Package *pkg)
+{
+ PackingList p = pkg->head;
+
+ while (p) {
+ PackingList p1 = p->next;
+
+ free(p->name);
+ free(p);
+ p = p1;
+ }
+ pkg->head = pkg->tail = NULL;
+}
+
+/*
+ * For an ascii string denoting a plist command, return its code and
+ * optionally its argument(s)
+ */
+int
+plist_cmd(const char *s, char **arg)
+{
+ char cmd[FILENAME_MAX + 20]; /* 20 == fudge for max cmd len */
+ char *cp;
+ const char *sp;
+
+ strcpy(cmd, s);
+ str_lowercase(cmd);
+ cp = cmd;
+ sp = s;
+ while (*cp) {
+ if (isspace(*cp)) {
+ *cp = '\0';
+ while (isspace(*sp)) /* Never sure if macro, increment later */
+ ++sp;
+ break;
+ }
+ ++cp, ++sp;
+ }
+ if (arg)
+ *arg = (char *)sp;
+ if (!strcmp(cmd, "cwd"))
+ return PLIST_CWD;
+ else if (!strcmp(cmd, "srcdir"))
+ return PLIST_SRC;
+ else if (!strcmp(cmd, "cd"))
+ return PLIST_CWD;
+ else if (!strcmp(cmd, "exec"))
+ return PLIST_CMD;
+ else if (!strcmp(cmd, "unexec"))
+ return PLIST_UNEXEC;
+ else if (!strcmp(cmd, "mode"))
+ return PLIST_CHMOD;
+ else if (!strcmp(cmd, "owner"))
+ return PLIST_CHOWN;
+ else if (!strcmp(cmd, "group"))
+ return PLIST_CHGRP;
+ else if (!strcmp(cmd, "noinst"))
+ return PLIST_NOINST;
+ else if (!strcmp(cmd, "comment")) {
+ if (!strncmp(*arg, "ORIGIN:", 7)) {
+ *arg += 7;
+ return PLIST_ORIGIN;
+ } else if (!strncmp(*arg, "DEPORIGIN:", 10)) {
+ *arg += 10;
+ return PLIST_DEPORIGIN;
+ }
+ return PLIST_COMMENT;
+ } else if (!strcmp(cmd, "ignore"))
+ return PLIST_IGNORE;
+ else if (!strcmp(cmd, "ignore_inst"))
+ return PLIST_IGNORE_INST;
+ else if (!strcmp(cmd, "name"))
+ return PLIST_NAME;
+ else if (!strcmp(cmd, "display"))
+ return PLIST_DISPLAY;
+ else if (!strcmp(cmd, "pkgdep"))
+ return PLIST_PKGDEP;
+ else if (!strcmp(cmd, "conflicts"))
+ return PLIST_CONFLICTS;
+ else if (!strcmp(cmd, "mtree"))
+ return PLIST_MTREE;
+ else if (!strcmp(cmd, "dirrm"))
+ return PLIST_DIR_RM;
+ else if (!strcmp(cmd, "option"))
+ return PLIST_OPTION;
+ else
+ return FAIL;
+}
+
+/* Read a packing list from a file */
+void
+read_plist(Package *pkg, FILE *fp)
+{
+ char *cp, pline[FILENAME_MAX];
+ int cmd, major, minor;
+
+ pkg->fmtver_maj = 1;
+ pkg->fmtver_mnr = 0;
+ pkg->origin = NULL;
+ while (fgets(pline, FILENAME_MAX, fp)) {
+ int len = strlen(pline);
+
+ while (len && isspace(pline[len - 1]))
+ pline[--len] = '\0';
+ if (!len)
+ continue;
+ cp = pline;
+ if (pline[0] != CMD_CHAR) {
+ cmd = PLIST_FILE;
+ goto bottom;
+ }
+ cmd = plist_cmd(pline + 1, &cp);
+ if (cmd == FAIL) {
+ warnx("%s: unknown command '%s' (package tools out of date?)",
+ __func__, pline);
+ goto bottom;
+ }
+ if (*cp == '\0') {
+ cp = NULL;
+ if (cmd == PLIST_PKGDEP) {
+ warnx("corrupted record (pkgdep line without argument), ignoring");
+ cmd = FAIL;
+ }
+ goto bottom;
+ }
+ if (cmd == PLIST_COMMENT && sscanf(cp, "PKG_FORMAT_REVISION:%d.%d\n",
+ &major, &minor) == 2) {
+ pkg->fmtver_maj = major;
+ pkg->fmtver_mnr = minor;
+ if (verscmp(pkg, PLIST_FMT_VER_MAJOR, PLIST_FMT_VER_MINOR) <= 0)
+ goto bottom;
+
+ warnx("plist format revision (%d.%d) is higher than supported"
+ "(%d.%d)", pkg->fmtver_maj, pkg->fmtver_mnr,
+ PLIST_FMT_VER_MAJOR, PLIST_FMT_VER_MINOR);
+ if (pkg->fmtver_maj > PLIST_FMT_VER_MAJOR) {
+ cleanup(0);
+ exit(2);
+ }
+ }
+bottom:
+ add_plist(pkg, cmd, cp);
+ }
+}
+
+/* Write a packing list to a file, converting commands to ascii equivs */
+void
+write_plist(Package *pkg, FILE *fp)
+{
+ PackingList plist = pkg->head;
+
+ while (plist) {
+ switch(plist->type) {
+ case PLIST_FILE:
+ fprintf(fp, "%s\n", plist->name);
+ break;
+
+ case PLIST_CWD:
+ fprintf(fp, "%ccwd %s\n", CMD_CHAR, (plist->name == NULL) ? "" : plist->name);
+ break;
+
+ case PLIST_SRC:
+ fprintf(fp, "%csrcdir %s\n", CMD_CHAR, plist->name);
+ break;
+
+ case PLIST_CMD:
+ fprintf(fp, "%cexec %s\n", CMD_CHAR, plist->name);
+ break;
+
+ case PLIST_UNEXEC:
+ fprintf(fp, "%cunexec %s\n", CMD_CHAR, plist->name);
+ break;
+
+ case PLIST_CHMOD:
+ fprintf(fp, "%cmode %s\n", CMD_CHAR, plist->name ? plist->name : "");
+ break;
+
+ case PLIST_CHOWN:
+ fprintf(fp, "%cowner %s\n", CMD_CHAR, plist->name ? plist->name : "");
+ break;
+
+ case PLIST_CHGRP:
+ fprintf(fp, "%cgroup %s\n", CMD_CHAR, plist->name ? plist->name : "");
+ break;
+
+ case PLIST_COMMENT:
+ fprintf(fp, "%ccomment %s\n", CMD_CHAR, plist->name);
+ break;
+
+ case PLIST_NOINST:
+ fprintf(fp, "%cnoinst %s\n", CMD_CHAR, plist->name);
+ break;
+
+ case PLIST_IGNORE:
+ case PLIST_IGNORE_INST: /* a one-time non-ignored file */
+ fprintf(fp, "%cignore\n", CMD_CHAR);
+ break;
+
+ case PLIST_NAME:
+ fprintf(fp, "%cname %s\n", CMD_CHAR, plist->name);
+ break;
+
+ case PLIST_DISPLAY:
+ fprintf(fp, "%cdisplay %s\n", CMD_CHAR, plist->name);
+ break;
+
+ case PLIST_PKGDEP:
+ fprintf(fp, "%cpkgdep %s\n", CMD_CHAR, plist->name);
+ break;
+
+ case PLIST_CONFLICTS:
+ fprintf(fp, "%cconflicts %s\n", CMD_CHAR, plist->name);
+ break;
+
+ case PLIST_MTREE:
+ fprintf(fp, "%cmtree %s\n", CMD_CHAR, plist->name);
+ break;
+
+ case PLIST_DIR_RM:
+ fprintf(fp, "%cdirrm %s\n", CMD_CHAR, plist->name);
+ break;
+
+ case PLIST_OPTION:
+ fprintf(fp, "%coption %s\n", CMD_CHAR, plist->name);
+ break;
+
+ case PLIST_ORIGIN:
+ fprintf(fp, "%ccomment ORIGIN:%s\n", CMD_CHAR, plist->name);
+ break;
+
+ case PLIST_DEPORIGIN:
+ fprintf(fp, "%ccomment DEPORIGIN:%s\n", CMD_CHAR, plist->name);
+ break;
+
+ default:
+ cleanup(0);
+ errx(2, "%s: unknown command type %d (%s)", __func__,
+ plist->type, plist->name);
+ break;
+ }
+ plist = plist->next;
+ }
+}
+
+/*
+ * Delete the results of a package installation.
+ *
+ * This is here rather than in the pkg_delete code because pkg_add needs to
+ * run it too in cases of failure.
+ */
+int
+delete_package(Boolean ign_err, Boolean nukedirs, Package *pkg)
+{
+ PackingList p;
+ const char *Where = ".", *last_file = "";
+ Boolean fail = SUCCESS;
+ Boolean preserve;
+ char tmp[FILENAME_MAX], *name = NULL;
+ char *prefix = NULL;
+
+ preserve = find_plist_option(pkg, "preserve") ? TRUE : FALSE;
+ for (p = pkg->head; p; p = p->next) {
+ switch (p->type) {
+ case PLIST_NAME:
+ name = p->name;
+ break;
+
+ case PLIST_IGNORE:
+ p = p->next;
+ break;
+
+ case PLIST_CWD:
+ if (!prefix)
+ prefix = p->name;
+ Where = (p->name == NULL) ? prefix : p->name;
+ if (Verbose)
+ printf("Change working directory to %s\n", Where);
+ break;
+
+ case PLIST_UNEXEC:
+ format_cmd(tmp, FILENAME_MAX, p->name, Where, last_file);
+ if (Verbose)
+ printf("Execute '%s'\n", tmp);
+ if (!Fake && system(tmp)) {
+ warnx("unexec command for '%s' failed", tmp);
+ fail = FAIL;
+ }
+ break;
+
+ case PLIST_FILE:
+ last_file = p->name;
+ sprintf(tmp, "%s/%s", Where, p->name);
+ if (isdir(tmp) && fexists(tmp) && !issymlink(tmp)) {
+ warnx("cannot delete specified file '%s' - it is a directory!\n"
+ "this packing list is incorrect - ignoring delete request", tmp);
+ }
+ else {
+ if (p->next && p->next->type == PLIST_COMMENT && !strncmp(p->next->name, "MD5:", 4)) {
+ char *cp = NULL, buf[33];
+
+ /*
+ * For packing lists whose version is 1.1 or greater, the md5
+ * hash for a symlink is calculated on the string returned
+ * by readlink().
+ */
+ if (issymlink(tmp) && verscmp(pkg, 1, 0) > 0) {
+ int len;
+ char linkbuf[FILENAME_MAX];
+
+ if ((len = readlink(tmp, linkbuf, FILENAME_MAX)) > 0)
+ cp = MD5Data((unsigned char *)linkbuf, len, buf);
+ } else if (isfile(tmp) || verscmp(pkg, 1, 1) < 0)
+ cp = MD5File(tmp, buf);
+
+ if (cp != NULL) {
+ /* Mismatch? */
+ if (strcmp(cp, p->next->name + 4)) {
+ warnx("'%s' fails original MD5 checksum - %s",
+ tmp, Force ? "deleted anyway." : "not deleted.");
+ if (!Force) {
+ fail = FAIL;
+ continue;
+ }
+ }
+ }
+ }
+ if (Verbose)
+ printf("Delete file %s\n", tmp);
+ if (!Fake) {
+ if (delete_hierarchy(tmp, ign_err, nukedirs))
+ fail = FAIL;
+ if (preserve && name) {
+ char tmp2[FILENAME_MAX];
+
+ if (make_preserve_name(tmp2, FILENAME_MAX, name, tmp)) {
+ if (fexists(tmp2)) {
+ if (rename(tmp2, tmp))
+ warn("preserve: unable to restore %s as %s",
+ tmp2, tmp);
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ case PLIST_DIR_RM:
+ sprintf(tmp, "%s/%s", Where, p->name);
+ if (!isdir(tmp) && fexists(tmp)) {
+ warnx("cannot delete specified directory '%s' - it is a file!\n"
+ "this packing list is incorrect - ignoring delete request", tmp);
+ }
+ else {
+ if (Verbose)
+ printf("Delete directory %s\n", tmp);
+ if (!Fake && delete_hierarchy(tmp, ign_err, FALSE)) {
+ warnx("unable to completely remove directory '%s'", tmp);
+ fail = FAIL;
+ }
+ }
+ last_file = p->name;
+ break;
+
+ default:
+ break;
+ }
+ }
+ return fail;
+}
+
+#ifdef DEBUG
+#define RMDIR(dir) vsystem("%s %s", RMDIR_CMD, dir)
+#define REMOVE(dir,ie) vsystem("%s %s%s", REMOVE_CMD, (ie ? "-f " : ""), dir)
+#else
+#define RMDIR rmdir
+#define REMOVE(file,ie) (remove(file) && !(ie))
+#endif
+
+/* Selectively delete a hierarchy */
+int
+delete_hierarchy(const char *dir, Boolean ign_err, Boolean nukedirs)
+{
+ char *cp1, *cp2;
+
+ cp1 = cp2 = strdup(dir);
+ if (!fexists(dir) && !issymlink(dir)) {
+ if (!ign_err)
+ warnx("%s '%s' doesn't exist",
+ isdir(dir) ? "directory" : "file", dir);
+ return !ign_err;
+ }
+ else if (nukedirs) {
+ if (vsystem("%s -r%s %s", REMOVE_CMD, (ign_err ? "f" : ""), dir))
+ return 1;
+ }
+ else if (isdir(dir) && !issymlink(dir)) {
+ if (RMDIR(dir) && !ign_err)
+ return 1;
+ }
+ else {
+ if (REMOVE(dir, ign_err))
+ return 1;
+ }
+
+ if (!nukedirs)
+ return 0;
+ while (cp2) {
+ if ((cp2 = strrchr(cp1, '/')) != NULL)
+ *cp2 = '\0';
+ if (!isemptydir(dir))
+ return 0;
+ if (RMDIR(dir) && !ign_err) {
+ if (!fexists(dir))
+ warnx("directory '%s' doesn't exist", dir);
+ else
+ return 1;
+ }
+ /* back up the pathname one component */
+ if (cp2) {
+ cp1 = strdup(dir);
+ }
+ }
+ return 0;
+}
diff --git a/usr.sbin/pkg_install/lib/str.c b/usr.sbin/pkg_install/lib/str.c
new file mode 100644
index 0000000..0d9e288
--- /dev/null
+++ b/usr.sbin/pkg_install/lib/str.c
@@ -0,0 +1,129 @@
+/*
+ * FreeBSD install - a package for the installation and maintainance
+ * of non-core utilities.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Jordan K. Hubbard
+ * 18 July 1993
+ *
+ * Miscellaneous string utilities.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "lib.h"
+
+char *
+strconcat(const char *s1, const char *s2)
+{
+ static char tmp[FILENAME_MAX];
+
+ tmp[0] = '\0';
+ strncpy(tmp, s1 ? s1 : s2, FILENAME_MAX); /* XXX: what if both are NULL? */
+ if (s1 && s2)
+ strncat(tmp, s2, FILENAME_MAX - strlen(tmp));
+ return tmp;
+}
+
+/* Get a string parameter as a file spec or as a "contents follow -" spec */
+char *
+get_dash_string(char **str)
+{
+ char *s = *str;
+
+ if (*s == '-')
+ *str = copy_string_adds_newline(s + 1);
+ else
+ *str = fileGetContents(s);
+ return *str;
+}
+
+/* Rather Obvious */
+char *
+copy_string(const char *str)
+{
+ return (str ? strdup(str) : NULL);
+}
+
+/* Rather Obvious but adds a trailing \n newline */
+char *
+copy_string_adds_newline(const char *str)
+{
+ if (str == NULL) {
+ return (NULL);
+ } else {
+ char *copy;
+ size_t line_length;
+
+ line_length = strlen(str) + 2;
+ if ((copy = malloc(line_length)) == NULL)
+ return (NULL);
+ memcpy(copy, str, line_length - 2);
+ copy[line_length - 2] = '\n'; /* Adds trailing \n */
+ copy[line_length - 1] = '\0';
+
+ return (copy);
+ }
+}
+
+/* Return TRUE if 'str' ends in suffix 'suff' */
+Boolean
+suffix(const char *str, const char *suff)
+{
+ char *idx;
+ Boolean ret = FALSE;
+
+ idx = strrchr(str, '.');
+ if (idx && !strcmp(idx + 1, suff))
+ ret = TRUE;
+ return ret;
+}
+
+/* Assuming str has a suffix, brutally murder it! */
+void
+nuke_suffix(char *str)
+{
+ char *idx;
+
+ idx = strrchr(str, '.');
+ if (idx)
+ *idx = '\0'; /* Yow! Don't try this on a const! */
+}
+
+/* Lowercase a whole string */
+void
+str_lowercase(char *str)
+{
+ while (*str) {
+ *str = tolower(*str);
+ ++str;
+ }
+}
+
+char *
+get_string(char *str, int max, FILE *fp)
+{
+ int len;
+
+ if (!str)
+ return NULL;
+ str[0] = '\0';
+ while (fgets(str, max, fp)) {
+ len = strlen(str);
+ while (len && isspace(str[len - 1]))
+ str[--len] = '\0';
+ if (len)
+ return str;
+ }
+ return NULL;
+}
diff --git a/usr.sbin/pkg_install/lib/url.c b/usr.sbin/pkg_install/lib/url.c
new file mode 100644
index 0000000..8c55347
--- /dev/null
+++ b/usr.sbin/pkg_install/lib/url.c
@@ -0,0 +1,171 @@
+/*
+ * FreeBSD install - a package for the installation and maintainance
+ * of non-core utilities.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Jordan K. Hubbard
+ * 18 July 1993
+ *
+ * URL file access utilities.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "lib.h"
+#include <err.h>
+#include <fetch.h>
+#include <libgen.h>
+#include <sys/wait.h>
+#include <stdio.h>
+
+/*
+ * Try and fetch a file by URL, returning the directory name for where
+ * it's unpacked, if successful.
+ */
+const char *
+fileGetURL(const char *base, const char *spec, int keep_package)
+{
+ const char *rp;
+ char *cp, *tmp;
+ char fname[FILENAME_MAX];
+ char pen[FILENAME_MAX];
+ char pkg[FILENAME_MAX];
+ char buf[8192];
+ FILE *ftp;
+ pid_t tpid;
+ int pfd[2], pstat, r, w = 0;
+ char *hint;
+ int fd, pkgfd = 0;
+
+ rp = NULL;
+ /* Special tip that sysinstall left for us */
+ hint = getenv("PKG_ADD_BASE");
+ if (!isURL(spec)) {
+ if (!base && !hint)
+ return NULL;
+ /*
+ * We've been given an existing URL (that's known-good) and now we need
+ * to construct a composite one out of that and the basename we were
+ * handed as a dependency.
+ */
+ if (base) {
+ strcpy(fname, base);
+ /*
+ * Advance back two slashes to get to the root of the package
+ * hierarchy
+ */
+ cp = strrchr(fname, '/');
+ if (cp) {
+ *cp = '\0'; /* chop name */
+ cp = strrchr(fname, '/');
+ }
+ if (cp) {
+ *(cp + 1) = '\0';
+ strcat(cp, "All/");
+ strcat(cp, spec);
+ strcat(cp, ".tbz");
+ }
+ else
+ return NULL;
+ }
+ else {
+ /*
+ * Otherwise, we've been given an environment variable hinting
+ * at the right location from sysinstall
+ */
+ strcpy(fname, hint);
+ strcat(fname, spec);
+ strcat(fname, ".tbz");
+ }
+ }
+ else
+ strcpy(fname, spec);
+
+ if (keep_package) {
+ tmp = getenv("PKGDIR");
+ strlcpy(pkg, tmp ? tmp : ".", sizeof(pkg));
+ tmp = basename(fname);
+ strlcat(pkg, "/", sizeof(pkg));
+ strlcat(pkg, tmp, sizeof(pkg));
+ if ((pkgfd = open(pkg, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1) {
+ printf("Error: Unable to open %s\n", pkg);
+ perror("open");
+ return NULL;
+ }
+ }
+
+ fetchDebug = (Verbose > 0);
+ if ((ftp = fetchGetURL(fname, Verbose ? "v" : NULL)) == NULL) {
+ printf("Error: Unable to get %s: %s\n",
+ fname, fetchLastErrString);
+ /* If the fetch fails, yank the package. */
+ if (keep_package && unlink(pkg) < 0 && Verbose) {
+ warnx("failed to remove partially fetched package: %s", pkg);
+ }
+ return NULL;
+ }
+
+ if (isatty(0) || Verbose)
+ printf("Fetching %s...", fname), fflush(stdout);
+ pen[0] = '\0';
+ if ((rp = make_playpen(pen, 0)) == NULL) {
+ printf("Error: Unable to construct a new playpen for FTP!\n");
+ fclose(ftp);
+ return NULL;
+ }
+ if (pipe(pfd) == -1) {
+ warn("pipe()");
+ cleanup(0);
+ exit(2);
+ }
+ if ((tpid = fork()) == -1) {
+ warn("pipe()");
+ cleanup(0);
+ exit(2);
+ }
+ if (!tpid) {
+ dup2(pfd[0], 0);
+ for (fd = getdtablesize() - 1; fd >= 3; --fd)
+ close(fd);
+ execl("/usr/bin/tar", "tar",
+ Verbose ? "-xpjvf" : "-xpjf",
+ "-", (char *)0);
+ _exit(2);
+ }
+ close(pfd[0]);
+ for (;;) {
+ if ((r = fread(buf, 1, sizeof buf, ftp)) < 1)
+ break;
+ if ((w = write(pfd[1], buf, r)) != r)
+ break;
+ if (keep_package) {
+ if ((w = write(pkgfd, buf, r)) != r)
+ break;
+ }
+ }
+ if (ferror(ftp))
+ warn("warning: error reading from server");
+ fclose(ftp);
+ if (keep_package) {
+ close(pkgfd);
+ }
+ close(pfd[1]);
+ if (w == -1)
+ warn("warning: error writing to tar");
+ tpid = waitpid(tpid, &pstat, 0);
+ if (Verbose)
+ printf("tar command returns %d status\n", WEXITSTATUS(pstat));
+ if (rp && (isatty(0) || Verbose))
+ printf(" Done.\n");
+ return rp;
+}
diff --git a/usr.sbin/pkg_install/lib/version.c b/usr.sbin/pkg_install/lib/version.c
new file mode 100644
index 0000000..d9c4fe7
--- /dev/null
+++ b/usr.sbin/pkg_install/lib/version.c
@@ -0,0 +1,328 @@
+/*
+ * FreeBSD install - a package for the installation and maintenance
+ * of non-core utilities.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Maxim Sobolev
+ * 31 July 2001
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "lib.h"
+#include <err.h>
+
+/*
+ * Routines to assist with PLIST_FMT_VER numbers in the packing
+ * lists.
+ *
+ * Following is the PLIST_FMT_VER history:
+ * 1.0 - Initial revision;
+ * 1.1 - When recording/checking checksum of symlink use hash of readlink()
+ * value instead of the hash of an object this links points to.
+ *
+ */
+int
+verscmp(Package *pkg, int major, int minor)
+{
+ int rval = 0;
+
+ if ((pkg->fmtver_maj < major) || (pkg->fmtver_maj == major &&
+ pkg->fmtver_mnr < minor))
+ rval = -1;
+ else if ((pkg->fmtver_maj > major) || (pkg->fmtver_maj == major &&
+ pkg->fmtver_mnr > minor))
+ rval = 1;
+
+ return rval;
+}
+
+/*
+ * split_version(pkgname, endname, epoch, revision) returns a pointer to
+ * the version portion of a package name and the two special components.
+ *
+ * Syntax is: ${PORTNAME}-${PORTVERSION}[_${PORTREVISION}][,${PORTEPOCH}]
+ *
+ * Written by Oliver Eikemeier
+ * Based on work of Jeremy D. Lea.
+ */
+static const char *
+split_version(const char *pkgname, const char **endname, unsigned long *epoch, unsigned long *revision)
+{
+ char *ch;
+ const char *versionstr;
+ const char *endversionstr;
+
+ if (pkgname == NULL)
+ errx(2, "%s: Passed NULL pkgname.", __func__);
+
+ /* Look for the last '-' the the pkgname */
+ ch = strrchr(pkgname, '-');
+ /* Cheat if we are just passed a version, not a valid package name */
+ versionstr = ch ? ch + 1 : pkgname;
+
+ /* Look for the last '_' in the version string, advancing the end pointer */
+ ch = strrchr(versionstr, '_');
+ if (revision != NULL) {
+ *revision = ch ? strtoul(ch + 1, NULL, 10) : 0;
+ }
+ endversionstr = ch;
+
+ /* Look for the last ',' in the remaining version string */
+ ch = strrchr(endversionstr ? endversionstr + 1 : versionstr, ',');
+ if (epoch != NULL) {
+ *epoch = ch ? strtoul(ch + 1, NULL, 10) : 0;
+ }
+ if (ch && !endversionstr)
+ endversionstr = ch;
+
+ /* set the pointer behind the last character of the version without revision or epoch */
+ if (endname)
+ *endname = endversionstr ? endversionstr : strrchr(versionstr, '\0');
+
+ return versionstr;
+}
+
+/*
+ * PORTVERSIONs are composed of components separated by dots. A component
+ * consists of a version number, a letter and a patchlevel number. This does
+ * not conform to the porter's handbook, but let us formulate rules that
+ * fit the current practice and are far simpler than to make decisions
+ * based on the order of netters and lumbers. Besides, people use versions
+ * like 10b2 in the ports...
+ */
+
+typedef struct {
+#ifdef __LONG_LONG_SUPPORTED
+ long long n;
+ long long pl;
+#else
+ long n;
+ long pl;
+#endif
+ int a;
+} version_component;
+
+/*
+ * get_component(position, component) gets the value of the next component
+ * (number - letter - number triple) and returns a pointer to the next character
+ * after any leading separators
+ *
+ * - components are separated by dots
+ * - characters !~ [a-zA-Z0-9.+*] are treated as separators
+ * (1.0:2003.09.16 = 1.0.2003.09.16), this may not be what you expect:
+ * 1.0.1:2003.09.16 < 1.0:2003.09.16
+ * - consecutive separators are collapsed (10..1 = 10.1)
+ * - missing separators are inserted, essentially
+ * letter number letter => letter number . letter (10a1b2 = 10a1.b2)
+ * - missing components are assumed to be equal to 0 (10 = 10.0 = 10.0.0)
+ * - the letter sort order is: [none], a, b, ..., z; numbers without letters
+ * sort first (10 < 10a < 10b)
+ * - missing version numbers (in components starting with a letter) sort as -1
+ * (a < 0, 10.a < 10)
+ * - a separator is inserted before the special strings "pl", "alpha", "beta",
+ * "pre" and "rc".
+ * - "pl" sorts before every other letter, "alpha", "beta", "pre" and "rc"
+ * sort as a, b, p and r. (10alpha = 10.a < 10, but 10 < 10a; pl11 < alpha3
+ * < 0.1beta2 = 0.1.b2 < 0.1)
+ * - other strings use only the first letter for sorting, case is ignored
+ * (1.d2 = 1.dev2 = 1.Development2)
+ * - The special component `*' is guaranteed to be the smallest possible
+ * component (2.* < 2pl1 < 2alpha3 < 2.9f7 < 3.*)
+ * - components separated by `+' are handled by version_cmp below
+ *
+ * Oliver Eikemeier
+ */
+
+static const struct {
+ const char *name;
+ size_t namelen;
+ int value;
+} stage[] = {
+ { "pl", 2, 0 },
+ { "alpha", 5, 'a'-'a'+1 },
+ { "beta", 4, 'b'-'a'+1 },
+ { "pre", 3, 'p'-'a'+1 },
+ { "rc", 2, 'r'-'a'+1 },
+ { NULL, 0, -1 }
+};
+
+static const char *
+get_component(const char *position, version_component *component)
+{
+ const char *pos = position;
+ int hasstage = 0, haspatchlevel = 0;
+
+ if (!pos)
+ errx(2, "%s: Passed NULL position.", __func__);
+
+ /* handle version number */
+ if (isdigit(*pos)) {
+ char *endptr;
+#ifdef __LONG_LONG_SUPPORTED
+ component->n = strtoll(pos, &endptr, 10);
+#else
+ component->n = strtol(pos, &endptr, 10);
+#endif
+ /* should we test for errno == ERANGE? */
+ pos = endptr;
+ } else if (*pos == '*') {
+ component->n = -2;
+ do {
+ pos++;
+ } while(*pos && *pos != '+');
+ } else {
+ component->n = -1;
+ hasstage = 1;
+ }
+
+ /* handle letter */
+ if (isalpha(*pos)) {
+ int c = tolower(*pos);
+ haspatchlevel = 1;
+ /* handle special suffixes */
+ if (isalpha(pos[1])) {
+ int i;
+ for (i = 0; stage[i].name; i++) {
+ if (strncasecmp(pos, stage[i].name, stage[i].namelen) == 0
+ && !isalpha(pos[stage[i].namelen])) {
+ if (hasstage) {
+ /* stage to value */
+ component->a = stage[i].value;
+ pos += stage[i].namelen;
+ } else {
+ /* insert dot */
+ component->a = 0;
+ haspatchlevel = 0;
+ }
+ c = 0;
+ break;
+ }
+ }
+ }
+ /* unhandled above */
+ if (c) {
+ /* use the first letter and skip following */
+ component->a = c - 'a' + 1;
+ do {
+ ++pos;
+ } while (isalpha(*pos));
+ }
+ } else {
+ component->a = 0;
+ haspatchlevel = 0;
+ }
+
+ if (haspatchlevel) {
+ /* handle patch number */
+ if (isdigit(*pos)) {
+ char *endptr;
+#ifdef __LONG_LONG_SUPPORTED
+ component->pl = strtoll(pos, &endptr, 10);
+#else
+ component->pl = strtol(pos, &endptr, 10);
+#endif
+ /* should we test for errno == ERANGE? */
+ pos = endptr;
+ } else {
+ component->pl = -1;
+ }
+ } else {
+ component->pl = 0;
+ }
+
+ /* skip trailing separators */
+ while (*pos && !isdigit(*pos) && !isalpha(*pos) && *pos != '+' && *pos != '*') {
+ pos++;
+ }
+
+ return pos;
+}
+
+/*
+ * version_cmp(pkg1, pkg2) returns -1, 0 or 1 depending on if the version
+ * components of pkg1 is less than, equal to or greater than pkg2. No
+ * comparison of the basenames is done.
+ *
+ * The port version is defined by:
+ * ${PORTVERSION}[_${PORTREVISION}][,${PORTEPOCH}]
+ * ${PORTEPOCH} supersedes ${PORTVERSION} supersedes ${PORTREVISION}.
+ * See the commit log for revision 1.349 of ports/Mk/bsd.port.mk
+ * for more information.
+ *
+ * The epoch and revision are defined to be a single number, while the rest
+ * of the version should conform to the porting guidelines. It can contain
+ * multiple components, separated by a period, including letters.
+ *
+ * The tests allow for significantly more latitude in the version numbers
+ * than is allowed in the guidelines. No point in enforcing them here.
+ * That's what portlint is for.
+ *
+ * Jeremy D. Lea.
+ * reimplemented by Oliver Eikemeier
+ */
+int
+version_cmp(const char *pkg1, const char *pkg2)
+{
+ const char *v1, *v2, *ve1, *ve2;
+ unsigned long e1, e2, r1, r2;
+ int result = 0;
+
+ v1 = split_version(pkg1, &ve1, &e1, &r1);
+ v2 = split_version(pkg2, &ve2, &e2, &r2);
+
+ /* Check epoch, port version, and port revision, in that order. */
+ if (e1 != e2) {
+ result = (e1 < e2 ? -1 : 1);
+ }
+
+ /* Shortcut check for equality before invoking the parsing routines. */
+ if (result == 0 && (ve1 - v1 != ve2 - v2 || strncasecmp(v1, v2, ve1 - v1) != 0)) {
+ /* Loop over different components (the parts separated by dots).
+ * If any component differs, we have the basis for an inequality. */
+ while(result == 0 && (v1 < ve1 || v2 < ve2)) {
+ int block_v1 = 0;
+ int block_v2 = 0;
+ version_component vc1 = {0, 0, 0};
+ version_component vc2 = {0, 0, 0};
+ if (v1 < ve1 && *v1 != '+') {
+ v1 = get_component(v1, &vc1);
+ } else {
+ block_v1 = 1;
+ }
+ if (v2 < ve2 && *v2 != '+') {
+ v2 = get_component(v2, &vc2);
+ } else {
+ block_v2 = 1;
+ }
+ if (block_v1 && block_v2) {
+ if (v1 < ve1)
+ v1++;
+ if (v2 < ve2)
+ v2++;
+ } else if (vc1.n != vc2.n) {
+ result = (vc1.n < vc2.n ? -1 : 1);
+ } else if (vc1.a != vc2.a) {
+ result = (vc1.a < vc2.a ? -1 : 1);
+ } else if (vc1.pl != vc2.pl) {
+ result = (vc1.pl < vc2.pl ? -1 : 1);
+ }
+ }
+ }
+
+ /* Compare FreeBSD revision numbers. */
+ if (result == 0 && r1 != r2) {
+ result = (r1 < r2 ? -1 : 1);
+ }
+ return result;
+}
diff --git a/usr.sbin/pkg_install/updating/Makefile b/usr.sbin/pkg_install/updating/Makefile
index f5b7525..b0d3689 100644
--- a/usr.sbin/pkg_install/updating/Makefile
+++ b/usr.sbin/pkg_install/updating/Makefile
@@ -3,6 +3,11 @@
PROG= pkg_updating
SRCS= main.c
+CFLAGS+= -I${.CURDIR}/../lib
+
WFORMAT?= 1
+DPADD= ${LIBINSTALL} ${LIBFETCH} ${LIBMD}
+LDADD= ${LIBINSTALL} -lfetch -lmd
+
.include <bsd.prog.mk>
diff --git a/usr.sbin/pkg_install/updating/main.c b/usr.sbin/pkg_install/updating/main.c
index 993ccd5..0ab2ec0 100644
--- a/usr.sbin/pkg_install/updating/main.c
+++ b/usr.sbin/pkg_install/updating/main.c
@@ -19,7 +19,7 @@ __FBSDID("$FreeBSD$");
#include <sysexits.h>
#include <getopt.h>
-#include <pkg.h>
+#include "lib.h"
#include "pathnames.h"
typedef struct installedport {
@@ -87,8 +87,6 @@ main(int argc, char *argv[])
DIR *dir;
FILE *fd;
- pkg_wrap(PKG_INSTALL_VERSION, argv);
-
while ((ch = getopt_long(argc, argv, opts, longopts, NULL)) != -1) {
switch (ch) {
case 'd':
diff --git a/usr.sbin/pkg_install/version/Makefile b/usr.sbin/pkg_install/version/Makefile
index fb079e3..3e1d7a5 100644
--- a/usr.sbin/pkg_install/version/Makefile
+++ b/usr.sbin/pkg_install/version/Makefile
@@ -3,8 +3,13 @@
PROG= pkg_version
SRCS= main.c perform.c
+CFLAGS+= -I${.CURDIR}/../lib
+
WFORMAT?= 1
+DPADD= ${LIBINSTALL} ${LIBFETCH} ${LIBMD}
+LDADD= ${LIBINSTALL} -lfetch -lmd
+
test:
sh ${.CURDIR}/test-pkg_version.sh
diff --git a/usr.sbin/pkg_install/version/main.c b/usr.sbin/pkg_install/version/main.c
index 4238497..cad8583 100644
--- a/usr.sbin/pkg_install/version/main.c
+++ b/usr.sbin/pkg_install/version/main.c
@@ -25,7 +25,7 @@ __FBSDID("$FreeBSD$");
#include <getopt.h>
#include <err.h>
-#include <pkg.h>
+#include "lib.h"
#include "version.h"
char *LimitChars = NULL;
@@ -58,8 +58,6 @@ main(int argc, char **argv)
{
int ch, cmp = 0;
- pkg_wrap(PKG_INSTALL_VERSION, argv);
-
if (argc == 4 && !strcmp(argv[1], "-t")) {
cmp = version_cmp(argv[2], argv[3]);
printf(cmp > 0 ? ">\n" : (cmp < 0 ? "<\n" : "=\n"));
diff --git a/usr.sbin/pkg_install/version/perform.c b/usr.sbin/pkg_install/version/perform.c
index 79575a3..dc85696 100644
--- a/usr.sbin/pkg_install/version/perform.c
+++ b/usr.sbin/pkg_install/version/perform.c
@@ -21,7 +21,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include <pkg.h>
+#include "lib.h"
#include "version.h"
#include <err.h>
#include <fetch.h>
OpenPOWER on IntegriCloud