From 7923356ae6b0c5daf724f0e5c8844ffec1bb4871 Mon Sep 17 00:00:00 2001 From: eik Date: Tue, 29 Jun 2004 18:54:47 +0000 Subject: - match package version numbers with relational operators - use glob patterns when matching packages by origin - csh-style {...} choices in glob matching - pkg_info: new flag -E (list matching package names only) - pkg_version: new flag -T (test if a given name matches a pattern) - new flag -X (interpret pattern as an extended regular expression) PR: 56961 --- usr.sbin/pkg_install/version/main.c | 22 +++++++-- usr.sbin/pkg_install/version/perform.c | 77 +++++++++++++++++++++++++++++- usr.sbin/pkg_install/version/pkg_version.1 | 34 ++++++++++--- usr.sbin/pkg_install/version/version.h | 3 ++ 4 files changed, 124 insertions(+), 12 deletions(-) (limited to 'usr.sbin/pkg_install/version') diff --git a/usr.sbin/pkg_install/version/main.c b/usr.sbin/pkg_install/version/main.c index cbc6a9e..39ea37f 100644 --- a/usr.sbin/pkg_install/version/main.c +++ b/usr.sbin/pkg_install/version/main.c @@ -25,11 +25,12 @@ __FBSDID("$FreeBSD$"); #include "version.h" #include -static char Options[] = "dhl:L:s:tv"; +static char Options[] = "dhl:L:s:XtTv"; char *LimitChars = NULL; char *PreventChars = NULL; char *MatchName = NULL; +Boolean RegexExtended = FALSE; static void usage __P((void)); @@ -43,6 +44,10 @@ main(int argc, char **argv) printf(cmp > 0 ? ">\n" : (cmp < 0 ? "<\n" : "=\n")); exit(0); } + else if (argc == 4 && !strcmp(argv[1], "-T")) { + cmp = version_match(argv[3], argv[2]); + exit(cmp == 1 ? 0 : 1); + } else while ((ch = getopt(argc, argv, Options)) != -1) { switch(ch) { case 'v': @@ -65,6 +70,14 @@ main(int argc, char **argv) errx(2, "Invalid -t usage."); break; + case 'T': + errx(2, "Invalid -T usage."); + break; + + case 'X': + RegexExtended = TRUE; + break; + case 'h': case '?': default: @@ -82,8 +95,9 @@ main(int argc, char **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"); + fprintf(stderr, "%s\n%s\n%s\n", + "usage: pkg_version [-hv] [-l limchar] [-L limchar] [[-X] -s string] index", + " pkg_version -t v1 v2", + " pkg_version -T name pattern"); exit(1); } diff --git a/usr.sbin/pkg_install/version/perform.c b/usr.sbin/pkg_install/version/perform.c index 8643dd2..df166f6 100644 --- a/usr.sbin/pkg_install/version/perform.c +++ b/usr.sbin/pkg_install/version/perform.c @@ -67,7 +67,7 @@ pkg_perform(char **indexarg) if (MatchName != NULL) { pat[0] = MatchName; pat[1] = NULL; - MatchType = MATCH_REGEX; + MatchType = RegexExtended ? MATCH_EREGEX : MATCH_REGEX; patterns = pat; } else { @@ -83,6 +83,7 @@ pkg_perform(char **indexarg) case MATCH_ALL: warnx("no packages installed"); return (0); + case MATCH_EREGEX: case MATCH_REGEX: warnx("no packages match pattern"); return (1); @@ -308,6 +309,80 @@ show_version(const char *installed, const char *latest, const char *source) } } +int +version_match(char *pattern, const char *pkgname) +{ + int ret = 0; + int matchstream = 0; + FILE *fp = NULL; + Boolean isTMP = FALSE; + + if (isURL(pkgname)) { + fp = fetchGetURL(pkgname, ""); + isTMP = TRUE; + matchstream = 1; + if (fp == NULL) + errx(2, "Unable to open %s.", pkgname); + } else if (pkgname[0] == '/') { + fp = fopen(pkgname, "r"); + isTMP = TRUE; + matchstream = 1; + if (fp == NULL) + errx(2, "Unable to open %s.", pkgname); + } else if (strcmp(pkgname, "-") == 0) { + fp = stdin; + matchstream = 1; + } else if (isURL(pattern)) { + fp = fetchGetURL(pattern, ""); + isTMP = TRUE; + matchstream = -1; + if (fp == NULL) + errx(2, "Unable to open %s.", pattern); + } else if (pattern[0] == '/') { + fp = fopen(pattern, "r"); + isTMP = TRUE; + matchstream = -1; + if (fp == NULL) + errx(2, "Unable to open %s.", pattern); + } else if (strcmp(pattern, "-") == 0) { + fp = stdin; + matchstream = -1; + } else { + ret = pattern_match(MATCH_GLOB, pattern, pkgname); + } + + if (fp != NULL) { + size_t len; + char *line; + while ((line = fgetln(fp, &len)) != NULL) { + int match; + char *ch, ln[2048]; + size_t lnlen; + if (len > 0 && line[len-1] == '\n') + len --; + lnlen = len; + if (lnlen > sizeof(ln)-1) + lnlen = sizeof(ln)-1; + memcpy(ln, line, lnlen); + ln[lnlen] = '\0'; + if ((ch = strchr(ln, '|')) != NULL) + ch[0] = '\0'; + if (matchstream > 0) + match = pattern_match(MATCH_GLOB, pattern, ln); + else + match = pattern_match(MATCH_GLOB, ln, pkgname); + if (match == 1) { + ret = 1; + printf("%.*s\n", (int)len, line); + } + } + if (isTMP) + fclose(fp); + } + + return ret; +} + void cleanup(int sig) { diff --git a/usr.sbin/pkg_install/version/pkg_version.1 b/usr.sbin/pkg_install/version/pkg_version.1 index 3f03997..ac1ac91 100644 --- a/usr.sbin/pkg_install/version/pkg_version.1 +++ b/usr.sbin/pkg_install/version/pkg_version.1 @@ -24,7 +24,7 @@ .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" .\" $FreeBSD$ -.Dd July 17, 1998 +.Dd June 29, 2004 .Dt PKG_VERSION 1 .Os .Sh NAME @@ -35,10 +35,15 @@ .Op Fl hv .Op Fl l Ar limchar .Op Fl L Ar limchar -.Op Fl s Ar string +.Oo +.Op Fl X +.Fl s Ar string +.Oc .Op Ar index .Nm .Op Fl t Ar version1 version2 +.Nm +.Op Fl T Ar pkgname pattern .Sh DESCRIPTION The .Nm @@ -134,6 +139,10 @@ with single quotes. .It Fl s Limit the output to those packages whose names match a given .Ar string . +.It Fl X +Interpret +.Ar string +as a extended regular expression. .It Fl t Test a pair of version number strings and exit. The output consists of one of the single characters @@ -144,6 +153,16 @@ The output consists of one of the single characters .Li \&> (left-hand number greater) on standard output. This flag is mostly useful for scripts or for testing. +.It Fl T +Test whether +.Ar pkgname +is matched by +.Ar pattern +and set the exit code accordingly. +.Fl T +can also be used in `filter mode': +When one of the arguments is `-', standard input is used, and lines +with matching package names/patterns are echoed to standard output. .It Fl v Enable verbose output. Verbose output includes some English-text interpretations of the version number comparisons, as well as the @@ -157,7 +176,7 @@ URL understandable by can be used here. If no .Ar index file is specified on the command line, -.Pa /usr/ports/INDEX +.Pa /usr/ports/INDEX-5 is used. .El .Sh COMPATIBILITY @@ -171,8 +190,8 @@ option has been deprecated and is no longer supported. .Xr pkg_delete 1 , .Xr pkg_info 1 .Sh FILES -.Bl -tag -width /usr/ports/INDEX -compact -.It Pa /usr/ports/INDEX +.Bl -tag -width /usr/ports/INDEX-5 -compact +.It Pa /usr/ports/INDEX-5 Default index file. .El .Sh EXAMPLES @@ -186,7 +205,7 @@ index file: The command below generates a report against the version numbers in the on-line ports collection: .Pp -.Dl % pkg_version ftp://ftp.FreeBSD.org/pub/FreeBSD/branches/-current/ports/INDEX +.Dl % pkg_version http://www.FreeBSD.org/ports/INDEX-5 .Pp The following command compares two package version strings: .Pp @@ -203,4 +222,5 @@ partially based on a Perl script written by .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 +.An Akinori MUSHA Aq knu@FreeBSD.org , +.An Oliver Eikemeier Aq eik@FreeBSD.org diff --git a/usr.sbin/pkg_install/version/version.h b/usr.sbin/pkg_install/version/version.h index daaebb0..3f3bcb8 100644 --- a/usr.sbin/pkg_install/version/version.h +++ b/usr.sbin/pkg_install/version/version.h @@ -40,5 +40,8 @@ SLIST_HEAD(index_head, index_entry); extern char *LimitChars; extern char *PreventChars; extern char *MatchName; +extern Boolean RegexExtended; + +extern int version_match(char *, const char *); #endif /* _INST_VERSION_H_INCLUDE */ -- cgit v1.1