freshen to upstream CVS head
[debian/pax] / pat_rep.c
index a93809f743692c9e4b1a2a9cdc60184caba81b17..ff79582ce24a34d81f14c1082263478e24c1ee0b 100644 (file)
--- a/pat_rep.c
+++ b/pat_rep.c
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pat_rep.c,v 1.11 1997/09/01 18:29:56 deraadt Exp $    */
+/*     $OpenBSD: pat_rep.c,v 1.30 2005/08/05 08:30:10 djm Exp $        */
 /*     $NetBSD: pat_rep.c,v 1.4 1995/03/21 09:07:33 cgd Exp $  */
 
 /*-
  * 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.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -40,9 +36,9 @@
 
 #ifndef lint
 #if 0
-static char sccsid[] = "@(#)pat_rep.c  8.2 (Berkeley) 4/18/94";
+static const char sccsid[] = "@(#)pat_rep.c    8.2 (Berkeley) 4/18/94";
 #else
-static char rcsid[] = "$OpenBSD: pat_rep.c,v 1.11 1997/09/01 18:29:56 deraadt Exp $";
+static const char rcsid[] = "$OpenBSD: pat_rep.c,v 1.30 2005/08/05 08:30:10 djm Exp $";
 #endif
 #endif /* not lint */
 
@@ -55,11 +51,7 @@ static char rcsid[] = "$OpenBSD: pat_rep.c,v 1.11 1997/09/01 18:29:56 deraadt Ex
 #include <unistd.h>
 #include <stdlib.h>
 #include <errno.h>
-#ifdef NET2_REGEX
-#include <regexp.h>
-#else
 #include <regex.h>
-#endif
 #include "pax.h"
 #include "pat_rep.h"
 #include "extern.h"
@@ -77,23 +69,19 @@ static PATTERN *pattail = NULL;             /* file pattern match list tail */
 static REPLACE *rephead = NULL;                /* replacement string list head */
 static REPLACE *reptail = NULL;                /* replacement string list tail */
 
-static int rep_name __P((char *, int *, int));
-static int tty_rename __P((register ARCHD *));
-static int fix_path __P((char *, int *, char *, int));
-static int fn_match __P((register char *, register char *, char **));
-static char * range_match __P((register char *, register int));
-#ifdef NET2_REGEX
-static int resub __P((regexp *, char *, char *, register char *));
-#else
-static int resub __P((regex_t *, regmatch_t *, char *, char *, char *));
-#endif
+static int rep_name(char *, size_t, int *, int);
+static int tty_rename(ARCHD *);
+static int fix_path(char *, int *, char *, int);
+static int fn_match(char *, char *, char **);
+static char * range_match(char *, int);
+static int resub(regex_t *, regmatch_t *, char *, char *, char *, char *);
 
 /*
  * rep_add()
  *     parses the -s replacement string; compiles the regular expression
  *     and stores the compiled value and it's replacement string together in
  *     replacement string list. Input to this function is of the form:
- *             /old/new/pg 
+ *             /old/new/pg
  *     The first char in the string specifies the delimiter used by this
  *     replacement string. "Old" is a regular expression in "ed" format which
  *     is compiled by regcomp() and is applied to filenames. "new" is the
@@ -104,22 +92,14 @@ static int resub __P((regex_t *, regmatch_t *, char *, char *, char *));
  *     the list of replacement patterns; -1 otherwise.
  */
 
-#ifdef __STDC__
 int
