Create file security context container.
authorjbj <devnull@localhost>
Sun, 21 Dec 2003 15:21:41 +0000 (15:21 +0000)
committerjbj <devnull@localhost>
Sun, 21 Dec 2003 15:21:41 +0000 (15:21 +0000)
CVS patchset: 6986
CVS date: 2003/12/21 15:21:41

lib/Makefile.am
lib/rpmsx.c [new file with mode: 0644]
lib/rpmsx.h [new file with mode: 0644]
lib/setfiles.c

index 4f21df6..820beb0 100644 (file)
@@ -18,7 +18,7 @@ EXTRA_DIST = getdate.y
 pkgincdir = $(pkgincludedir)
 pkginc_HEADERS = \
        misc.h rpmcli.h rpmlib.h \
-       rpmal.h rpmds.h rpmfi.h rpmps.h rpmte.h rpmts.h stringbuf.h
+       rpmal.h rpmds.h rpmfi.h rpmps.h rpmsx.h rpmte.h rpmts.h stringbuf.h
 noinst_HEADERS = \
        cpio.h fsm.h manifest.h psm.h rpmlead.h signature.h
 
@@ -34,8 +34,8 @@ librpm_la_SOURCES = \
        manifest.c misc.c package.c \
        poptALL.c poptI.c poptQV.c psm.c query.c \
        rpmal.c rpmchecksig.c rpmds.c rpmfi.c rpminstall.c \
-       rpmlead.c rpmlibprov.c rpmps.c rpmrc.c rpmte.c rpmts.c rpmvercmp.c \
-       signature.c stringbuf.c transaction.c \
+       rpmlead.c rpmlibprov.c rpmps.c rpmrc.c rpmsx.c rpmte.c rpmts.c \
+       rpmvercmp.c signature.c stringbuf.c transaction.c \
        verify.c
 librpm_la_LDFLAGS = -release 4.3 $(LDFLAGS) \
        $(top_builddir)/rpmdb/librpmdb.la \
@@ -77,10 +77,6 @@ BUILT_SOURCES = getdate.c # rpmlib.lcd
 #tds_SOURCES = tds.c
 #tds_LDFLAGS = @LDFLAGS_STATIC@ ./librpm.la
 
-noinst_PROGRAMS = setfiles
-setfiles_SOURCES =     setfiles.c
-setfiles_LDFLAGS =     @LDFLAGS_STATIC@ -lselinux $(top_builddir)/popt/libpopt.la # ./librpm.la
-
 rpmlib.lcd: Makefile.am ${librpm_la_SOURCES} ${pkginc_HEADERS} ${noinst_HEADERS}
        -lclint ${DEFS} ${INCLUDES} ${librpm_la_SOURCES} -dump $@ 2>/dev/null
 
@@ -92,12 +88,14 @@ sources:
 lint:
        $(LINT) $(DEFS) $(INCLUDES) $(librpm_la_SOURCES)
 
-th: th.c librpm.la
-       $(CC) $(CFLAGS) $(DEFS) $(INCLUDES) -o $@ $< $(mylibs)
-
+setfiles: setfiles.o
+       $(LINK) @LDFLAGS_STATIC@ $(CFLAGS) $(DEFS) $(INCLUDES) -o $@ $< \
+       -lselinux \
+       $(top_builddir)/rpmio/librpmio.la \
+       $(top_builddir)/popt/libpopt.la
+       
 #tds: tds.c librpm.la
 #      $(CC) $(CFLAGS) $(DEFS) $(INCLUDES) -o $@ $< $(mylibs)
-#
 
 trb: trb.o librpm.la
        $(LINK) @LDFLAGS_STATIC@ $(CFLAGS) $(DEFS) $(INCLUDES) -o $@ $< $(mylibs)
@@ -108,6 +106,12 @@ tthread: tthread.o librpm.la
 tsystem: tsystem.o $(top_builddir)/popt/libpopt.la
        $(LINK) $(CFLAGS) $(DEFS) $(INCLUDES) -o $@ $< $(top_builddir)/rpmio/librpmio.la $(top_builddir)/popt/libpopt.la
 
+tre: tre.o
+       $(LINK) @LDFLAGS_STATIC@ $(CFLAGS) $(DEFS) $(INCLUDES) -o $@ $< \
+       -lselinux \
+       $(top_builddir)/rpmio/librpmio.la \
+       $(top_builddir)/popt/libpopt.la
+
 tcpu: tcpu.o librpm.la
        $(LINK) @LDFLAGS_STATIC@ $(CFLAGS) $(DEFS) $(INCLUDES) -o $@ $< $(mylibs)
 
