Imported Upstream version 1.7.0
[debian/sudo] / glob.c
diff --git a/glob.c b/glob.c
index 5319c130c306a74c1131a7f6018b697e5c5906bf..46d883b085d86fd4d893241af63c4cd903403e2b 100644 (file)
--- a/glob.c
+++ b/glob.c
@@ -1,6 +1,5 @@
-/*     $OpenBSD: glob.c,v 1.23 2004/05/18 02:05:52 jfb Exp $   */
-
 /*
+ * Copyright (c) 2008 Todd C. Miller <Todd.Miller@courtesan.com>
  * Copyright (c) 1989, 1993
  *     The Regents of the University of California.  All rights reserved.
  *
@@ -99,6 +98,7 @@
 
 #include <compat.h>
 #include "emul/glob.h"
+#include "emul/charclass.h"
 
 #define        DOLLAR          '$'
 #define        DOT             '.'
@@ -147,6 +147,7 @@ typedef char Char;
 #define        M_ONE           META('?')
 #define        M_RNG           META('-')
 #define        M_SET           META('[')
+#define        M_CLASS         META(':')
 #define        ismeta(c)       (((c)&M_QUOTE) != 0)
 
 
@@ -154,7 +155,8 @@ static int   compare __P((const void *, const void *));
 static int      g_Ctoc __P((const Char *, char *, unsigned int));
 static int      g_lstat __P((Char *, struct stat *, glob_t *));
 static DIR     *g_opendir __P((Char *, glob_t *));
-static Char    *g_strchr __P((Char *, int));
+static Char    *g_strchr __P((const Char *, int));
+static int      g_strncmp __P((const Char *, const char *, size_t));
 static int      g_stat __P((Char *, struct stat *, glob_t *));
 static int      glob0 __P((const Char *, glob_t *));
 static int      glob1 __P((Char *, Char *, glob_t *));
@@ -172,6 +174,9 @@ static int   match __P((Char *, Char *, Char *));
 static void     qprintf __P((const char *, Char *));
 #endif
 
+extern struct passwd *sudo_getpwnam __P((const char *));
+extern struct passwd *sudo_getpwuid __P((uid_t));
+
 int
 glob(pattern, flags, errfunc, pglob)
        const char *pattern;
@@ -235,7 +240,7 @@ globexp1(pattern, pglob)
        if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS)
                return glob0(pattern, pglob);
 
-       while ((ptr = (const Char *) g_strchr((Char *) ptr, LBRACE)) != NULL)
+       while ((ptr = (const Char *) g_strchr(ptr, LBRACE)) != NULL)
                if (!globexp2(ptr, pattern, pglob, &rv))
                        return rv;
 
@@ -385,7 +390,7 @@ globtilde(pattern, patbuf, patbuf_len, pglob)
                 * first and then trying the password file
                 */
                if ((h = getenv("HOME")) == NULL) {
-                       if ((pwd = getpwuid(getuid())) == NULL)
+                       if ((pwd = sudo_getpwuid(getuid())) == NULL)
                                return pattern;
                        else
                                h = pwd->pw_dir;
@@ -394,7 +399,7 @@ globtilde(pattern, patbuf, patbuf_len, pglob)
                /*
                 * Expand a ~user
                 */
-               if ((pwd = getpwnam((char*) patbuf)) == NULL)
+               if ((pwd = sudo_getpwnam((char*) patbuf)) == NULL)
                        return pattern;
                else
                        h = pwd->pw_dir;
@@ -412,6 +417,52 @@ globtilde(pattern, patbuf, patbuf_len, pglob)
        return patbuf;
 }
 
+static int
+g_strncmp(s1, s2, n)
+       const Char *s1;
+       const char *s2;
+       size_t n;
+{
+       int rv = 0;
+
+       while (n--) {
+               rv = *(Char *)s1 - *(const unsigned char *)s2++;
+               if (rv)
+                       break;
+               if (*s1++ == '\0')
+                       break;
+       }
+       return rv;
+}
+
+static int
+g_charclass(patternp, bufnextp)
+       const Char **patternp;
+       Char **bufnextp;
+{
+       const Char *pattern = *patternp + 1;
+       Char *bufnext = *bufnextp;
+       const Char *colon;
+       struct cclass *cc;
+       size_t len;
+
+       if ((colon = g_strchr(pattern, ':')) == NULL || colon[1] != ']')
+               return 1;       /* not a character class */
+
+       len = (size_t)(colon - pattern);
+       for (cc = cclasses; cc->name != NULL; cc++) {
+               if (!g_strncmp(pattern, cc->name, len) && cc->name[len] == '\0')
+                       break;
+       }
+       if (cc->name == NULL)
+               return -1;      /* invalid character class */
+       *bufnext++ = M_CLASS;
+       *bufnext++ = (Char)(cc - &cclasses[0]);
+       *bufnextp = bufnext;
+       *patternp += len + 3;
+
+       return 0;
+}
 
 /*
  * The main glob() routine: compiles the pattern (optionally processing
@@ -441,7 +492,7 @@ glob0(pattern, pglob)
                        if (c == NOT)
                                ++qpatnext;
                        if (*qpatnext == EOS ||
-                           g_strchr((Char *) qpatnext+1, RBRACKET) == NULL) {
+                           g_strchr(qpatnext+1, RBRACKET) == NULL) {
                                *bufnext++ = LBRACKET;
                                if (c == NOT)
                                        --qpatnext;
@@ -452,6 +503,20 @@ glob0(pattern, pglob)
                                *bufnext++ = M_NOT;
                        c = *qpatnext++;
                        do {
+                               if (c == LBRACKET && *qpatnext == ':') {
+                                       do {
+                                               err = g_charclass(&qpatnext,
+                                                   &bufnext);
+                                               if (err)
+                                                       break;
+                                               c = *qpatnext++;
+                                       } while (c == LBRACKET && *qpatnext == ':');
+                                       if (err == -1 &&
+                                           !(pglob->gl_flags & GLOB_NOCHECK))
+                                               return GLOB_NOMATCH;
+                                       if (c == RBRACKET)
+                                               break;
+                               }
                                *bufnext++ = CHAR(c);
                                if (*qpatnext == RANGE &&
                                    (c = qpatnext[1]) != RBRACKET) {
@@ -750,6 +815,13 @@ match(name, pat, patend)
                        if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS)
                                ++pat;
                        while (((c = *pat++) & M_MASK) != M_END)
+                               if ((c & M_MASK) == M_CLASS) {
+                                       int idx = *pat & M_MASK;
+                                       if (idx < NCCLASSES &&
+                                           cclasses[idx].isctype(k))
+                                               ok = 1;
+                                       ++pat;
+                               }
                                if ((*pat & M_MASK) == M_RNG) {
                                        if (c <= k && k <= pat[1])
                                                ok = 1;
@@ -831,12 +903,12 @@ g_stat(fn, sb, pglob)
 
 static Char *
 g_strchr(str, ch)
-       Char *str;
+       const Char *str;
        int ch;
 {
        do {
                if (*str == ch)
-                       return (str);
+                       return ((Char *)str);
        } while (*str++);
        return (NULL);
 }