summaryrefslogtreecommitdiffstats
path: root/usr.sbin
diff options
context:
space:
mode:
authormarkm <markm@FreeBSD.org>2002-06-24 16:03:24 +0000
committermarkm <markm@FreeBSD.org>2002-06-24 16:03:24 +0000
commit8f058b4f92a8cd167524bace0f2b9f989a6fed17 (patch)
tree032be2ec1e27bc433f682c593ac36e767015fb2c /usr.sbin
parente102a9b6dd829c7b39358e1bed4ae6be3a6758d7 (diff)
downloadFreeBSD-src-8f058b4f92a8cd167524bace0f2b9f989a6fed17.zip
FreeBSD-src-8f058b4f92a8cd167524bace0f2b9f989a6fed17.tar.gz
C replacement for the Perl5 code.
Submitted by: reg
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/pkg_install/lib/lib.h2
-rw-r--r--usr.sbin/pkg_install/lib/version.c139
-rw-r--r--usr.sbin/pkg_install/version/Makefile16
-rw-r--r--usr.sbin/pkg_install/version/main.c89
-rw-r--r--usr.sbin/pkg_install/version/perform.c281
-rw-r--r--usr.sbin/pkg_install/version/pkg_version.154
-rwxr-xr-xusr.sbin/pkg_install/version/pkg_version.pl623
-rwxr-xr-xusr.sbin/pkg_install/version/test-pkg_version.sh2
-rw-r--r--usr.sbin/pkg_install/version/version.h44
9 files changed, 570 insertions, 680 deletions
diff --git a/usr.sbin/pkg_install/lib/lib.h b/usr.sbin/pkg_install/lib/lib.h
index 5a11712..6a01fac 100644
--- a/usr.sbin/pkg_install/lib/lib.h
+++ b/usr.sbin/pkg_install/lib/lib.h
@@ -203,6 +203,8 @@ int requiredby(const char *, struct reqr_by_head **, Boolean, Boolean);
/* Version */
int verscmp(Package *, int, int);
+const char *version_of(const char *, int *, int *);
+int version_cmp(const char *, const char *);
/* Externs */
extern Boolean Verbose;
diff --git a/usr.sbin/pkg_install/lib/version.c b/usr.sbin/pkg_install/lib/version.c
index dca95cc..8241961 100644
--- a/usr.sbin/pkg_install/lib/version.c
+++ b/usr.sbin/pkg_install/lib/version.c
@@ -14,6 +14,15 @@
* 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.
*
@@ -23,13 +32,6 @@
* value insted of the hash of an object this links points to.
*
*/
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include "lib.h"
-#include <err.h>
-
int
verscmp(Package *pkg, int major, int minor)
{
@@ -44,3 +46,126 @@ verscmp(Package *pkg, int major, int minor)
return rval;
}
+
+/*
+ * version_of(pkgname, epoch, revision) returns a pointer to the version
+ * portion of a package name and the two special components.
+ *
+ * Jeremy D. Lea.
+ */
+const char *
+version_of(const char *pkgname, int *epoch, int *revision)
+{
+ char *ch;
+
+ if (pkgname == NULL)
+ errx(2, "%s: Passed NULL pkgname.", __func__);
+ if (epoch != NULL) {
+ if ((ch = strrchr(pkgname, ',')) == NULL)
+ *epoch = 0;
+ else
+ *epoch = atoi(&ch[1]);
+ }
+ if (revision != NULL) {
+ if ((ch = strrchr(pkgname, '_')) == NULL)
+ *revision = 0;
+ else
+ *revision = atoi(&ch[1]);
+ }
+ /* Cheat if we are just passed a version, not a valid package name */
+ if ((ch = strrchr(pkgname, '-')) == NULL)
+ return pkgname;
+ else
+ return &ch[1];
+}
+
+/*
+ * 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
+ * comparision of the basenames is done.
+ *
+ * The port verison is defined by:
+ * ${PORTVERSION}[_${PORTREVISION}][,${PORTEPOCH}]
+ * ${PORTEPOCH} supercedes ${PORTVERSION} supercedes ${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, seperated by a period, including letters.
+ *
+ * The tests below allow for significantly more latitude in the version
+ * numbers than is allowed in the guidelines. No point in wasting user's
+ * time enforcing them here. That's what flamewars are for.
+ *
+ * Jeremy D. Lea.
+ */
+int
+version_cmp(const char *pkg1, const char *pkg2)
+{
+ const char *c1, *c2, *v1, *v2;
+ char *t1, *t2;
+ int e1, e2, r1, r2, n1, n2;
+
+ v1 = version_of(pkg1, &e1, &r1);
+ v2 = version_of(pkg2, &e2, &r2);
+ /* Minor optimisation. */
+ if (strcmp(v1, v2) == 0)
+ return 0;
+ /* First compare epoch. */
+ if (e1 != e2)
+ return (e1 < e2 ? -1 : 1);
+ else {
+ /*
+ * We walk down the versions, trying to convert to numbers.
+ * We terminate when we reach an underscore, a comma or the
+ * string terminator, thanks to a nasty trick with strchr().
+ * strtol() conveniently gobbles up the chars it converts.
+ */
+ c1 = strchr("_,", v1[0]);
+ c2 = strchr("_,", v2[0]);
+ while (c1 == NULL && c2 == NULL) {
+ n1 = strtol(v1, &t1, 10);
+ n2 = strtol(v2, &t2, 10);
+ if (n1 != n2)
+ return (n1 < n2 ? -1 : 1);
+ /*
+ * The numbers are equal, check for letters. Assume they're
+ * letters purely because strtol() didn't chomp them.
+ */
+ c1 = strchr("_,.", t1[0]);
+ c2 = strchr("_,.", t2[0]);
+ if (c1 == NULL && c2 == NULL) {
+ /* Both have letters. Compare them. */
+ if (t1[0] != t2[0])
+ return (t1[0] < t2[0] ? -1 : 1);
+ /* Boring. The letters are equal. Carry on. */
+ v1 = &t1[1], v2 = &t2[1];
+ } else if (c1 == NULL) {
+ /*
+ * Letters are strange. After a number, a letter counts
+ * as greater, but after a period it's less.
+ */
+ return (isdigit(v1[0]) ? 1 : -1);
+ } else if (c2 == NULL) {
+ return (isdigit(v2[0]) ? -1 : 1);
+ } else {
+ /* Neither were letters. Advance over the period. */
+ v1 = (t1[0] == '.' ? &t1[1] : t1);
+ v2 = (t2[0] == '.' ? &t2[1] : t2);
+ }
+ c1 = strchr("_,", v1[0]);
+ c2 = strchr("_,", v2[0]);
+ }
+ /* If we got here, check if one version has something left. */
+ if (c1 == NULL)
+ return (isdigit(v1[0]) ? 1 : -1);
+ if (c2 == NULL)
+ return (isdigit(v2[0]) ? -1 : 1);
+ /* We've run out of version. Try the revision... */
+ if (r1 != r2)
+ return (r1 < r2 ? -1 : 1);
+ else
+ return 0;
+ }
+}
diff --git a/usr.sbin/pkg_install/version/Makefile b/usr.sbin/pkg_install/version/Makefile
index cba73fb..f18bedf 100644
--- a/usr.sbin/pkg_install/version/Makefile
+++ b/usr.sbin/pkg_install/version/Makefile
@@ -1,7 +1,19 @@
# $FreeBSD$
-SCRIPTS= pkg_version.pl
-MAN= pkg_version.1
+PROG= pkg_version
+SRCS= main.c perform.c
+
+CFLAGS+= ${DEBUG} -I${.CURDIR}/../lib
+
+WARNS?= 2
+
+DPADD= ${LIBINSTALL} ${LIBFETCH} ${LIBMD}
+LDADD= ${LIBINSTALL} -lfetch -lmd
+
+.if !defined(NOCRYPT) && !defined(NOSECURE) && !defined(NO_OPENSSL)
+DPADD+= ${LIBSSL} ${LIBCRYPTO}
+LDADD+= -lssl -lcrypto
+.endif
test:
./test-pkg_version.sh
diff --git a/usr.sbin/pkg_install/version/main.c b/usr.sbin/pkg_install/version/main.c
new file mode 100644
index 0000000..cbc6a9e
--- /dev/null
+++ b/usr.sbin/pkg_install/version/main.c
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ *
+ * Jeremy D. Lea.
+ * 11 May 2002
+ *
+ * This is the version module. Based on pkg_version.pl by Bruce A. Mah.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "lib.h"
+#include "version.h"
+#include <err.h>
+
+static char Options[] = "dhl:L:s:tv";
+
+char *LimitChars = NULL;
+char *PreventChars = NULL;
+char *MatchName = NULL;
+
+static void usage __P((void));
+
+int
+main(int argc, char **argv)
+{
+ int ch, cmp = 0;
+
+ if (argc == 4 && !strcmp(argv[1], "-t")) {
+ cmp = version_cmp(argv[2], argv[3]);
+ printf(cmp > 0 ? ">\n" : (cmp < 0 ? "<\n" : "=\n"));
+ exit(0);
+ }
+ else while ((ch = getopt(argc, argv, Options)) != -1) {
+ switch(ch) {
+ case 'v':
+ Verbose = TRUE;
+ break;
+
+ case 'l':
+ LimitChars = optarg;
+ break;
+
+ case 'L':
+ PreventChars = optarg;
+ break;
+
+ case 's':
+ MatchName = optarg;
+ break;
+
+ case 't':
+ errx(2, "Invalid -t usage.");
+ break;
+
+ case 'h':
+ case '?':
+ default:
+ usage();
+ break;
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ return pkg_perform(argv);
+}
+
+static void
+usage()
+{
+ fprintf(stderr, "%s\n%s\n",
+ "usage: pkg_version [-hv] [-l limchar] [-L limchar] [-s string] index",
+ " pkg_version -t v1 v2");
+ exit(1);
+}
diff --git a/usr.sbin/pkg_install/version/perform.c b/usr.sbin/pkg_install/version/perform.c
new file mode 100644
index 0000000..fd340ff
--- /dev/null
+++ b/usr.sbin/pkg_install/version/perform.c
@@ -0,0 +1,281 @@
+/*
+ * 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.
+ *
+ * Jeremy D. Lea.
+ * 11 May 2002
+ *
+ * This is the version module. Based on pkg_version.pl by Bruce A. Mah.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "lib.h"
+#include "version.h"
+#include <err.h>
+#include <fetch.h>
+#include <signal.h>
+
+FILE *IndexFile;
+struct index_head Index = SLIST_HEAD_INITIALIZER(Index);
+
+static int pkg_do(char *);
+static void show_version(const char *, const char *, const char *);
+
+/*
+ * This is the traditional pkg_perform, except that the argument is _not_
+ * a list of packages. It is the index file from the command line.
+ *
+ * We loop over the installed packages, matching them with the -s flag
+ * if needed and calling pkg_do(). Before hand we set up a few things,
+ * and after we tear them down...
+ */
+int
+pkg_perform(char **indexarg)
+{
+ char tmp[PATH_MAX], **pkgs;
+ struct index_entry *ie;
+ int i, err_cnt = 0;
+
+ /*
+ * Try to find and open the INDEX. We only check IndexFile != NULL
+ * later, if we actually need the INDEX.
+ */
+ if (*indexarg == NULL)
+ snprintf(tmp, PATH_MAX, "%s/INDEX", PORTS_DIR);
+ else
+ strlcpy(tmp, *indexarg, PATH_MAX);
+ if (isURL(tmp))
+ IndexFile = fetchGetURL(tmp, "");
+ else
+ IndexFile = fopen(tmp, "r");
+
+ /* Get a list of all the installed packages */
+ pkgs = matchinstalled(MATCH_ALL, NULL, &err_cnt);
+ if (err_cnt != 0)
+ errx(2, "Unable to find package database directory!");
+ i = -1;
+ while (pkgs[++i] != NULL) {
+ if (MatchName == NULL || strstr(pkgs[i], MatchName))
+ err_cnt += pkg_do(pkgs[i]);
+ }
+
+ /* If we opened the INDEX in pkg_do(), clean up. */
+ while (!SLIST_EMPTY(&Index)) {
+ ie = SLIST_FIRST(&Index);
+ SLIST_REMOVE_HEAD(&Index, next);
+ free(ie);
+ }
+ if (IndexFile != NULL)
+ fclose(IndexFile);
+
+ return err_cnt;
+}
+
+/*
+ * Traditional pkg_do(). We take the package name we are passed and
+ * first slurp in the CONTENTS file, getting name and origin, then
+ * we look for it's corresponding Makefile. If that fails we pull in
+ * the INDEX, and check there.
+ */
+static int
+pkg_do(char *pkg)
+{
+ char *ch, tmp[PATH_MAX], tmp2[PATH_MAX], *latest = NULL;
+ Package plist;
+ struct index_entry *ie;
+ FILE *fp;
+ size_t len;
+
+ /* Suck in the contents list. */
+ plist.head = plist.tail = NULL;
+ plist.name = plist.origin = NULL;
+ snprintf(tmp, PATH_MAX, "%s/%s/%s", LOG_DIR, pkg, CONTENTS_FNAME);
+ fp = fopen(tmp, "r");
+ if (!fp) {
+ warnx("unable to open %s file", CONTENTS_FNAME);
+ return 1;
+ }
+ read_plist(&plist, fp);
+ fclose(fp);
+
+ /*
+ * First we check if the installed package has an origin, and try
+ * looking for it's Makefile. If we find the Makefile we get the
+ * latest version from there. If we fail, we start looking in the
+ * INDEX, first matching the origin and then the package name.
+ */
+ if (plist.origin != NULL) {
+ snprintf(tmp, PATH_MAX, "%s/%s", PORTS_DIR, plist.origin);
+ if (isdir(tmp) && chdir(tmp) != FAIL && isfile("Makefile")) {
+ if ((latest = vpipe("make -V PKGNAME", tmp)) == NULL)
+ warnx("Failed to get PKGNAME from %s/Makefile!", tmp);
+ else
+ show_version(plist.name, latest, "port");
+ }
+ }
+ if (latest == NULL) {
+ /* We only pull in the INDEX once, if needed. */
+ if (SLIST_EMPTY(&Index)) {
+ if (!IndexFile)
+ errx(2, "Unable to open INDEX in %s.", __func__);
+ while ((ch = fgetln(IndexFile, &len)) != NULL) {
+ /*
+ * Don't use strlcpy() because fgetln() doesn't
+ * return a valid C string.
+ */
+ strncpy(tmp, ch, MIN(len, PATH_MAX));
+ tmp[PATH_MAX-1] = '\0';
+ /* The INDEX has pkgname|portdir|... */
+ if ((ch = strchr(tmp, '|')) != NULL)
+ ch[0] = '\0';
+ if (ch != NULL && (ch = strchr(&ch[1], '|')) != NULL)
+ ch[0] = '\0';
+ /* Look backwards for the last two dirs = origin */
+ while (ch != NULL && *--ch != '/')
+ if (ch[0] == '\0')
+ ch = NULL;
+ while (ch != NULL && *--ch != '/')
+ if (ch[0] == '\0')
+ ch = NULL;
+ if (ch == NULL)
+ errx(2, "The INDEX does not appear to be valid!");
+ if ((ie = malloc(sizeof(struct index_entry))) == NULL)
+ errx(2, "Unable to allocate memory in %s.", __func__);
+ strlcpy(ie->name, tmp, PATH_MAX);
+ strlcpy(ie->origin, &ch[1], PATH_MAX);
+ /* Who really cares if we reverse the index... */
+ SLIST_INSERT_HEAD(&Index, ie, next);
+ }
+ }
+ /* Now that we've slurped in the INDEX... */
+ SLIST_FOREACH(ie, &Index, next) {
+ if (plist.origin != NULL) {
+ if (strcmp(plist.origin, ie->origin) == 0)
+ latest = strdup(ie->name);
+ } else {
+ strlcpy(tmp, ie->name, PATH_MAX);
+ strlcpy(tmp2, plist.name, PATH_MAX);
+ /* Chop off the versions and compare. */
+ if ((ch = strrchr(tmp, '-')) == NULL)
+ errx(2, "The INDEX does not appear to be valid!");
+ ch[0] = '\0';
+ if ((ch = strrchr(tmp2, '-')) == NULL)
+ warnx("%s is not a valid package!", plist.name);
+ else
+ ch[0] = '\0';
+ if (strcmp(tmp2, tmp) == 0) {
+ if (latest != NULL) {
+ /* Multiple matches */
+ snprintf(tmp, PATH_MAX, "%s|%s", latest, ie->name);
+ free(latest);
+ latest = strdup(tmp);
+ } else
+ latest = strdup(ie->name);
+ }
+ }
+ }
+ if (latest == NULL)
+ show_version(plist.name, NULL, plist.origin);
+ else
+ show_version(plist.name, latest, "index");
+ }
+ if (latest != NULL)
+ free(latest);
+ free_plist(&plist);
+ return 0;
+}
+
+#define OUTPUT(c) ((PreventChars != NULL && !strchr(PreventChars, (c))) || \
+ (LimitChars != NULL && strchr(LimitChars, (c))) || \
+ (PreventChars == NULL && LimitChars == NULL))
+
+/*
+ * Do the work of comparing and outputing. Ugly, but well that's what
+ * You get when you try to match perl output in C ;-).
+ */
+void
+show_version(const char *installed, const char *latest, const char *source)
+{
+ char *ch, tmp[PATH_MAX];
+ const char *ver;
+ int cmp = 0;
+
+ if (!installed || strlen(installed) == 0)
+ return;
+ strlcpy(tmp, installed, PATH_MAX);
+ if (!Verbose) {
+ if ((ch = strrchr(tmp, '-')) != NULL)
+ ch[0] = '\0';
+ }
+ if (latest == NULL) {
+ if (source == NULL && OUTPUT('!')) {
+ printf("%-34s !", tmp);
+ if (Verbose)
+ printf(" Comparison failed");
+ printf("\n");
+ } else if (source != NULL && OUTPUT('?')) {
+ printf("%-34s ?", tmp);
+ if (Verbose)
+ printf(" orphaned: %s", source);
+ printf("\n");
+ }
+ } else if (strchr(latest,'|') != NULL) {
+ if (OUTPUT('*')) {
+ printf("%-34s *", tmp);
+ if (Verbose) {
+ strlcpy(tmp, latest, PATH_MAX);
+ ch = strchr(tmp, '|');
+ ch[0] = '\0';
+
+ ver = version_of(tmp, NULL, NULL);
+ printf(" multiple versions (index has %s", ver);
+ do {
+ ver = version_of(&ch[1], NULL, NULL);
+ if ((ch = strchr(&ch[1], '|')) != NULL)
+ ch[0] = '\0';
+ printf(", %s", ver);
+ } while (ch != NULL);
+ printf(")");
+ }
+ printf("\n");
+ }
+ } else {
+ cmp = version_cmp(installed, latest);
+ ver = version_of(latest, NULL, NULL);
+ if (cmp < 0 && OUTPUT('<')) {
+ printf("%-34s <", tmp);
+ if (Verbose)
+ printf(" needs updating (%s has %s)", source, ver);
+ printf("\n");
+ } else if (cmp == 0 && OUTPUT('=')) {
+ printf("%-34s =", tmp);
+ if (Verbose)
+ printf(" up-to-date with %s", source);
+ printf("\n");
+ } else if (cmp > 0 && OUTPUT('>')) {
+ printf("%-34s >", tmp);
+ if (Verbose)
+ printf(" succeeds %s (%s has %s)", source, source, ver);
+ printf("\n");
+ }
+ }
+}
+
+void
+cleanup(int sig)
+{
+ if (sig)
+ exit(1);
+}
diff --git a/usr.sbin/pkg_install/version/pkg_version.1 b/usr.sbin/pkg_install/version/pkg_version.1
index da9a703..e252210 100644
--- a/usr.sbin/pkg_install/version/pkg_version.1
+++ b/usr.sbin/pkg_install/version/pkg_version.1
@@ -32,7 +32,7 @@
.Nd summarize installed versions of packages
.Sh SYNOPSIS
.Nm
-.Op Fl cdhv
+.Op Fl hv
.Op Fl l Ar limchar
.Op Fl L Ar limchar
.Op Fl s Ar string
@@ -110,23 +110,6 @@ The
.Nm
utility supports several command-line arguments:
.Bl -tag -width indent
-.It Fl c
-Enable commands output. Commands output includes the commands you should
-type to update your installed packages to the latest versions in the ports
-system.
-This feature does
-.Bf Em
-not
-.Ef
-constitute an automated packages updating system.
-The output of this command
-.Bf Em
-must
-.Ef
-be edited, in order to avoid destroying dependencies between installed
-packages.
-.It Fl d
-Enable debugging output.
.It Fl h
Print help message.
.It Fl l
@@ -201,42 +184,19 @@ the version numbers in the on-line ports collection:
.Pp
.Dl % pkg_version ftp://ftp.FreeBSD.org/pub/FreeBSD/branches/-current/ports/INDEX
.Pp
-The command below generates a file of commands to run to update the installed
-files.
-These commands must
-.Bf Em
-not
-.Ef
-be run without suitable editing.
-They should be treated as suggestions, and may need to be reordered
-to account for dependencies between installed packages, or may need to
-be disregarded if multiple versions of an installed package can coexist.
-Blindly running the output of this command may leave a system in an
-unusable state.
-.Pp
-.Dl % pkg_version -c > do_update
-.Pp
The following command compares two package version strings:
.Pp
.Dl % pkg_version -t 1.5 1.5.1
.Sh AUTHORS
-.An Bruce A. Mah Aq bmah@FreeBSD.org
+The
+.Nm
+utility was written by
+.An Jeremy D. Lea Aq reg@FreeBSD.org ,
+partially based on a Perl script written by
+.An Bruce A. Mah Aq bmah@FreeBSD.org .
.Sh CONTRIBUTORS
.An Nik Clayton Aq nik@FreeBSD.org ,
.An Dominic Mitchell Aq dom@palmerharvey.co.uk ,
.An Mark Ovens Aq marko@FreeBSD.org ,
.An Doug Barton Aq DougB@gorean.org ,
.An Akinori MUSHA Aq knu@FreeBSD.org
-.Sh BUGS
-The commands output feature is
-.Bf Em
-not
-.Ef
-an automated ports/packages updating system.
-It does not even attempt to handle dependencies between installed
-packages correctly, and can produce incorrect results if multiple
-versions of a package can coexist on a system.
-.Pp
-Commands output assumes you install new software using the ports system,
-rather than using
-.Xr pkg_add 1 .
diff --git a/usr.sbin/pkg_install/version/pkg_version.pl b/usr.sbin/pkg_install/version/pkg_version.pl
deleted file mode 100755
index 86c6547..0000000
--- a/usr.sbin/pkg_install/version/pkg_version.pl
+++ /dev/null
@@ -1,623 +0,0 @@
-#! /usr/bin/perl
-#
-# Copyright 1998 Bruce A. Mah
-#
-# All rights reserved.
-#
-# 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.
-#
-# THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE DEVELOPERS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-# pkg_version.pl
-#
-# A package version-checking utility for FreeBSD.
-#
-# $FreeBSD$
-#
-
-use Cwd;
-use Getopt::Std;
-
-#
-# Configuration global variables
-#
-$AllCurrentPackagesCommand = '/usr/sbin/pkg_info -aI';
-$SelectedCurrentPackagesCommand = '/usr/sbin/pkg_info -I';
-$CatProgram = "cat ";
-$FetchProgram = "fetch -o - ";
-$OriginCommand = '/usr/sbin/pkg_info -qo';
-$GetPkgNameCommand = 'make -V PKGNAME';
-
-#$IndexFile = "ftp://ftp.freebsd.org/pub/FreeBSD/branches/-current/ports/INDEX";
-$PortsDirectory = $ENV{PORTSDIR} || '/usr/ports';
-$IndexFile = "$PortsDirectory/INDEX";
-$ShowCommandsFlag = 0;
-$DebugFlag = 0;
-$VerboseFlag = 0;
-$CommentChar = "#";
-$LimitFlag = "";
-$PreventFlag = "";
-
-#
-# CompareNumbers
-#
-# Try to figure out the relationship between two program version numbers.
-# Detecting equality is easy, but determining order is a little difficult.
-# This function returns -1, 0, or 1, in the same manner as <=> or cmp.
-#
-sub CompareNumbers {
- my ($v1, $v2) = @_;
-
- # Short-cut in case of equality
- if ($v1 eq $v2) {
- return 0;
- }
-
- # Loop over different components (the parts separated by dots).
- # If any component differs, we have the basis for an inequality.
- my @s1 = split(/\./, $v1);
- my @s2 = split(/\./, $v2);
- my ($c1, $c2);
- do {
- last unless @s1 || @s2;
- $c1 = shift @s1;
- $c2 = shift @s2;
- } while ($c1 eq $c2);
-
- # Look at the first components of the arrays that are left.
- # These will determine the result of the comparison.
- # Note that if either version doesn't have any components left,
- # it's implicitly treated as a "0".
-
- # Our next set of checks looks to see if either component has a
- # leading letter (there should be at most one leading letter per
- # component, so that "4.0b1" is allowed, but "4.0beta1" is not).
- if ($c1 =~ /^\D/) {
- if ($c2 =~ /^\D/) {
-
- # Both have a leading letter, so do an alpha comparison
- # on the letters. This isn't ideal, since we're assuming
- # that "1.0.b4" > "1.0.a2". But it's about the best we can do,
- # without encoding some explicit policy.
- my ($letter1, $letter2);
- $letter1 = substr($c1, 0, 1);
- $letter2 = substr($c2, 0, 1);
-
- if ($letter1 ne $letter2) {
- return $letter1 cmp $letter2;
- }
- else {
- # The letters matched equally. Delete the leading
- # letters and invoke ourselves on the remainining
- # characters, which according to the Porters Handbook
- # must be digits, so for example, "1.0.a9" < "1.0.a10".
- substr($c1, 0, 1) = "";
- substr($c2, 0, 1) = "";
- return &CompareNumbers($c1, $c2);
- }
-
- }
- else {
- # $c1 begins with a letter, but $c2 doesn't. Let $c2
- # win the comparison, so that "1.0.b1" < "1.0.1".
- return -1;
- }
- }
- else {
- if ($c2 =~ /^\D/) {
- # $c2 begins with a letter but $c1 doesn't. Let $c1
- # win the comparison, as above.
- return 1;
- }
- else {
- # Neither component begins with a leading letter.
- # See if either component has no characters left. If so,
- # let the other component win.
- if ($c1 eq "") {
- return -1;
- }
- if ($c2 eq "") {
- return 1;
- }
-
- # Check for numeric inequality. We assume here that (for example)
- # "3.09" < "3.10", and that we aren't going to be asked to
- # decide between "3.010" and "3.10".
- if ($c1 != $c2) {
- return $c1 <=> $c2;
- }
-
- # String comparison, given numeric equality. This
- # handles comparisons of the form "3.4j" < "3.4k". This form
- # technically isn't allowed by the Porter's Handbook, but a
- # number of ports in the FreeBSD Ports Collection as of this
- # writing use it (graphics/jpeg and graphics/xv). So we need
- # to support it.
- #
- # What we actually do is to strip off the leading digits and
- # invoke ourselves on the remainder. This allows us to handle
- # comparisons of the form "1.1p1" < "1.1p2". Again, not
- # technically allowed by the Porters Handbook, but lots of ports
- # use it.
- else {
- $c1 =~ s/\d+//;
- $c2 =~ s/\d+//;
- if ($c1 eq $c2) {
- return 0;
- }
- elsif ($c1 eq "") {
- return -1;
- }
- elsif ($c2 eq "") {
- return 1;
- }
- else {
- return &CompareNumbers($c1, $c2);
- }
- }
- }
- }
-}
-
-#
-# CompareVersions
-#
-# Try to figure out the relationship between two program "full
-# versions", which is defined as the
-# ${PORTVERSION}[_${PORTREVISION}][,${PORTEPOCH}]
-# part of a package's name.
-#
-# Key points: ${PORTEPOCH} supercedes ${PORTVERSION}
-# supercedes ${PORTREVISION}. See the commit log for revision
-# 1.349 of ports/Mk/bsd.port.mk for more information.
-#
-sub CompareVersions {
- local($fv1, $fv2, $v1, $v2, $r1, $r2, $e1, $e2, $rc);
-
- $fv1 = $_[0];
- $fv2 = $_[1];
-
- # Shortcut check for equality before invoking the parsing
- # routines.
- if ($fv1 eq $fv2) {
- return 0;
- }
- else {
- ($v1, $r1, $e1) = &GetVersionComponents($fv1);
- ($v2, $r2, $e2) = &GetVersionComponents($fv2);
-
- # Port revision and port epoch numbers default to zero if not
- # specified.
- if ($r1 eq "") {
- $r1 = "0";
- }
- if ($r2 eq "") {
- $r2 = "0";
- }
- if ($e1 eq "") {
- $e1 = "0";
- }
- if ($e2 eq "") {
- $e2 = "0";
- }
-
- # Check epoch, port version, and port revision, in that
- # order.
- $rc = &CompareNumbers($e1, $e2);
- if ($rc == 0) {
- $rc = &CompareNumbers($v1, $v2);
- if ($rc == 0) {
- $rc = &CompareNumbers($r1, $r2);
- }
- }
-
- return $rc;
- }
-}
-
-#
-# GetVersionComponents
-#
-# Parse out the version number, revision number, and epoch number
-# of a port's version string and return them as a three-element array.
-#
-# Syntax is: ${PORTVERSION}[_${PORTREVISION}][,${PORTEPOCH}]
-#
-sub GetVersionComponents {
- local ($fullversion, $version, $revision, $epoch);
-
- $fullversion = $_[0];
-
- $fullversion =~ /([^_,]+)/;
- $version = $1;
-
- if ($fullversion =~ /_([^_,]+)/) {
- $revision = $1;
- }
-
- if ($fullversion =~ /,([^_,]+)/) {
- $epoch = $1;
- }
-
- return($version, $revision, $epoch);
-}
-
-#
-# GetNameAndVersion
-#
-# Get the name and version number of a package. Returns a two element
-# array, first element is name, second element is full version string.,
-#
-sub GetNameAndVersion {
- local($fullname, $name, $fullversion);
- $fullname = $_[0];
-
- # If no hyphens then no version numbers
- return ($fullname, "", "", "", "") if $fullname !~ /-/;
-
- # Match (and group) everything after hyphen(s). Because the
- # regexp is 'greedy', the first .* will try and match everything up
- # to (but not including) the last hyphen
- $fullname =~ /(.+)-(.+)/;
- $name = $1;
- $fullversion = $2;
-
- return ($name, $fullversion);
-}
-
-#
-# PrintHelp
-#
-# Print usage information
-#
-sub PrintHelp {
- print <<"EOF"
-Usage: pkg_version [-c] [-d] [-h] [-l limchar] [-L limchar] [-s string]
- [-v] [index]
- pkg_version [-d debug] -t v1 v2
--c Show commands to update installed packages
--d Enable debugging output
--h Help (this message)
--l limchar Limit output to status flags that match
--L limchar Limit output to status flags that DON\'T match
--s string Limit output to packages matching a string
--v Verbose output
-index URL or filename of index file
- (Default is $IndexFile)
-
--t v1 v2 Test two version strings
-EOF
-}
-
-#
-# Parse command-line arguments, deal with them
-#
-if (!getopts('cdhl:L:s:tv') || ($opt_h)) {
- &PrintHelp();
- exit;
-}
-if ($opt_c) {
- $ShowCommandsFlag = $opt_c;
- $LimitFlag = "<?"; # note that if the user specifies -l, we
- # deal with this *after* setting a default
- # for $LimitFlag
-}
-if ($opt_d) {
- $DebugFlag = $opt_d;
-}
-if ($opt_l) {
- $LimitFlag = $opt_l;
-}
-if ($opt_L) {
- $PreventFlag = $opt_L;
-}
-if ($opt_t) {
- $TestFlag = 1;
-}
-if ($opt_s) {
- $StringFlag = $opt_s;
-}
-if ($opt_v) {
- $VerboseFlag = 1;
-}
-if ($#ARGV >= 0) {
- if ($TestFlag) {
- ($test1, $test2) = @ARGV;
- }
- else {
- $IndexFile = $ARGV[0];
- }
-}
-
-# Handle test flag now
-if ($TestFlag) {
- my $cmp = CompareVersions($test1, $test2);
- if ($cmp < 0) {
- print "<\n";
- }
- elsif ($cmp == 0) {
- print "=\n";
- }
- else {
- print ">\n";
- }
- exit(0);
-}
-
-# Determine what command to use to retrieve the index file.
-if ($IndexFile =~ m-^((http|ftp)://|file:/)-) {
- $IndexPackagesCommand = $FetchProgram . $IndexFile;
-}
-else {
- $IndexPackagesCommand = $CatProgram . $IndexFile;
-}
-
-#
-# Get the current list of installed packages
-#
-if ($StringFlag) {
- if ($DebugFlag) {
- print STDERR "$SelectedCurrentPackagesCommand *$StringFlag*\n";
- }
- open CURRENT, "$SelectedCurrentPackagesCommand \\*$StringFlag\\*|";
-} else {
- if ($DebugFlag) {
- print STDERR "$AllCurrentPackagesCommand\n";
- }
- open CURRENT, "$AllCurrentPackagesCommand|";
-}
-while (<CURRENT>) {
- ($packageString, $rest) = split;
-
- ($packageName, $packageFullversion) = &GetNameAndVersion($packageString);
- $currentPackages{$packageString}{'name'} = $packageName;
- $currentPackages{$packageString}{'fullversion'} = $packageFullversion;
-}
-close CURRENT;
-
-#
-# Iterate over installed packages, get origin directory (if it
-# exists) and PORTVERSION
-#
-$dir = cwd();
-foreach $packageString (sort keys %currentPackages) {
-
- open ORIGIN, "$OriginCommand $packageString|";
- $origin = <ORIGIN>;
- close ORIGIN;
-
- # If there is an origin variable for this package, then store it.
- if ($origin ne "") {
- chomp $origin;
-
- # Try to get the version out of the makefile.
- # The chdir needs to be successful or our make -V invocation
- # will fail.
- unless (chdir "$PortsDirectory/$origin" and -r "Makefile") {
- $currentPackages{$packageString}->{orphaned} = $origin;
- next;
- }
-
- open PKGNAME, "$GetPkgNameCommand|";
- $pkgname = <PKGNAME>;
- close PKGNAME;
-
- if ($pkgname ne "") {
- chomp $pkgname;
-
- $pkgname =~ /(.+)-(.+)/;
- $portversion = $2;
-
- $currentPackages{$packageString}{'origin'} = $origin;
- $currentPackages{$packageString}{'portversion'} = $portversion;
- }
- }
-}
-chdir "$dir";
-
-#
-# Slurp in the index file
-#
-if ($DebugFlag) {
- print STDERR "$IndexPackagesCommand\n";
-}
-
-open INDEX, "$IndexPackagesCommand|";
-while (<INDEX>) {
- ($packageString, $packagePath, $rest) = split(/\|/);
-
- ($packageName, $packageFullversion) = &GetNameAndVersion($packageString);
- $indexPackages{$packageName}{'name'} = $packageName;
- $indexPackages{$packageName}{'path'} = $packagePath;
- if (defined $indexPackages{$packageName}{'fullversion'}) {
- $indexPackages{$packageName}{'fullversion'} .= "|" . $packageFullversion;
- }
- else {
- $indexPackages{$packageName}{'fullversion'} = $packageFullversion;
- }
- $indexPackages{$packageName}{'refcount'}++;
-}
-close INDEX;
-
-#
-# If we're doing commands output, cripple the output so that users
-# can't just pipe the output to sh(1) and expect this to work.
-#
-if ($ShowCommandsFlag) {
- print<<EOF
-echo "The commands output of pkg_version cannot be executed without editing."
-echo "You MUST save this output to a file and then edit it, taking into"
-echo "account package dependencies and the fact that some packages cannot"
-echo "or should not be upgraded."
-exit 1
-EOF
-}
-
-#
-# Produce reports
-#
-# Prior versions of pkg_version used commas (",") as delimiters
-# when there were multiple versions of a package installed.
-# The new package version number syntax uses commas as well,
-# so we've used vertical bars ("|") internally, and convert them
-# to commas before we output anything so the reports look the
-# same as they did before.
-#
-foreach $packageString (sort keys %currentPackages) {
- $~ = "STDOUT_VERBOSE" if $VerboseFlag;
- $~ = "STDOUT_COMMANDS" if $ShowCommandsFlag;
-
- $packageNameVer = $packageString;
- $packageName = $currentPackages{$packageString}{'name'};
-
- $currentVersion = $currentPackages{$packageString}{'fullversion'};
-
- if ($currentPackages{$packageString}->{orphaned}) {
-
- next if $ShowCommandsFlag;
- $versionCode = "?";
- $Comment = "orphaned: $currentPackages{$packageString}->{orphaned}";
-
- } elsif (defined $currentPackages{$packageString}{'portversion'}) {
-
- $portVersion = $currentPackages{$packageString}{'portversion'};
-
- $portPath = "$PortsDirectory/$currentPackages{$packageString}{'origin'}";
-
- # Do the comparison
- $rc = &CompareVersions($currentVersion, $portVersion);
-
- if ($rc == 0) {
- $versionCode = "=";
- $Comment = "up-to-date with port";
- }
- elsif ($rc < 0) {
- $versionCode = "<";
- $Comment = "needs updating (port has $portVersion)";
- }
- elsif ($rc > 0) {
- $versionCode = ">";
- $Comment = "succeeds port (port has $portVersion)";
- }
- else {
- $versionCode = "!";
- $Comment = "Comparison failed";
- }
- }
-
- elsif (defined $indexPackages{$packageName}{'fullversion'}) {
-
- $indexVersion = $indexPackages{$packageName}{'fullversion'};
- $indexRefcount = $indexPackages{$packageName}{'refcount'};
-
- $portPath = $indexPackages{$packageName}{'path'};
-
- if ($indexRefcount > 1) {
- $versionCode = "*";
- $Comment = "multiple versions (index has $indexVersion)";
- $Comment =~ s/\|/,/g;
- }
- else {
-
- # Do the comparison
- $rc =
- &CompareVersions($currentVersion, $indexVersion);
-
- if ($rc == 0) {
- $versionCode = "=";
- $Comment = "up-to-date with index";
- }
- elsif ($rc < 0) {
- $versionCode = "<";
- $Comment = "needs updating (index has $indexVersion)"
- }
- elsif ($rc > 0) {
- $versionCode = ">";
- $Comment = "succeeds index (index has $indexVersion)";
- }
- else {
- $versionCode = "!";
- $Comment = "Comparison failed";
- }
- }
- }
- else {
- next if $ShowCommandsFlag;
- $versionCode = "?";
- $Comment = "unknown in index";
- }
-
- # Having figured out what to print, now determine, based on the
- # $LimitFlag and $PreventFlag variables, if we should print or not.
- if ((not $LimitFlag) and (not $PreventFlag)) {
- write;
- } elsif ($PreventFlag) {
- if ($versionCode !~ m/[$PreventFlag]/o) {
- if (not $LimitFlag) {
- write;
- } else {
- write if $versionCode =~ m/[$LimitFlag]/o;
- }
- }
- } else {
- # Must mean that there is a LimitFlag
- write if $versionCode =~ m/[$LimitFlag]/o;
- }
-}
-
-exit 0;
-
-#
-# Formats
-#
-# $CommentChar is in the formats because you can't put a literal '#' in
-# a format specification
-
-# General report (no output flags)
-format STDOUT =
-@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @<
-$packageName, $versionCode
-.
- ;
-
-# Verbose report (-v flag)
-format STDOUT_VERBOSE =
-@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
-$packageNameVer, $versionCode, $Comment
-.
- ;
-
-# Report that includes commands to update program (-c flag)
-format STDOUT_COMMANDS =
-@<
-$CommentChar
-@< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
-$CommentChar, $packageName
-@< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
-$CommentChar, $Comment
-@<
-$CommentChar
-cd @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
-$portPath
-make clean && make && pkg_delete -f @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
- $packageNameVer
-make install clean
-
-.
- ;
diff --git a/usr.sbin/pkg_install/version/test-pkg_version.sh b/usr.sbin/pkg_install/version/test-pkg_version.sh
index 081f559..0651047 100755
--- a/usr.sbin/pkg_install/version/test-pkg_version.sh
+++ b/usr.sbin/pkg_install/version/test-pkg_version.sh
@@ -33,7 +33,7 @@
#
ECHO=echo
-PKG_VERSION=./pkg_version.pl
+PKG_VERSION=./pkg_version
test-pv ( ) { \
setvar v1 $1
diff --git a/usr.sbin/pkg_install/version/version.h b/usr.sbin/pkg_install/version/version.h
new file mode 100644
index 0000000..6ed6511
--- /dev/null
+++ b/usr.sbin/pkg_install/version/version.h
@@ -0,0 +1,44 @@
+/* $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.
+ *
+ * Jeremy D. Lea.
+ * 11 May 2002
+ *
+ * This is the version module. Based on pkg_version.pl by Bruce A. Mah.
+ *
+ */
+
+#ifndef _INST_VERSION_H_INCLUDE
+#define _INST_VERSION_H_INCLUDE
+
+/* 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 we put logging information */
+#define PORTS_DIR (getenv(PORTSDIR) ? getenv(PORTSDIR) : DEF_PORTS_DIR)
+
+struct index_entry {
+ SLIST_ENTRY(index_entry) next;
+ char name[PATH_MAX];
+ char origin[PATH_MAX];
+};
+SLIST_HEAD(index_head, index_entry);
+
+extern char *LimitChars;
+extern char *PreventChars;
+extern char *MatchName;
+
+#endif /* _INST_VERSION_H_INCLUDE */
OpenPOWER on IntegriCloud