diff options
author | sobomax <sobomax@FreeBSD.org> | 2001-02-08 17:44:00 +0000 |
---|---|---|
committer | sobomax <sobomax@FreeBSD.org> | 2001-02-08 17:44:00 +0000 |
commit | 391b1060843d1e99546c0c4b871c89ef16217a94 (patch) | |
tree | 5c4a922cdaca2a0d079072c7efa1182372c56a31 /usr.sbin/pkg_install/info/perform.c | |
parent | 4331c8a979db44fc3779e72b294c0a5d6a78d619 (diff) | |
download | FreeBSD-src-391b1060843d1e99546c0c4b871c89ef16217a94.zip FreeBSD-src-391b1060843d1e99546c0c4b871c89ef16217a94.tar.gz |
- By default treat supplied arguments as a shell globs to be matched against
names of installed packages;
- add new `-G' option to disable glob matching and revert to previous
behaviour (I have no idea why this could be necessary, though);
- add a new `-x' option, which instructs pkg_info(1) to treat supplied
arguments as a regular expressions.
For example:
$ pkg_info foo\* - displays information about all packages whose names start
from foo
$ pkg_info -G foo\*-1.1 - displays information about package named "foo*-1.1"
$ pkg_info -x ^foo.\* - displays information about all packages whose names
start from foo
Original idea submitted by: Edwin Groothuis <mavetju@chello.nl> (bin/24695)
Reviewed by: jkh, roam
Approved by: jkh
Diffstat (limited to 'usr.sbin/pkg_install/info/perform.c')
-rw-r--r-- | usr.sbin/pkg_install/info/perform.c | 155 |
1 files changed, 135 insertions, 20 deletions
diff --git a/usr.sbin/pkg_install/info/perform.c b/usr.sbin/pkg_install/info/perform.c index f9955bc..80de910 100644 --- a/usr.sbin/pkg_install/info/perform.c +++ b/usr.sbin/pkg_install/info/perform.c @@ -26,12 +26,16 @@ static const char rcsid[] = #include "lib.h" #include "info.h" +#include <sys/types.h> +#include <err.h> +#include <glob.h> #include <fts.h> +#include <regex.h> #include <signal.h> -#include <err.h> static int fname_cmp(const FTSENT **, const FTSENT **); static int pkg_do(char *); +static int rexs_match(char **, char *); int pkg_perform(char **pkgs) @@ -50,31 +54,93 @@ pkg_perform(char **pkgs) snprintf(buf, FILENAME_MAX, "%s/%s", tmp, CheckPkg); return abs(access(buf, R_OK)); + /* Not reached */ } - else if (AllInstalled) { - FTS *ftsp; - FTSENT *f; - char *paths[2]; - if (!isdir(tmp)) - return 1; - paths[0] = tmp; - paths[1] = NULL; - ftsp = fts_open(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) { - err_cnt += pkg_do(f->fts_name); - fts_set(ftsp, f, FTS_SKIP); + switch (MatchType) { + case MATCH_ALL: + case MATCH_REGEX: + { + FTS *ftsp; + FTSENT *f; + char *paths[2]; + int errcode; + + if (!isdir(tmp)) + return 1; + paths[0] = tmp; + paths[1] = NULL; + ftsp = fts_open(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); + if (MatchType == MATCH_REGEX) { + errcode = rexs_match(pkgs, f->fts_name); + if (errcode == -1) { + err_cnt += 1; + break; + } + else if (errcode == 0) + continue; + } + err_cnt += pkg_do(f->fts_name); + } } + fts_close(ftsp); } - fts_close(ftsp); } - } - else + break; + case MATCH_GLOB: + { + glob_t g; + char *gexpr; + char *cp; + int gflags; + int prev_matchc; + + gflags = GLOB_ERR; + prev_matchc = 0; + for (i = 0; pkgs[i]; i++) { + asprintf(&gexpr, "%s/%s", tmp, pkgs[i]); + + if (glob(gexpr, gflags, NULL, &g) != 0) { + warn("%s: error encountered when matching glob", pkgs[i]); + return 1; + } + + /* + * If glob doesn't match try to use pkgs[i] directly - it + * could be name of the tarball. + */ + if (g.gl_matchc == prev_matchc) + err_cnt += pkg_do(pkgs[i]); + + prev_matchc = g.gl_matchc; + gflags |= GLOB_APPEND; + free(gexpr); + } + + for (i = 0; i < g.gl_matchc; i++) { + cp = strrchr(g.gl_pathv[i], '/'); + if (cp == NULL) + cp = g.gl_pathv[i]; + else + cp++; + + err_cnt += pkg_do(cp); + } + + globfree(&g); + } + break; + default: for (i = 0; pkgs[i]; i++) err_cnt += pkg_do(pkgs[i]); + break; + } + return err_cnt; } @@ -227,7 +293,7 @@ cleanup(int sig) if (!in_cleanup) { in_cleanup = 1; - leave_playpen(); + leave_playpen(); } if (sig) exit(1); @@ -238,3 +304,52 @@ fname_cmp(const FTSENT **a, const FTSENT **b) { return strcmp((*a)->fts_name, (*b)->fts_name); } + +/* + * Returns 1 if specified pkgname matches at least one + * of the RE from patterns. Otherwise return 0 if no + * matches were found or -1 if RE engine reported an + * error (usually invalid syntax). + */ +static int +rexs_match(char **patterns, char *pkgname) +{ + Boolean matched; + char errbuf[128]; + int i; + int errcode; + int retval; + regex_t rex; + + errcode = 0; + retval = 0; + matched = FALSE; + for (i = 0; patterns[i]; i++) { + errcode = regcomp(&rex, patterns[i], REG_BASIC | REG_NOSUB); + if (errcode != 0) + break; + + errcode = regexec(&rex, pkgname, 0, NULL, 0); + if (errcode == 0) { + matched = TRUE; + retval = 1; + break; + } + else if (errcode != REG_NOMATCH) + break; + + regfree(&rex); + errcode = 0; + } + + if (errcode != 0) { + regerror(errcode, &rex, errbuf, sizeof(errbuf)); + warnx("%s: %s", patterns[i], errbuf); + retval = -1; + } + + if ((errcode != 0) || (matched == TRUE)) + regfree(&rex); + + return retval; +} |