-rep_add(register char *str)
-#else
-int
-rep_add(str)
-       register char *str;
-#endif
+rep_add(char *str)
 {
-       register char *pt1;
-       register char *pt2;
-       register REPLACE *rep;
-#      ifndef NET2_REGEX
-       register int res;
+       char *pt1;
+       char *pt2;
+       REPLACE *rep;
+       int res;
        char rebuf[BUFSIZ];
-#      endif
 
        /*
         * throw out the bad parameters
@@ -133,7 +113,15 @@ rep_add(str)
         * first character in the string specifies what the delimiter is for
         * this expression
         */
-       if ((pt1 = strchr(str+1, *str)) == NULL) {
+       for (pt1 = str+1; *pt1; pt1++) {
+               if (*pt1 == '\\') {
+                       pt1++;
+                       continue;
+               }
+               if (*pt1 == *str)
+                       break;
+       }
+       if (*pt1 == '\0') {
                paxwarn(1, "Invalid replacement string %s", str);
                return(-1);
        }
@@ -148,13 +136,9 @@ rep_add(str)
        }
 
        *pt1 = '\0';
-#      ifdef NET2_REGEX
-       if ((rep->rcmp = regcomp(str+1)) == NULL) {
-#      else
        if ((res = regcomp(&(rep->rcmp), str+1, 0)) != 0) {
                regerror(res, &(rep->rcmp), rebuf, sizeof(rebuf));
                paxwarn(1, "%s while compiling regular expression %s", rebuf, str);
-#      endif
                (void)free((char *)rep);
                return(-1);
        }
@@ -165,12 +149,16 @@ rep_add(str)
         * we then point the node at the new substitution string
         */
        *pt1++ = *str;
-       if ((pt2 = strchr(pt1, *str)) == NULL) {
-#              ifdef NET2_REGEX
-               (void)free((char *)rep->rcmp);
-#              else
+       for (pt2 = pt1; *pt2; pt2++) {
+               if (*pt2 == '\\') {
+                       pt2++;
+                       continue;
+               }
+               if (*pt2 == *str)
+                       break;
+       }
+       if (*pt2 == '\0') {
                regfree(&(rep->rcmp));
-#              endif
                (void)free((char *)rep);
                paxwarn(1, "Invalid replacement string %s", str);
                return(-1);
@@ -185,7 +173,7 @@ rep_add(str)
         * set the options if any
         */
        while (*pt2 != '\0') {
-               switch(*pt2) {
+               switch (*pt2) {
                case 'g':
                case 'G':
                        rep->flgs  |= GLOB;
@@ -195,11 +183,7 @@ rep_add(str)
                        rep->flgs  |= PRNT;
                        break;
                default:
-#                      ifdef NET2_REGEX
-                       (void)free((char *)rep->rcmp);
-#                      else
                        regfree(&(rep->rcmp));
-#                      endif
                        (void)free((char *)rep);
                        *pt1 = *str;
                        paxwarn(1, "Invalid replacement string option %s", str);
@@ -232,17 +216,10 @@ rep_add(str)
  *     0 if the pattern was added to the list, -1 otherwise
  */
 
-#ifdef __STDC__
 int
 pat_add(char *str, char *chdname)
-#else
-int
-pat_add(str, chdname)
-       char *str;
-       char *chdname;
-#endif
 {
-       register PATTERN *pt;
+       PATTERN *pt;
 
        /*
         * throw out the junk
@@ -284,16 +261,11 @@ pat_add(str, chdname)
  *     a selected archive member.
  */
 
-#ifdef __STDC__
 void
 pat_chk(void)
-#else
-void
-pat_chk()
-#endif
 {
-       register PATTERN *pt;
-       register int wban = 0;
+       PATTERN *pt;
+       int wban = 0;
 
        /*
         * walk down the list checking the flags to make sure MTCH was set,
@@ -318,26 +290,20 @@ pat_chk()
  *
  *     NOTE: When the -c option is used, we are called when there was no match
  *     by pat_match() (that means we did match before the inverted sense of
- *     the logic). Now this seems really strange at first, but with -c  we
- *     need to keep track of those patterns that cause a archive member to NOT
+ *     the logic). Now this seems really strange at first, but with -c we
+ *     need to keep track of those patterns that cause an archive member to NOT
  *     be selected (it found an archive member with a specified pattern)
  * Return:
  *     0 if the pattern pointed at by arcn->pat was tagged as creating a
  *     match, -1 otherwise.
  */
 
-#ifdef __STDC__
 int
-pat_sel(register ARCHD *arcn)
-#else
-int
-pat_sel(arcn)
-       register ARCHD *arcn;
-#endif
+pat_sel(ARCHD *arcn)
 {
-       register PATTERN *pt;
-       register PATTERN **ppt;
-       register int len;
+       PATTERN *pt;
+       PATTERN **ppt;
+       int len;
 
        /*
         * if no patterns just return
@@ -356,7 +322,7 @@ pat_sel(arcn)
 
        /*
         * we reach this point only when we allow a single selected match per
-        * pattern, if the pattern matches a directory and we do not have -d 
+        * pattern, if the pattern matches a directory and we do not have -d
         * (dflag) we are done with this pattern. We may also be handed a file
         * in the subtree of a directory. in that case when we are operating
         * with -d, this pattern was already selected and we are done
@@ -415,7 +381,7 @@ pat_sel(arcn)
         * we are then done with this pattern, so we delete it from the list
         * because it can never be used for another match.
         * Seems kind of strange to do for a -c, but the pax spec is really
-        * vague on the interaction of -c -n and -d. We assume that when -c
+        * vague on the interaction of -c, -n and -d. We assume that when -c
         * and the pattern rejects a member (i.e. it matched it) it is done.
         * In effect we place the order of the flags as having -c last.
         */
@@ -430,7 +396,7 @@ pat_sel(arcn)
                /*
                 * should never happen....
                 */
-               paxwarn(1, "Pattern list inconsistant");
+               paxwarn(1, "Pattern list inconsistent");
                return(-1);
        }
        *ppt = pt->fow;
@@ -446,21 +412,15 @@ pat_sel(arcn)
  *     this archive member is "selected" we process and mark the pattern as
  *     one which matched a selected archive member (see pat_sel())
  * Return:
- *     0 if this archive member should be processed, 1 if it should be 
+ *     0 if this archive member should be processed, 1 if it should be
  *     skipped and -1 if we are done with all patterns (and pax should quit
  *     looking for more members)
  */
 
-#ifdef __STDC__
-int
-pat_match(register ARCHD *arcn)
-#else
 int
-pat_match(arcn)
-       register ARCHD *arcn;
-#endif
+pat_match(ARCHD *arcn)
 {
-       register PATTERN *pt;
+       PATTERN *pt;
 
        arcn->pat = NULL;
 
@@ -523,24 +483,16 @@ pat_match(arcn)
 /*
  * fn_match()
  * Return:
- *     0 if this archive member should be processed, 1 if it should be 
+ *     0 if this archive member should be processed, 1 if it should be
  *     skipped and -1 if we are done with all patterns (and pax should quit
  *     looking for more members)
  *     Note: *pend may be changed to show where the prefix ends.
  */
 
-#ifdef __STDC__
-static int
-fn_match(register char *pattern, register char *string, char **pend)
-#else
 static int
-fn_match(pattern, string, pend)
-       register char *pattern;
-       register char *string;
-       char **pend;
-#endif
+fn_match(char *pattern, char *string, char **pend)
 {
-       register char c;
+       char c;
        char test;
 
        *pend = NULL;
@@ -572,7 +524,7 @@ fn_match(pattern, string, pend)
                case '*':
                        c = *pattern;
                        /*
-                        * Collapse multiple *'s. 
+                        * Collapse multiple *'s.
                         */
                        while (c == '*')
                                c = *++pattern;
@@ -610,18 +562,11 @@ fn_match(pattern, string, pend)
        /* NOTREACHED */
 }
 
-#ifdef __STDC__
-static char *
-range_match(register char *pattern, register int test)
-#else
 static char *
-range_match(pattern, test)
-       register char *pattern;
-       register int test;
-#endif
+range_match(char *pattern, int test)
 {
-       register char c;
-       register char c2;
+       char c;
+       char c2;
        int negate;
        int ok = 0;
 
@@ -657,25 +602,19 @@ range_match(pattern, test)
  *     if we spot any file links to the old file name in the future, we will
  *     know exactly how to fix the file link.
  * Return:
- *     0 continue to  process file, 1 skip this file, -1 pax is finished 
+ *     0 continue to  process file, 1 skip this file, -1 pax is finished
  */
 
-#ifdef __STDC__
-int
-mod_name(register ARCHD *arcn)
-#else
 int
-mod_name(arcn)
-       register ARCHD *arcn;
-#endif
+mod_name(ARCHD *arcn)
 {
-       register int res = 0;
+       int res = 0;
 
        /*
         * Strip off leading '/' if appropriate.
         * Currently, this option is only set for the tar format.
         */
-       if (rmleadslash && arcn->name[0] == '/') {
+       while (rmleadslash && arcn->name[0] == '/') {
                if (arcn->name[1] == '\0') {
                        arcn->name[0] = '.';
                } else {
@@ -688,7 +627,7 @@ mod_name(arcn)
                        paxwarn(0, "Removing leading / from absolute path names in the archive");
                }
        }
-       if (rmleadslash && arcn->ln_name[0] == '/' &&
+       while (rmleadslash && arcn->ln_name[0] == '/' &&
            (arcn->type == PAX_HLK || arcn->type == PAX_HRG)) {
                if (arcn->ln_name[1] == '\0') {
                        arcn->ln_name[0] = '.';
@@ -727,12 +666,12 @@ mod_name(arcn)
                 * we have replacement strings, modify the name and the link
                 * name if any.
                 */
-               if ((res = rep_name(arcn->name, &(arcn->nlen), 1)) != 0)
+               if ((res = rep_name(arcn->name, sizeof(arcn->name), &(arcn->nlen), 1)) != 0)
                        return(res);
 
                if (((arcn->type == PAX_SLK) || (arcn->type == PAX_HLK) ||
                    (arcn->type == PAX_HRG)) &&
-                   ((res = rep_name(arcn->ln_name, &(arcn->ln_nlen), 0)) != 0))
+                   ((res = rep_name(arcn->ln_name, sizeof(arcn->ln_name), &(arcn->ln_nlen), 0)) != 0))
                        return(res);
        }
 
@@ -759,14 +698,8 @@ mod_name(arcn)
  *     0 process this file, 1 skip this file, -1 we need to exit pax
  */
 
-#ifdef __STDC__
-static int
-tty_rename(register ARCHD *arcn)
-#else
 static int
-tty_rename(arcn)
-       register ARCHD *arcn;
-#endif
+tty_rename(ARCHD *arcn)
 {
        char tmpname[PAXPATHLEN+2];
        int res;
@@ -816,8 +749,9 @@ tty_rename(arcn)
         */
        tty_prnt("Processing continues, name changed to: %s\n", tmpname);
        res = add_name(arcn->name, arcn->nlen, tmpname);
-       arcn->nlen = l_strncpy(arcn->name, tmpname, sizeof(arcn->name) - 1);
-       arcn->name[arcn->nlen] = '\0';
+       arcn->nlen = strlcpy(arcn->name, tmpname, sizeof(arcn->name));
+       if (arcn->nlen >= sizeof(arcn->name))
+               arcn->nlen = sizeof(arcn->name) - 1; /* XXX truncate? */
        if (res < 0)
                return(-1);
        return(0);
@@ -831,16 +765,8 @@ tty_rename(arcn)
  *     0 if ok, -1 if failure (name too long)
  */
 
-#ifdef __STDC__
-int
-set_dest(register ARCHD *arcn, char *dest_dir, int dir_len)
-#else
 int
-set_dest(arcn, dest_dir, dir_len)
-       register ARCHD *arcn;
-       char *dest_dir;
-       int dir_len;
-#endif
+set_dest(ARCHD *arcn, char *dest_dir, int dir_len)
 {
        if (fix_path(arcn->name, &(arcn->nlen), dest_dir, dir_len) < 0)
                return(-1);
@@ -866,21 +792,12 @@ set_dest(arcn, dest_dir, dir_len)
  *     0 if ok, -1 if the final name is too long
  */
 
-#ifdef __STDC__
-static int
-fix_path( char *or_name, int *or_len, char *dir_name, int dir_len)
-#else
 static int
-fix_path(or_name, or_len, dir_name, dir_len)
-       char *or_name;
-       int *or_len;
-       char *dir_name;
-       int dir_len;
-#endif
+fix_path(char *or_name, int *or_len, char *dir_name, int dir_len)
 {
-       register char *src;
-       register char *dest;
-       register char *start;
+       char *src;
+       char *dest;
+       char *start;
        int len;
 
        /*
@@ -903,7 +820,7 @@ fix_path(or_name, or_len, dir_name, dir_len)
        *or_len = len;
 
        /*
-        * enough space, shift 
+        * enough space, shift
         */
        while (src >= start)
                *dest-- = *src--;
@@ -930,6 +847,7 @@ fix_path(or_name, or_len, dir_name, dir_len)
  *     --Parameters--
  *     name is the file name we are going to apply the regular expressions to
  *     (and may be modified)
+ *     nsize is the size of the name buffer.
  *     nlen is the length of this name (and is modified to hold the length of
  *     the final string).
  *     prnt is a flag that says whether to print the final result.
@@ -938,27 +856,17 @@ fix_path(or_name, or_len, dir_name, dir_len)
  *     ended up empty)
  */
 
-#ifdef __STDC__
 static int
-rep_name(char *name, int *nlen, int prnt)
-#else
-static int
-rep_name(name, nlen, prnt)
-       char *name;
-       int *nlen;
-       int prnt;
-#endif
+rep_name(char *name, size_t nsize, int *nlen, int prnt)
 {
-       register REPLACE *pt;
-       register char *inpt;
-       register char *outpt;
-       register char *endpt;
-       register char *rpt;
-       register int found = 0;
-       register int res;
-#      ifndef NET2_REGEX
+       REPLACE *pt;
+       char *inpt;
+       char *outpt;
+       char *endpt;
+       char *rpt;
+       int found = 0;
+       int res;
        regmatch_t pm[MAXSUBEXP];
-#      endif
        char nname[PAXPATHLEN+1];       /* final result of all replacements */
        char buf1[PAXPATHLEN+1];        /* where we work on the name */
 
@@ -971,7 +879,7 @@ rep_name(name, nlen, prnt)
         * (the user already saw that substitution go by)
         */
        pt = rephead;
-       (void)strcpy(buf1, name);
+       (void)strlcpy(buf1, name, sizeof(buf1));
        inpt = buf1;
        outpt = nname;
        endpt = outpt + PAXPATHLEN;
@@ -981,15 +889,12 @@ rep_name(name, nlen, prnt)
         */
        while (pt != NULL) {
                do {
+                       char *oinpt = inpt;
                        /*
                         * check for a successful substitution, if not go to
                         * the next pattern, or cleanup if we were global
                         */
-#                      ifdef NET2_REGEX
-                       if (regexec(pt->rcmp, inpt) == 0)
-#                      else
                        if (regexec(&(pt->rcmp), inpt, MAXSUBEXP, pm, 0) != 0)
-#                      endif
                                break;
 
                        /*
@@ -1000,11 +905,7 @@ rep_name(name, nlen, prnt)
                         * do not create a string too long).
                         */
                        found = 1;
-#                      ifdef NET2_REGEX
-                       rpt = pt->rcmp->startp[0];
-#                      else
                        rpt = inpt + pm[0].rm_so;
-#                      endif
 
                        while ((inpt < rpt) && (outpt < endpt))
                                *outpt++ = *inpt++;
@@ -1017,12 +918,8 @@ rep_name(name, nlen, prnt)
                         * replacement string and place it the prefix in the
                         * final output. If we have problems, skip it.
                         */
-#                      ifdef NET2_REGEX
-                       if ((res = resub(pt->rcmp,pt->nstr,outpt,endpt)) < 0) {
-#                      else
-                       if ((res = resub(&(pt->rcmp),pm,pt->nstr,outpt,endpt))
+                       if ((res = resub(&(pt->rcmp),pm,pt->nstr,oinpt,outpt,endpt))
                            < 0) {
-#                      endif
                                if (prnt)
                                        paxwarn(1, "Replacement name error %s",
                                            name);
@@ -1040,11 +937,7 @@ rep_name(name, nlen, prnt)
                         * the final result. Make sure we do not overrun the
                         * output buffer
                         */
-#                      ifdef NET2_REGEX
-                       inpt = pt->rcmp->endp[0];
-#                      else
                        inpt += pm[0].rm_eo - pm[0].rm_so;
-#                      endif
 
                        if ((outpt == endpt) || (*inpt == '\0'))
                                break;
@@ -1097,98 +990,28 @@ rep_name(name, nlen, prnt)
                 */
                if (*nname == '\0')
                        return(1);
-               *nlen = l_strncpy(name, nname, PAXPATHLEN + 1);
-               name[PAXPATHLEN] = '\0';
+               *nlen = strlcpy(name, nname, nsize);
        }
        return(0);
 }
 
-#ifdef NET2_REGEX
-/*
- * resub()
- *     apply the replacement to the matched expression. expand out the old
- *     style ed(1) subexpression expansion.
- * Return:
- *     -1 if error, or the number of characters added to the destination.
- */
-
-#ifdef __STDC__
-static int
-resub(regexp *prog, char *src, char *dest, register char *destend)
-#else
-static int
-resub(prog, src, dest, destend)
-       regexp *prog;
-       char *src;
-       char *dest;
-       register char *destend;
-#endif
-{
-       register char *spt;
-       register char *dpt;
-       register char c;
-       register int no;
-       register int len;
-
-       spt = src;
-       dpt = dest;
-       while ((dpt < destend) && ((c = *spt++) != '\0')) {
-               if (c == '&')
-                       no = 0;
-               else if ((c == '\\') && (*spt >= '0') && (*spt <= '9'))
-                       no = *spt++ - '0';
-               else {
-                       if ((c == '\\') && ((*spt == '\\') || (*spt == '&')))
-                               c = *spt++;
-                       *dpt++ = c;
-                       continue;
-               }
-               if ((prog->startp[no] == NULL) || (prog->endp[no] == NULL) ||
-                   ((len = prog->endp[no] - prog->startp[no]) <= 0))
-                       continue;
-
-               /*
-                * copy the subexpression to the destination.
-                * fail if we run out of space or the match string is damaged
-                */
-               if (len > (destend - dpt))
-                       len = destend - dpt;
-               if (l_strncpy(dpt, prog->startp[no], len) != len)
-                       return(-1);
-               dpt += len;
-       }
-       return(dpt - dest);
-}
-
-#else
-
 /*
  * resub()
  *     apply the replacement to the matched expression. expand out the old
- *     style ed(1) subexpression expansion.
+ *     style ed(1) subexpression expansion.
  * Return:
  *     -1 if error, or the number of characters added to the destination.
  */
 
-#ifdef __STDC__
-static int
-resub(regex_t *rp, register regmatch_t *pm, char *src, char *dest,
-       register char *destend)
-#else
 static int
-resub(rp, pm, src, dest, destend)
-       regex_t *rp;
-       register regmatch_t *pm;
-       char *src;
-       char *dest;
-       register char *destend;
-#endif
+resub(regex_t *rp, regmatch_t *pm, char *src, char *inpt, char *dest,
+       char *destend)
 {
-       register char *spt;
-       register char *dpt;
-       register char c;
-       register regmatch_t *pmpt;
-       register int len;
+       char *spt;
+       char *dpt;
+       char c;
+       regmatch_t *pmpt;
+       int len;
        int subexcnt;
 
        spt =  src;
@@ -1209,12 +1032,12 @@ resub(rp, pm, src, dest, destend)
                                return(-1);
                        pmpt = pm + len;
                } else {
-                       /*
+                       /*
                         * Ordinary character, just copy it
                         */
-                       if ((c == '\\') && ((*spt == '\\') || (*spt == '&')))
-                               c = *spt++;
-                       *dpt++ = c;
+                       if ((c == '\\') && (*spt != '\0'))
+                               c = *spt++;
+                       *dpt++ = c;
                        continue;
                }
 
@@ -1230,11 +1053,9 @@ resub(rp, pm, src, dest, destend)
                 * fail if we run out of space or the match string is damaged
                 */
                if (len > (destend - dpt))
-                       len = destend - dpt;
-               if (l_strncpy(dpt, src + pmpt->rm_so, len) != len)
-                       return(-1);
+                       return (-1);
+               strncpy(dpt, inpt + pmpt->rm_so, len);
                dpt += len;
        }
        return(dpt - dest);
 }
-#endif