patch from upstream for prompting problem when no tty associated with sudo
[debian/sudo] / glob.c
diff --git a/glob.c b/glob.c
index 3c32e053bb80b16e0be0962d6405c63f8b1ad3eb..9673626531776c465f47e40f3efd9cb33d099e96 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-2010 Todd C. Miller <Todd.Miller@courtesan.com>
  * Copyright (c) 1989, 1993
  *     The Regents of the University of California.  All rights reserved.
  *
 #endif /* HAVE_MALLOC_H && !STDC_HEADERS */
 #ifdef HAVE_STRING_H
 # include <string.h>
-#else
-# ifdef HAVE_STRINGS_H
-#  include <strings.h>
-# endif
 #endif /* HAVE_STRING_H */
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif /* HAVE_STRINGS_H */
 #ifdef HAVE_UNISTD_H
 # include <unistd.h>
 #endif /* HAVE_UNISTD_H */
@@ -99,6 +97,7 @@
 
 #include <compat.h>
 #include "emul/glob.h"
+#include "emul/charclass.h"
 
 #define        DOLLAR          '$'
 #define        DOT             '.'
 #define        M_MASK          0xffff
 #define        M_ASCII         0x00ff
 
-typedef u_short Char;
+typedef unsigned short Char;
 
 #else
 
@@ -147,14 +146,16 @@ 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)
 
 
 static int      compare __P((const void *, const void *));
-static int      g_Ctoc __P((const Char *, char *, u_int));
+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,17 +173,20 @@ 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;
        int flags, (*errfunc) __P((const char *, int));
        glob_t *pglob;
 {
-       const u_char *patnext;
+       const unsigned char *patnext;
        int c;
        Char *bufnext, *bufend, patbuf[PATH_MAX];
 
-       patnext = (u_char *) pattern;
+       patnext = (unsigned char *) pattern;
        if (!(flags & GLOB_APPEND)) {
                pglob->gl_pathc = 0;
                pglob->gl_pathv = NULL;
@@ -235,7 +239,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 +389,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 +398,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 +416,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 +491,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 +502,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) {
@@ -627,14 +691,14 @@ glob3(pathbuf, pathbuf_last, pathend, pathend_last, pattern, pattern_last,
 
        /* Search directory for matching names. */
        while ((dp = readdir(dirp))) {
-               u_char *sc;
+               unsigned char *sc;
                Char *dc;
 
                /* Initial DOT must be matched literally. */
                if (dp->d_name[0] == DOT && *pattern != DOT)
                        continue;
                dc = pathend;
-               sc = (u_char *) dp->d_name;
+               sc = (unsigned char *) dp->d_name;
                while (dc < pathend_last && (*dc++ = *sc++) != EOS)
                        continue;
                if (dc >= pathend_last) {
@@ -678,7 +742,7 @@ globextend(path, pglob)
 {
        char **pathv;
        int i;
-       u_int newsize, len;
+       unsigned int newsize, len;
        char *copy;
        const Char *p;
 
@@ -749,13 +813,21 @@ match(name, pat, patend)
                                return(0);
                        if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS)
                                ++pat;
-                       while (((c = *pat++) & M_MASK) != M_END)
+                       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;
                                        pat += 2;
                                } else if (c == k)
                                        ok = 1;
+                       }
                        if (ok == negate_range)
                                return(0);
                        break;
@@ -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);
 }
@@ -845,7 +917,7 @@ static int
 g_Ctoc(str, buf, len)
        const Char *str;
        char *buf;
-       u_int len;
+       unsigned int len;
 {
 
        while (len--) {