diff --git a/lib/rpmsx.c b/lib/rpmsx.c
new file mode 100644 (file)
index 0000000..1fe2e93
--- /dev/null
@@ -0,0 +1,144 @@
+/** \ingroup rpmdep
+ * \file lib/rpmsx.c
+ */
+#include "system.h"
+
+#include <rpmlib.h>
+
+#define        _RPMSX_INTERNAL
+#include "rpmsx.h"
+
+#include "debug.h"
+
+/*@unchecked@*/
+int _rpmsx_debug = 0;
+
+rpmsx XrpmsxUnlink(rpmsx sx, const char * msg, const char * fn, unsigned ln)
+{
+    if (sx == NULL) return NULL;
+/*@-modfilesys@*/
+if (_rpmsx_debug && msg != NULL)
+fprintf(stderr, "--> sx %p -- %d %s at %s:%u\n", sx, sx->nrefs, msg, fn, ln);
+/*@=modfilesys@*/
+    sx->nrefs--;
+    return NULL;
+}
+
+rpmsx XrpmsxLink(rpmsx sx, const char * msg, const char * fn, unsigned ln)
+{
+    if (sx == NULL) return NULL;
+    sx->nrefs++;
+
+/*@-modfilesys@*/
+if (_rpmsx_debug && msg != NULL)
+fprintf(stderr, "--> sx %p ++ %d %s at %s:%u\n", sx, sx->nrefs, msg, fn, ln);
+/*@=modfilesys@*/
+
+    /*@-refcounttrans@*/ return sx; /*@=refcounttrans@*/
+}
+
+rpmsx rpmsxFree(rpmsx sx)
+{
+    int i;
+
+    if (sx == NULL)
+       return NULL;
+
+    if (sx->nrefs > 1)
+       return rpmsxUnlink(sx, __func__);
+
+/*@-modfilesys@*/
+if (_rpmsx_debug < 0)
+fprintf(stderr, "*** sx %p\t%s[%d]\n", sx, __func__, sx->Count);
+/*@=modfilesys@*/
+
+    /*@-branchstate@*/
+    if (sx->Count > 0)
+    for (i = 0; i < sx->Count; i++) {
+       rpmsxp sxp = sx->sxp + i;
+       sxp->pattern = _free(sxp->pattern);
+       sxp->type = _free(sxp->type);
+       sxp->context = _free(sxp->context);
+    }
+    /*@=branchstate@*/
+
+    sx->sxp = _free(sx->sxp);
+
+    (void) rpmsxUnlink(sx, __func__);
+    /*@-refcounttrans -usereleased@*/
+/*@-bounsxwrite@*/
+    memset(sx, 0, sizeof(*sx));                /* XXX trash and burn */
+/*@=bounsxwrite@*/
+    sx = _free(sx);
+    /*@=refcounttrans =usereleased@*/
+    return NULL;
+}
+
+rpmsx rpmsxNew(const char * fn)
+{
+    rpmsx sx;
+
+    sx = xcalloc(1, sizeof(*sx));
+    sx->Count = 0;
+    sx->i = -1;
+    sx->sxp = NULL;
+
+/*@-modfilesys@*/
+if (_rpmsx_debug < 0)
+fprintf(stderr, "*** sx %p\t%s[%d]\n", sx, __func__, sx->Count);
+/*@=modfilesys@*/
+
+    return rpmsxLink(sx, (sx ? __func__ : NULL));
+}
+
+int rpmsxCount(const rpmsx sx)
+{
+    return (sx != NULL ? sx->Count : 0);
+}
+
+int rpmsxIx(const rpmsx sx)
+{
+    return (sx != NULL ? sx->i : -1);
+}
+
+int rpmsxSetIx(rpmsx sx, int ix)
+{
+    int i = -1;
+
+    if (sx != NULL) {
+       i = sx->i;
+       sx->i = ix;
+    }
+    return i;
+}
+
+int rpmsxNext(/*@null@*/ rpmsx sx)
+       /*@modifies sx @*/
+{
+    int i = -1;
+
+    if (sx != NULL && ++sx->i >= 0) {
+       if (sx->i < sx->Count) {
+           i = sx->i;
+       } else
+           sx->i = -1;
+
+/*@-modfilesys @*/
+if (_rpmsx_debug  < 0 && i != -1)
+fprintf(stderr, "*** sx %p\t%s[%d]\n", sx, __func__, i);
+/*@=modfilesys @*/
+
+    }
+
+    return i;
+}
+
+rpmsx rpmsxInit(/*@null@*/ rpmsx sx)
+       /*@modifies sx @*/
+{
+    if (sx != NULL)
+       sx->i = -1;
+    /*@-refcounttrans@*/
+    return sx;
+    /*@=refcounttrans@*/
+}
diff --git a/lib/rpmsx.h b/lib/rpmsx.h
new file mode 100644 (file)
index 0000000..7570b1c
--- /dev/null
@@ -0,0 +1,161 @@
+#ifndef H_RPMSX
+#define H_RPMSX
+
+/** \ingroup rpmdep rpmtrans
+ * \file lib/rpmsx.h
+ * Structure(s) used for file security context pattern handling
+ */
+
+#include <regex.h>
+
+/**
+ */
+/*@-exportlocal@*/
+/*@unchecked@*/
+extern int _rpmsx_debug;
+/*@=exportlocal@*/
+
+/**
+ */
+/*@-exportlocal@*/
+/*@unchecked@*/
+extern int _rpmsx_nopromote;
+/*@=exportlocal@*/
+
+typedef struct rpmsxp_s * rpmsxp;
+typedef struct rpmsx_s * rpmsx;
+
+#if defined(_RPMSX_INTERNAL)
+/**
+ * File security context regex pattern.
+ */
+struct rpmsxp_s {
+/*@only@*/ /*@null@*/
+    const char * pattern;      /*!< File path regex pattern. */
+/*@only@*/ /*@null@*/
+    const char * type;         /*!< File type. */
+/*@only@*/ /*@null@*/
+    const char * context;      /*!< Security context. */
+/*@only@*/ /*@null@*/
+    regex_t * preg;            /*!< Compiled regex. */
+};
+
+/**
+ * File security context patterns container.
+ */
+struct rpmsx_s {
+    int Count;                 /*!< No. of elements */
+    int i;                     /*!< Current element index. */
+/*@only@*/ /*@null@*/
+    rpmsxp sxp;                        /*!< File context patterns. */
+    int nrefs;                 /*!< Reference count. */
+};
+#endif /* defined(_RPMSX_INTERNAL) */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Unreference a security context patterns instance.
+ * @param sx           security context patterns
+ * @param msg
+ * @return             NULL always
+ */
+/*@unused@*/ /*@null@*/
+rpmsx rpmsxUnlink (/*@killref@*/ /*@only@*/ /*@null@*/ rpmsx sx,
+               /*@null@*/ const char * msg)
+       /*@modifies sx @*/;
+
+/** @todo Remove debugging entry from the ABI. */
+/*@-exportlocal@*/
+/*@null@*/
+rpmsx XrpmsxUnlink (/*@killref@*/ /*@only@*/ /*@null@*/ rpmsx sx,
+               /*@null@*/ const char * msg, const char * fn, unsigned ln)
+       /*@modifies sx @*/;
+/*@=exportlocal@*/
+#define        rpmsxUnlink(_sx, _msg)  XrpmsxUnlink(_sx, _msg, __FILE__, __LINE__)
+
+/**
+ * Reference a security context patterns instance.
+ * @param sx           security context patterns
+ * @param msg
+ * @return             new security context patterns reference
+ */
+/*@unused@*/ /*@newref@*/ /*@null@*/
+rpmsx rpmsxLink (/*@null@*/ rpmsx sx, /*@null@*/ const char * msg)
+       /*@modifies sx @*/;
+
+/** @todo Remove debugging entry from the ABI. */
+/*@newref@*/ /*@null@*/
+rpmsx XrpmsxLink (/*@null@*/ rpmsx sx, /*@null@*/ const char * msg,
+               const char * fn, unsigned ln)
+        /*@modifies sx @*/;
+#define        rpmsxLink(_sx, _msg)    XrpmsxLink(_sx, _msg, __FILE__, __LINE__)
+
+/**
+ * Destroy a security context patterns.
+ * @param sx           security context patterns
+ * @return             NULL always
+ */
+/*@null@*/
+rpmsx rpmsxFree(/*@killref@*/ /*@only@*/ /*@null@*/ rpmsx sx)
+       /*@modifies sx@*/;
+/**
+ * Create and load security context patterns.
+ * @param fn           header
+ * @param tagN         type of dependency
+ * @param scareMem     Use pointers to refcounted header memory?
+ * @return             new security context patterns
+ */
+/*@null@*/
+rpmsx rpmsxNew(const char * fn)
+       /*@*/;
+
+/**
+ * Return security context patterns count.
+ * @param sx           security context patterns
+ * @return             current count
+ */
+int rpmsxCount(/*@null@*/ const rpmsx sx)
+       /*@*/;
+
+/**
+ * Return security context patterns index.
+ * @param sx           security context patterns
+ * @return             current index
+ */
+int rpmsxIx(/*@null@*/ const rpmsx sx)
+       /*@*/;
+
+/**
+ * Set security context patterns index.
+ * @param sx           security context patterns
+ * @param ix           new index
+ * @return             current index
+ */
+int rpmsxSetIx(/*@null@*/ rpmsx sx, int ix)
+       /*@modifies sx @*/;
+
+/**
+ * Return next security context patterns iterator index.
+ * @param sx           security context patterns
+ * @return             security context patterns iterator index, -1 on termination
+ */
+int rpmsxNext(/*@null@*/ rpmsx sx)
+       /*@modifies sx @*/;
+
+/**
+ * Initialize security context patterns iterator.
+ * @param sx           security context patterns
+ * @return             security context patterns
+ */
+/*@null@*/
+rpmsx rpmsxInit(/*@null@*/ rpmsx sx)
+       /*@modifies sx @*/;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* H_RPMSX */
index aa99037..ac155c0 100644 (file)
@@ -84,10 +84,14 @@ static int rootpathlen = 0;
  * A file security context specification.
  */
 typedef struct spec {
-    char *regex_str;   /* regular expession string for diagnostic messages */
+/*@only@*/
+    char *pattern;     /* regular expession string for diagnostic messages */
+/*@only@*/
     char *type_str;    /* type string for diagnostic messages */
+/*@only@*/
     char *context;     /* context string */
-    regex_t regex;     /* compiled regular expression */
+/*@only@*/
+    regex_t * preg;    /* compiled regular expression */
     mode_t mode;       /* mode format value */
     int matches;       /* number of matching pathnames */
     int hasMetaChars;  /* indicates whether the RE has 
@@ -119,7 +123,7 @@ static int get_stem_from_spec(const char * const buf)
     if (!tmp)
        return 0;
 
-    for(ind = buf + 1; ind < tmp; ind++) {
+    for (ind = buf + 1; ind < tmp; ind++) {
        if (strchr(regex_chars, (int)*ind))
            return 0;
     }
@@ -147,7 +151,7 @@ static int find_stem_from_spec(const char **buf)
 
     if (!stem_len)
        return -1;
-    for(i = 0; i < num_stems; i++) {
+    for (i = 0; i < num_stems; i++) {
        if (stem_len != stem_arr[i].len)
            continue;
        if (strncmp(*buf, stem_arr[i].buf, stem_len))
@@ -158,18 +162,10 @@ static int find_stem_from_spec(const char **buf)
 
     if (num_stems == alloc_stems) {
        alloc_stems = alloc_stems * 2 + 16;
-       stem_arr = realloc(stem_arr, sizeof(*stem_arr) * alloc_stems);
-       if (!stem_arr) {
-           fprintf(stderr, "Unable to grow stem array to %d entries:  out of memory.\n", alloc_stems);
-           exit(1);
-       }
+       stem_arr = xrealloc(stem_arr, sizeof(*stem_arr) * alloc_stems);
     }
     stem_arr[num_stems].len = stem_len;
-    stem_arr[num_stems].buf = malloc(stem_len + 1);
-    if (!stem_arr[num_stems].buf) {
-       fprintf(stderr, "Unable to allocate new stem of length %d:  out of memory.\n", stem_len+1);
-       exit(1);
-    }
+    stem_arr[num_stems].buf = xmalloc(stem_len + 1);
     memcpy(stem_arr[num_stems].buf, *buf, stem_len);
     stem_arr[num_stems].buf[stem_len] = '\0';
     num_stems++;
@@ -186,7 +182,7 @@ static int find_stem_from_file(const char **buf)
     int i;
 
     if (stem_len)
-    for(i = 0; i < num_stems; i++) {
+    for (i = 0; i < num_stems; i++) {
        if (stem_len != stem_arr[i].len)
            continue;
        if (strncmp(*buf, stem_arr[i].buf, stem_len))
@@ -252,14 +248,7 @@ static file_spec_t file_spec_add(ino_t ino, int specind, const char *file)
            if (ret < 0 || sb.st_ino != ino) {
                fl->specind = specind;
                free(fl->file);
-               fl->file = malloc(strlen(file) + 1);
-               if (!fl->file) {
-                   fprintf(stderr,
-                       "%s:  insufficient memory for file label entry for %s\n",
-                       __progname, file);
-                   return NULL;
-               }
-               strcpy(fl->file, file);
+               fl->file = xstrdup(file);
                return fl;
            }
 
@@ -275,14 +264,7 @@ static file_spec_t file_spec_add(ino_t ino, int specind, const char *file)
            fl->specind =
                    (specind > fl->specind) ? specind : fl->specind;
            free(fl->file);
-           fl->file = malloc(strlen(file) + 1);
-           if (!fl->file) {
-               fprintf(stderr,
-                       "%s:  insufficient memory for file label entry for %s\n",
-                       __progname, file);
-               return NULL;
-           }
-           strcpy(fl->file, file);
+           fl->file = xstrdup(file);
            return fl;
        }
 
@@ -290,21 +272,10 @@ static file_spec_t file_spec_add(ino_t ino, int specind, const char *file)
            break;
     }
 
-    fl = malloc(sizeof(*fl));
-    if (!fl) {
-       fprintf(stderr, "%s:  insufficient memory for file label entry for %s\n",
-               __progname, file);
-       return NULL;
-    }
+    fl = xmalloc(sizeof(*fl));
     fl->ino = ino;
     fl->specind = specind;
-    fl->file = malloc(strlen(file) + 1);
-    if (!fl->file) {
-       fprintf(stderr, "%s:  insufficient memory for file label entry for %s\n",
-               __progname, file);
-       return NULL;
-    }
-    strcpy(fl->file, file);
+    fl->file = xstrdup(file);
     fl->next = prevfl->next;
     prevfl->next = fl;
     return fl;
@@ -406,9 +377,9 @@ static int match(const char *name, struct stat *sb)
            continue;
 
        if (sp->stem_id == -1)
-           ret = regexec(&sp->regex, name, 0, NULL, 0);
+           ret = regexec(sp->preg, name, 0, NULL, 0);
        else
-           ret = regexec(&sp->regex, buf, 0, NULL, 0);
+           ret = regexec(sp->preg, buf, 0, NULL, 0);
        if (ret == 0)
            break;
 
@@ -416,9 +387,9 @@ static int match(const char *name, struct stat *sb)
            continue;
 
        /* else it's an error */
-       regerror(ret, &sp->regex, errbuf, sizeof errbuf);
+       regerror(ret, sp->preg, errbuf, sizeof errbuf);
        fprintf(stderr, "%s:  unable to match %s against %s:  %s\n",
-               __progname, name, sp->regex_str, errbuf);
+               __progname, name, sp->pattern, errbuf);
        return -1;
     }
 
