-/* $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 */
#include <compat.h>
#include "emul/glob.h"
+#include "emul/charclass.h"
#define DOLLAR '$'
#define DOT '.'
#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 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 *));
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;
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;
* 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;
/*
* Expand a ~user
*/
- if ((pwd = getpwnam((char*) patbuf)) == NULL)
+ if ((pwd = sudo_getpwnam((char*) patbuf)) == NULL)
return pattern;
else
h = pwd->pw_dir;
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
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;
*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) {
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;
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);
}