summaryrefslogtreecommitdiffstats
path: root/usr.sbin/pkg_install/lib
diff options
context:
space:
mode:
authorsobomax <sobomax@FreeBSD.org>2001-02-27 09:00:18 +0000
committersobomax <sobomax@FreeBSD.org>2001-02-27 09:00:18 +0000
commit9ef21beb7a0f2e40841eaec959a3353bb1a0fab1 (patch)
treee3f9b793ac5867f8c854408a2545d3e05f9e0df5 /usr.sbin/pkg_install/lib
parent3dba1d1543776a0f641cde330672fdb902764a4b (diff)
downloadFreeBSD-src-9ef21beb7a0f2e40841eaec959a3353bb1a0fab1.zip
FreeBSD-src-9ef21beb7a0f2e40841eaec959a3353bb1a0fab1.tar.gz
- Merge recently added into pkg_info(1) regex/glob matching functionality into
pkg_delete(1) as well; - add a new `-a' option for pkg_delete(1) to delete all installed packages; - add a new `-i' option for pkg_delete(1) to request simple rm(1)-like interactive confirmation before attempting to delete each package. Silently approved by: jkh, -ports
Diffstat (limited to 'usr.sbin/pkg_install/lib')
-rw-r--r--usr.sbin/pkg_install/lib/Makefile4
-rw-r--r--usr.sbin/pkg_install/lib/lib.h8
-rw-r--r--usr.sbin/pkg_install/lib/match.c197
3 files changed, 208 insertions, 1 deletions
diff --git a/usr.sbin/pkg_install/lib/Makefile b/usr.sbin/pkg_install/lib/Makefile
index 3876b10..990bfe3 100644
--- a/usr.sbin/pkg_install/lib/Makefile
+++ b/usr.sbin/pkg_install/lib/Makefile
@@ -1,5 +1,7 @@
+# $FreeBSD$
+
LIB= install
-SRCS= file.c msg.c plist.c str.c exec.c global.c pen.c
+SRCS= file.c msg.c plist.c str.c exec.c global.c pen.c match.c
CFLAGS+= ${DEBUG}
NOPROFILE= yes
NOPIC= yes
diff --git a/usr.sbin/pkg_install/lib/lib.h b/usr.sbin/pkg_install/lib/lib.h
index 2584655..fae802d 100644
--- a/usr.sbin/pkg_install/lib/lib.h
+++ b/usr.sbin/pkg_install/lib/lib.h
@@ -88,6 +88,11 @@ enum _plist_t {
};
typedef enum _plist_t plist_t;
+enum _match_t {
+ MATCH_ALL, MATCH_EXACT, MATCH_GLOB, MATCH_REGEX
+};
+typedef enum _match_t match_t;
+
/* Types */
typedef unsigned int Boolean;
@@ -169,6 +174,9 @@ Boolean make_preserve_name(char *, int, char *, char *);
/* For all */
int pkg_perform(char **);
+/* Query installed packages */
+char **matchinstalled(match_t, char **, int *);
+
/* Externs */
extern Boolean Verbose;
extern Boolean Fake;
diff --git a/usr.sbin/pkg_install/lib/match.c b/usr.sbin/pkg_install/lib/match.c
new file mode 100644
index 0000000..21495f6
--- /dev/null
+++ b/usr.sbin/pkg_install/lib/match.c
@@ -0,0 +1,197 @@
+#ifndef lint
+static const char rcsid[] =
+ "$FreeBSD$";
+#endif
+
+/*
+ * 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 "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(char *, char *);
+static void storeappend(struct store *, const char *);
+static int fname_cmp(const FTSENT **, const FTSENT **);
+
+/*
+ * Function to query names of installed packages.
+ * MatchType - one of MATCH_ALL, MATCH_REGEX, MATCH_GLOB;
+ * 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, matched, errcode;
+ char *tmp;
+ char *paths[2];
+ static struct store *store = NULL;
+ FTS *ftsp;
+ FTSENT *f;
+
+ if (store == NULL) {
+ store = malloc(sizeof *store);
+ 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->used = 0;
+
+ if (retval != NULL)
+ *retval = 0;
+
+ tmp = getenv(PKG_DBDIR);
+ if (!tmp)
+ tmp = DEF_LOG_DIR;
+ if (!isdir(tmp)) {
+ if (retval != NULL)
+ *retval = 1;
+ return NULL;
+ /* Not reached */
+ }
+
+ 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_ALL) {
+ storeappend(store, f->fts_name);
+ continue;
+ }
+ for (i = 0; patterns[i]; i++) {
+ matched = 0;
+ switch (MatchType) {
+ case MATCH_REGEX:
+ errcode = rex_match(patterns[i], f->fts_name);
+ if (errcode == 1) {
+ storeappend(store, f->fts_name);
+ matched = 1;
+ } else if (errcode == -1) {
+ if (retval != NULL)
+ *retval = 1;
+ return NULL;
+ /* Not reached */
+ }
+ break;
+ case MATCH_GLOB:
+ if (fnmatch(patterns[i], f->fts_name, 0) == 0) {
+ storeappend(store, f->fts_name);
+ matched = 1;
+ }
+ break;
+ default:
+ break;
+ }
+ if (matched == 1)
+ break;
+ }
+ }
+ }
+ fts_close(ftsp);
+ }
+
+ if (store->used == 0)
+ return NULL;
+ else
+ return store->store;
+}
+
+/*
+ * 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(char *pattern, char *pkgname)
+{
+ char errbuf[128];
+ int errcode;
+ int retval;
+ regex_t rex;
+
+ retval = 0;
+
+ errcode = regcomp(&rex, pattern, 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;
+}
+
+static void
+storeappend(struct store *store, const char *item)
+{
+ char **tmp;
+
+ if (store->used + 2 > store->currlen) {
+ tmp = store->store;
+ store->currlen += 16;
+ store->store = malloc(store->currlen * sizeof(*(store->store)));
+ memcpy(store->store, tmp, store->used * sizeof(*(store->store)));
+ free(tmp);
+ }
+
+ asprintf(&(store->store[store->used]), "%s", item);
+ store->used++;
+ store->store[store->used] = NULL;
+}
+
+static int
+fname_cmp(const FTSENT **a, const FTSENT **b)
+{
+ return strcmp((*a)->fts_name, (*b)->fts_name);
+}
OpenPOWER on IntegriCloud