@@ -454,7 +425,7 @@ static int nodups_specs(void)
            spec_t sjp = spec_arr + j;
 
            /* Check if same RE string */
-           if (strcmp(sjp->regex_str, sip->regex_str))
+           if (strcmp(sjp->pattern, sip->pattern))
                continue;
            if (sjp->mode && sip->mode && sjp->mode != sip->mode)
                continue;
@@ -464,12 +435,12 @@ static int nodups_specs(void)
                /* If different contexts, give warning */
                fprintf(stderr,
                "ERROR: Multiple different specifications for %s  (%s and %s).\n",
-                       sip->regex_str, sjp->context, sip->context);
+                       sip->pattern, sjp->context, sip->context);
            } else {
                /* If same contexts give warning */
                fprintf(stderr,
                "WARNING: Multiple same specifications for %s.\n",
-                       sip->regex_str);
+                       sip->pattern);
            }
        }
     }
@@ -486,17 +457,13 @@ static void usage(const char * const name, poptContext optCon)
 }
 
 /* Determine if the regular expression specification has any meta characters. */
-static void spec_hasMetaChars(spec_t spec)
+static void spec_hasMetaChars(spec_t sp)
 {
-    char *c;
-    int len;
-    char *end;
+    char * c = sp->pattern;
+    int len = strlen(c);
+    char * end = c + len;
 
-    c = spec->regex_str;
-    len = strlen(spec->regex_str);
-    end = c + len;
-
-    spec->hasMetaChars = 0; 
+    sp->hasMetaChars = 0; 
 
     /* Look at each character in the RE specification string for a 
      * meta character. Return when any meta character reached. */
@@ -512,7 +479,7 @@ static void spec_hasMetaChars(spec_t spec)
        case '[':
        case '(':
        case '{':
-           spec->hasMetaChars = 1;
+           sp->hasMetaChars = 1;
            return;
            break;
        case '\\':              /* skip the next character */
@@ -535,11 +502,11 @@ static void spec_hasMetaChars(spec_t spec)
 static int apply_spec(const char *file,
                      const struct stat *sb_unused, int flag, struct FTW *s_unused)
 {
-    const char *my_file;
+    const char * my_file;
     file_spec_t fl;
     struct stat my_sb;
     int i, ret;
-    char *context; 
+    char * context; 
     spec_t sp;
 
     /* Skip the extra slash at the beginning, if present. */
@@ -580,11 +547,11 @@ static int apply_spec(const char *file,
     if (debug) {
        if (sp->type_str) {
            printf("%s:  %s matched by (%s,%s,%s)\n", __progname,
-                      my_file, sp->regex_str,
+                      my_file, sp->pattern,
                       sp->type_str, sp->context);
        } else {
            printf("%s:  %s matched by (%s,%s)\n", __progname,
-                      my_file, sp->regex_str, sp->context);
+                      my_file, sp->pattern, sp->context);
        }
     }
 
@@ -592,8 +559,7 @@ static int apply_spec(const char *file,
     ret = lgetfilecon(my_file, &context);
     if (ret < 0) {
        if (errno == ENODATA) {
-           context = malloc(10);
-           strcpy(context, "<<none>>");
+           context = xstrdup("<<none>>");
        } else {
            perror(my_file);
            fprintf(stderr, "%s:  unable to obtain attribute for file %s\n", 
@@ -684,6 +650,7 @@ int parseREContexts(const char *fn)
      */
     for (pass = 0; pass < 2; pass++) {
        spec_t sp;
+
        lineno = 0;
        nspec = 0;
        sp = spec_arr;
@@ -724,25 +691,19 @@ int parseREContexts(const char *fn)
                /* On the second pass, compile and store the specification in spec. */
                const char *reg_buf = regex;
                sp->stem_id = find_stem_from_spec(&reg_buf);
-               sp->regex_str = regex;
+               sp->pattern = regex;
 
                /* Anchor the regular expression. */
                len = strlen(reg_buf);
-               anchored_regex = malloc(len + 3);
-               if (!anchored_regex) {
-                   fprintf(stderr,
-                       "%s:  insufficient memory for anchored regexp on line %d\n",
-                       fn, lineno);
-                   return -1;
-               }
+               anchored_regex = xmalloc(len + 3);
                sprintf(anchored_regex, "^%s$", reg_buf);
 
                /* Compile the regular expression. */
-               regerr = regcomp(&sp->regex, anchored_regex,
+               sp->preg = xcalloc(1, sizeof(*sp->preg));
+               regerr = regcomp(sp->preg, anchored_regex,
                            REG_EXTENDED | REG_NOSUB);
                if (regerr < 0) {
-                   regerror(regerr, &sp->regex,
-                                errbuf, sizeof errbuf);
+                   regerror(regerr, sp->preg, errbuf, sizeof errbuf);
                    fprintf(stderr,
                        "%s:  unable to compile regular expression %s on line number %d:  %s\n",
                        fn, regex, lineno,
@@ -828,12 +789,7 @@ int parseREContexts(const char *fn)
            QPRINTF("%s:  read %d specifications\n", fn, nspec);
            if (nspec == 0)
                return 0;
-           if ((spec_arr = malloc(sizeof(*spec_arr) * nspec)) == NULL) {
-               fprintf(stderr, "%s:  insufficient memory for specifications\n",
-                       fn);
-               return -1;
-           }
-           memset(spec_arr, 0, sizeof(*spec_arr) * nspec);
+           spec_arr = xcalloc(nspec, sizeof(*spec_arr));
            rewind(fp);
        }
     }
@@ -1008,12 +964,11 @@ int main(int argc, char **argv)
                continue;
            if (sp->type_str) {
                printf("%s:  Warning!  No matches for (%s, %s, %s)\n",
-                        __progname, sp->regex_str,
+                        __progname, sp->pattern,
                         sp->type_str, sp->context);
            } else {
                printf("%s:  Warning!  No matches for (%s, %s)\n",
-                        __progname, sp->regex_str,
-                        sp->context);
+                        __progname, sp->pattern, sp->context);
            }
        }
     }