169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban/*	$NetBSD: glob.c,v 1.35 2013/03/20 23:44:47 lukem Exp $	*/
269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban/*
469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * Copyright (c) 1989, 1993
569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban *	The Regents of the University of California.  All rights reserved.
669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban *
769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * This code is derived from software contributed to Berkeley by
869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * Guido van Rossum.
969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban *
1069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * Redistribution and use in source and binary forms, with or without
1169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * modification, are permitted provided that the following conditions
1269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * are met:
1369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * 1. Redistributions of source code must retain the above copyright
1469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban *    notice, this list of conditions and the following disclaimer.
1569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * 2. Redistributions in binary form must reproduce the above copyright
1669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban *    notice, this list of conditions and the following disclaimer in the
1769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban *    documentation and/or other materials provided with the distribution.
1869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * 3. Neither the name of the University nor the names of its contributors
1969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban *    may be used to endorse or promote products derived from this software
2069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban *    without specific prior written permission.
2169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban *
2269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * SUCH DAMAGE.
3369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban */
3469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
3569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#include <sys/cdefs.h>
3669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#if defined(LIBC_SCCS) && !defined(lint)
3769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#if 0
3869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanstatic char sccsid[] = "@(#)glob.c	8.3 (Berkeley) 10/13/93";
3969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#else
4069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban__RCSID("$NetBSD: glob.c,v 1.35 2013/03/20 23:44:47 lukem Exp $");
4169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#endif
4269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#endif /* LIBC_SCCS and not lint */
4369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
4469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban/*
4569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * glob(3) -- a superset of the one defined in POSIX 1003.2.
4669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban *
4769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * The [!...] convention to negate a range is supported (SysV, Posix, ksh).
4869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban *
4969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * Optional extra services, controlled by flags not defined by POSIX:
5069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban *
5169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * GLOB_MAGCHAR:
5269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban *	Set in gl_flags if pattern contained a globbing character.
5369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * GLOB_NOMAGIC:
5469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban *	Same as GLOB_NOCHECK, but it will only append pattern if it did
5569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban *	not contain any magic characters.  [Used in csh style globbing]
5669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * GLOB_ALTDIRFUNC:
5769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban *	Use alternately specified directory access functions.
5869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * GLOB_TILDE:
5969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban *	expand ~user/foo to the /home/dir/of/user/foo
6069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * GLOB_BRACE:
6169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban *	expand {1,2}{a,b} to 1a 1b 2a 2b
6269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * GLOB_PERIOD:
6369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban *	allow metacharacters to match leading dots in filenames.
6469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * GLOB_NO_DOTDIRS:
6569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban *	. and .. are hidden from wildcards, even if GLOB_PERIOD is set.
6669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * gl_matchc:
6769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban *	Number of matches in the current invocation of glob.
6869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban */
6969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
7069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban//#include "namespace.h"
7169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#include <sys/param.h>
7269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#include <sys/stat.h>
7369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
7469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#include <assert.h>
7569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#include <ctype.h>
7669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#include <dirent.h>
7769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#include <errno.h>
7869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#include <glob.h>
7969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#include <pwd.h>
8069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#include <stdio.h>
8169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#include <stddef.h>
8269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#include <stdlib.h>
8369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#include <string.h>
8469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#include <unistd.h>
8569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
8669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#ifdef HAVE_NBTOOL_CONFIG_H
8769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#define NO_GETPW_R
8869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#endif
8969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
9069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#define	GLOB_LIMIT_STRING	65536	/* number of readdirs */
9169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#define	GLOB_LIMIT_STAT		128	/* number of stat system calls */
9269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#define	GLOB_LIMIT_READDIR	16384	/* total buffer size of path strings */
9369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#define	GLOB_LIMIT_PATH		1024	/* number of path elements */
9469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#define GLOB_LIMIT_BRACE	128	/* Number of brace calls */
9569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
9669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanstruct glob_limit {
9769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	size_t l_string;
9869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	size_t l_stat;
9969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	size_t l_readdir;
10069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	size_t l_brace;
10169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban};
10269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
10369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban/*
10469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * XXX: For NetBSD 1.4.x compatibility. (kill me l8r)
10569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban */
10669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#ifndef _DIAGASSERT
10769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#define _DIAGASSERT(a)
10869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#endif
10969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
11069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#define	DOLLAR		'$'
11169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#define	DOT		'.'
11269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#define	EOS		'\0'
11369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#define	LBRACKET	'['
11469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#define	NOT		'!'
11569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#define	QUESTION	'?'
11669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#define	QUOTE		'\\'
11769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#define	RANGE		'-'
11869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#define	RBRACKET	']'
11969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#define	SEP		'/'
12069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#define	STAR		'*'
12169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#define	TILDE		'~'
12269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#define	UNDERSCORE	'_'
12369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#define	LBRACE		'{'
12469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#define	RBRACE		'}'
12569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#define	SLASH		'/'
12669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#define	COMMA		','
12769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
12869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#ifndef USE_8BIT_CHARS
12969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
13069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#define	M_QUOTE		0x8000
13169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#define	M_PROTECT	0x4000
13269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#define	M_MASK		0xffff
13369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#define	M_ASCII		0x00ff
13469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
13569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbantypedef unsigned short Char;
13669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
13769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#else
13869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
13969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#define	M_QUOTE		(Char)0x80
14069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#define	M_PROTECT	(Char)0x40
14169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#define	M_MASK		(Char)0xff
14269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#define	M_ASCII		(Char)0x7f
14369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
14469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbantypedef char Char;
14569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
14669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#endif
14769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
14869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
14969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#define	CHAR(c)		((Char)((c)&M_ASCII))
15069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#define	META(c)		((Char)((c)|M_QUOTE))
15169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#define	M_ALL		META('*')
15269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#define	M_END		META(']')
15369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#define	M_NOT		META('!')
15469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#define	M_ONE		META('?')
15569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#define	M_RNG		META('-')
15669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#define	M_SET		META('[')
15769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#define	ismeta(c)	(((c)&M_QUOTE) != 0)
15869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
15969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
16069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanstatic int	 compare(const void *, const void *);
16169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanstatic int	 g_Ctoc(const Char *, char *, size_t);
16269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanstatic int	 g_lstat(Char *, __gl_stat_t  *, glob_t *);
16369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanstatic DIR	*g_opendir(Char *, glob_t *);
16469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanstatic Char	*g_strchr(const Char *, int);
16569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanstatic int	 g_stat(Char *, __gl_stat_t *, glob_t *);
16669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanstatic int	 glob0(const Char *, glob_t *, struct glob_limit *);
16769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanstatic int	 glob1(Char *, glob_t *, struct glob_limit *);
16869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanstatic int	 glob2(Char *, Char *, Char *, const Char *, glob_t *,
16969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban    struct glob_limit *);
17069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanstatic int	 glob3(Char *, Char *, Char *, const Char *, const Char *,
17169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban    const Char *, glob_t *, struct glob_limit *);
17269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanstatic int	 globextend(const Char *, glob_t *, struct glob_limit *);
17369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanstatic const Char *globtilde(const Char *, Char *, size_t, glob_t *);
17469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanstatic int	 globexp1(const Char *, glob_t *, struct glob_limit *);
17569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanstatic int	 globexp2(const Char *, const Char *, glob_t *, int *,
17669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban    struct glob_limit *);
17769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanstatic int	 match(const Char *, const Char *, const Char *);
17869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#ifdef DEBUG
17969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanstatic void	 qprintf(const char *, Char *);
18069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#endif
18169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
18269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanint
18369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanglob(const char * __restrict pattern, int flags, int (*errfunc)(const char *,
18469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban    int), glob_t * __restrict pglob)
18569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban{
18669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	const unsigned char *patnext;
18769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	int c;
18869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	Char *bufnext, *bufend, patbuf[MAXPATHLEN+1];
18969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	struct glob_limit limit = { 0, 0, 0, 0 };
19069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
19169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	_DIAGASSERT(pattern != NULL);
19269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
19369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	patnext = (const unsigned char *) pattern;
19469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	if (!(flags & GLOB_APPEND)) {
19569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		pglob->gl_pathc = 0;
19669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		pglob->gl_pathv = NULL;
19769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		if (!(flags & GLOB_DOOFFS))
19869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			pglob->gl_offs = 0;
19969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	}
20069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	pglob->gl_flags = flags & ~GLOB_MAGCHAR;
20169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	pglob->gl_errfunc = errfunc;
20269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	pglob->gl_matchc = 0;
20369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
20469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	bufnext = patbuf;
20569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	bufend = bufnext + MAXPATHLEN;
20669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	if (flags & GLOB_NOESCAPE) {
20769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		while (bufnext < bufend && (c = *patnext++) != EOS)
20869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			*bufnext++ = c;
20969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	} else {
21069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		/* Protect the quoted characters. */
21169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		while (bufnext < bufend && (c = *patnext++) != EOS)
21269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			if (c == QUOTE) {
21369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				if ((c = *patnext++) == EOS) {
21469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban					c = QUOTE;
21569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban					--patnext;
21669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				}
21769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				*bufnext++ = c | M_PROTECT;
21869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			}
21969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			else
22069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				*bufnext++ = c;
22169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	}
22269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	*bufnext = EOS;
22369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
22469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	if (flags & GLOB_BRACE)
22569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	    return globexp1(patbuf, pglob, &limit);
22669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	else
22769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	    return glob0(patbuf, pglob, &limit);
22869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban}
22969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
23069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban/*
23169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * Expand recursively a glob {} pattern. When there is no more expansion
23269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * invoke the standard globbing routine to glob the rest of the magic
23369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * characters
23469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban */
23569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanstatic int
23669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanglobexp1(const Char *pattern, glob_t *pglob, struct glob_limit *limit)
23769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban{
23869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	const Char* ptr = pattern;
23969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	int rv;
24069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
24169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	_DIAGASSERT(pattern != NULL);
24269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	_DIAGASSERT(pglob != NULL);
24369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
24469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	if ((pglob->gl_flags & GLOB_LIMIT) &&
24569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	    limit->l_brace++ >= GLOB_LIMIT_BRACE) {
24669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		errno = 0;
24769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		return GLOB_NOSPACE;
24869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	}
24969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
25069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	/* Protect a single {}, for find(1), like csh */
25169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS)
25269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		return glob0(pattern, pglob, limit);
25369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
25469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	while ((ptr = (const Char *) g_strchr(ptr, LBRACE)) != NULL)
25569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		if (!globexp2(ptr, pattern, pglob, &rv, limit))
25669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			return rv;
25769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
25869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	return glob0(pattern, pglob, limit);
25969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban}
26069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
26169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
26269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban/*
26369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * Recursive brace globbing helper. Tries to expand a single brace.
26469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * If it succeeds then it invokes globexp1 with the new pattern.
26569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * If it fails then it tries to glob the rest of the pattern and returns.
26669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban */
26769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanstatic int
26869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanglobexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv,
26969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban    struct glob_limit *limit)
27069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban{
27169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	int     i;
27269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	Char   *lm, *ls;
27369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	const Char *pe, *pm, *pl;
27469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	Char    patbuf[MAXPATHLEN + 1];
27569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
27669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	_DIAGASSERT(ptr != NULL);
27769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	_DIAGASSERT(pattern != NULL);
27869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	_DIAGASSERT(pglob != NULL);
27969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	_DIAGASSERT(rv != NULL);
28069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
28169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	/* copy part up to the brace */
28269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++)
28369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		continue;
28469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	ls = lm;
28569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
28669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	/* Find the balanced brace */
28769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	for (i = 0, pe = ++ptr; *pe; pe++)
28869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		if (*pe == LBRACKET) {
28969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			/* Ignore everything between [] */
29069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			for (pm = pe++; *pe != RBRACKET && *pe != EOS; pe++)
29169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				continue;
29269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			if (*pe == EOS) {
29369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				/*
29469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				 * We could not find a matching RBRACKET.
29569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				 * Ignore and just look for RBRACE
29669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				 */
29769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				pe = pm;
29869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			}
29969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		}
30069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		else if (*pe == LBRACE)
30169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			i++;
30269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		else if (*pe == RBRACE) {
30369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			if (i == 0)
30469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				break;
30569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			i--;
30669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		}
30769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
30869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	/* Non matching braces; just glob the pattern */
30969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	if (i != 0 || *pe == EOS) {
31069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		/*
31169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		 * we use `pattern', not `patbuf' here so that that
31269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		 * unbalanced braces are passed to the match
31369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		 */
31469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		*rv = glob0(pattern, pglob, limit);
31569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		return 0;
31669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	}
31769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
31869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	for (i = 0, pl = pm = ptr; pm <= pe; pm++) {
31969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		switch (*pm) {
32069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		case LBRACKET:
32169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			/* Ignore everything between [] */
32269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			for (pl = pm++; *pm != RBRACKET && *pm != EOS; pm++)
32369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				continue;
32469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			if (*pm == EOS) {
32569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				/*
32669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				 * We could not find a matching RBRACKET.
32769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				 * Ignore and just look for RBRACE
32869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				 */
32969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				pm = pl;
33069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			}
33169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			break;
33269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
33369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		case LBRACE:
33469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			i++;
33569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			break;
33669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
33769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		case RBRACE:
33869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			if (i) {
33969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				i--;
34069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				break;
34169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			}
34269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			/* FALLTHROUGH */
34369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		case COMMA:
34469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			if (i && *pm == COMMA)
34569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				break;
34669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			else {
34769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				/* Append the current string */
34869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				for (lm = ls; (pl < pm); *lm++ = *pl++)
34969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban					continue;
35069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				/*
35169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				 * Append the rest of the pattern after the
35269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				 * closing brace
35369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				 */
35469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				for (pl = pe + 1; (*lm++ = *pl++) != EOS;)
35569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban					continue;
35669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
35769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				/* Expand the current pattern */
35869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#ifdef DEBUG
35969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				qprintf("globexp2", patbuf);
36069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#endif
36169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				*rv = globexp1(patbuf, pglob, limit);
36269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
36369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				/* move after the comma, to the next string */
36469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				pl = pm + 1;
36569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			}
36669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			break;
36769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
36869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		default:
36969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			break;
37069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		}
37169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	}
37269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	*rv = 0;
37369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	return 0;
37469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban}
37569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
37669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
37769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
37869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban/*
37969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * expand tilde from the passwd file.
38069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban */
38169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanstatic const Char *
38269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanglobtilde(const Char *pattern, Char *patbuf, size_t patsize, glob_t *pglob)
38369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban{
38469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	struct passwd *pwd;
38569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	const char *h;
38669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	const Char *p;
38769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	Char *b;
38869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	char *d;
38969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	Char *pend = &patbuf[patsize / sizeof(Char)];
39069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#ifndef NO_GETPW_R
39169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	struct passwd pwres;
39269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	char pwbuf[1024];
39369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#endif
39469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
39569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	pend--;
39669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
39769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	_DIAGASSERT(pattern != NULL);
39869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	_DIAGASSERT(patbuf != NULL);
39969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	_DIAGASSERT(pglob != NULL);
40069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
40169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	if (*pattern != TILDE || !(pglob->gl_flags & GLOB_TILDE))
40269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		return pattern;
40369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
40469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	/* Copy up to the end of the string or / */
40569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	for (p = pattern + 1, d = (char *)(void *)patbuf;
40669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	     d < (char *)(void *)pend && *p && *p != SLASH;
40769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	     *d++ = *p++)
40869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		continue;
40969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
41069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	if (d == (char *)(void *)pend)
41169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		return NULL;
41269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
41369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	*d = EOS;
41469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	d = (char *)(void *)patbuf;
41569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
41669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	if (*d == EOS) {
41769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		/*
41869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		 * handle a plain ~ or ~/ by expanding $HOME
41969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		 * first and then trying the password file
42069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		 */
42169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		if ((h = getenv("HOME")) == NULL) {
42269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#ifdef NO_GETPW_R
42369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			if ((pwd = getpwuid(getuid())) == NULL)
42469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#else
42569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			if (getpwuid_r(getuid(), &pwres, pwbuf, sizeof(pwbuf),
42669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			    &pwd) != 0 || pwd == NULL)
42769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#endif
42869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				return pattern;
42969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			else
43069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				h = pwd->pw_dir;
43169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		}
43269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	}
43369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	else {
43469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		/*
43569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		 * Expand a ~user
43669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		 */
43769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#ifdef NO_GETPW_R
43869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		if ((pwd = getpwnam(d)) == NULL)
43969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#else
44069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		if (getpwnam_r(d, &pwres, pwbuf, sizeof(pwbuf), &pwd) != 0 ||
44169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		    pwd == NULL)
44269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#endif
44369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			return pattern;
44469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		else
44569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			h = pwd->pw_dir;
44669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	}
44769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
44869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	/* Copy the home directory */
44969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	for (b = patbuf; b < pend && *h; *b++ = *h++)
45069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		continue;
45169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
45269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	if (b == pend)
45369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		return NULL;
45469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
45569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	/* Append the rest of the pattern */
45669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	while (b < pend && (*b++ = *p++) != EOS)
45769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		continue;
45869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
45969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	if (b == pend)
46069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		return NULL;
46169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
46269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	return patbuf;
46369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban}
46469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
46569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
46669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban/*
46769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * The main glob() routine: compiles the pattern (optionally processing
46869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * quotes), calls glob1() to do the real pattern matching, and finally
46969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * sorts the list (unless unsorted operation is requested).  Returns 0
47069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * if things went well, nonzero if errors occurred.  It is not an error
47169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * to find no matches.
47269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban */
47369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanstatic int
47469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanglob0(const Char *pattern, glob_t *pglob, struct glob_limit *limit)
47569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban{
47669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	const Char *qpatnext;
47769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	int c, error;
47869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	__gl_size_t oldpathc;
47969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	Char *bufnext, patbuf[MAXPATHLEN+1];
48069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
48169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	_DIAGASSERT(pattern != NULL);
48269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	_DIAGASSERT(pglob != NULL);
48369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
48469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	if ((qpatnext = globtilde(pattern, patbuf, sizeof(patbuf),
48569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	    pglob)) == NULL)
48669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		return GLOB_ABEND;
48769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	oldpathc = pglob->gl_pathc;
48869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	bufnext = patbuf;
48969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
49069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	/* We don't need to check for buffer overflow any more. */
49169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	while ((c = *qpatnext++) != EOS) {
49269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		switch (c) {
49369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		case LBRACKET:
49469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			c = *qpatnext;
49569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			if (c == NOT)
49669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				++qpatnext;
49769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			if (*qpatnext == EOS ||
49869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			    g_strchr(qpatnext+1, RBRACKET) == NULL) {
49969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				*bufnext++ = LBRACKET;
50069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				if (c == NOT)
50169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban					--qpatnext;
50269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				break;
50369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			}
50469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			*bufnext++ = M_SET;
50569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			if (c == NOT)
50669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				*bufnext++ = M_NOT;
50769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			c = *qpatnext++;
50869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			do {
50969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				*bufnext++ = CHAR(c);
51069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				if (*qpatnext == RANGE &&
51169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				    (c = qpatnext[1]) != RBRACKET) {
51269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban					*bufnext++ = M_RNG;
51369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban					*bufnext++ = CHAR(c);
51469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban					qpatnext += 2;
51569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				}
51669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			} while ((c = *qpatnext++) != RBRACKET);
51769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			pglob->gl_flags |= GLOB_MAGCHAR;
51869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			*bufnext++ = M_END;
51969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			break;
52069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		case QUESTION:
52169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			pglob->gl_flags |= GLOB_MAGCHAR;
52269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			*bufnext++ = M_ONE;
52369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			break;
52469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		case STAR:
52569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			pglob->gl_flags |= GLOB_MAGCHAR;
52669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			/* collapse adjacent stars to one [or three if globstar]
52769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			 * to avoid exponential behavior
52869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			 */
52969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			if (bufnext == patbuf || bufnext[-1] != M_ALL ||
53069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			    ((pglob->gl_flags & GLOB_STAR) != 0 &&
53169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			    (bufnext - 1 == patbuf || bufnext[-2] != M_ALL ||
53269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			    bufnext - 2 == patbuf || bufnext[-3] != M_ALL)))
53369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				*bufnext++ = M_ALL;
53469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			break;
53569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		default:
53669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			*bufnext++ = CHAR(c);
53769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			break;
53869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		}
53969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	}
54069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	*bufnext = EOS;
54169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#ifdef DEBUG
54269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	qprintf("glob0", patbuf);
54369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#endif
54469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
54569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	if ((error = glob1(patbuf, pglob, limit)) != 0)
54669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		return error;
54769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
54869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	if (pglob->gl_pathc == oldpathc) {
54969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		/*
55069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		 * If there was no match we are going to append the pattern
55169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		 * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was
55269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		 * specified and the pattern did not contain any magic
55369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		 * characters GLOB_NOMAGIC is there just for compatibility
55469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		 * with csh.
55569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		 */
55669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		if ((pglob->gl_flags & GLOB_NOCHECK) ||
55769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		    ((pglob->gl_flags & (GLOB_NOMAGIC|GLOB_MAGCHAR))
55869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		     == GLOB_NOMAGIC)) {
55969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			return globextend(pattern, pglob, limit);
56069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		} else {
56169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			return GLOB_NOMATCH;
56269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		}
56369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	} else if (!(pglob->gl_flags & GLOB_NOSORT)) {
56469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc,
56569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		    (size_t)pglob->gl_pathc - oldpathc, sizeof(char *),
56669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		    compare);
56769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	}
56869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
56969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	return 0;
57069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban}
57169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
57269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanstatic int
57369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbancompare(const void *p, const void *q)
57469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban{
57569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
57669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	_DIAGASSERT(p != NULL);
57769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	_DIAGASSERT(q != NULL);
57869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
57969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	return strcoll(*(const char * const *)p, *(const char * const *)q);
58069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban}
58169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
58269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanstatic int
58369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanglob1(Char *pattern, glob_t *pglob, struct glob_limit *limit)
58469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban{
58569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	Char pathbuf[MAXPATHLEN+1];
58669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
58769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	_DIAGASSERT(pattern != NULL);
58869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	_DIAGASSERT(pglob != NULL);
58969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
59069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	/* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */
59169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	if (*pattern == EOS)
59269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		return 0;
59369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	/*
59469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	 * we save one character so that we can use ptr >= limit,
59569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	 * in the general case when we are appending non nul chars only.
59669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	 */
59769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	return glob2(pathbuf, pathbuf,
59869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	    pathbuf + (sizeof(pathbuf) / sizeof(*pathbuf)) - 1, pattern,
59969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	    pglob, limit);
60069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban}
60169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
60269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban/*
60369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * The functions glob2 and glob3 are mutually recursive; there is one level
60469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * of recursion for each segment in the pattern that contains one or more
60569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * meta characters.
60669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban */
60769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanstatic int
60869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanglob2(Char *pathbuf, Char *pathend, Char *pathlim, const Char *pattern,
60969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban    glob_t *pglob, struct glob_limit *limit)
61069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban{
61169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	__gl_stat_t sb;
61269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	const Char *p;
61369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	Char *q;
61469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	int anymeta;
61569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
61669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	_DIAGASSERT(pathbuf != NULL);
61769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	_DIAGASSERT(pathend != NULL);
61869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	_DIAGASSERT(pattern != NULL);
61969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	_DIAGASSERT(pglob != NULL);
62069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
62169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#ifdef DEBUG
62269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	qprintf("glob2", pathbuf);
62369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#endif
62469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	/*
62569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	 * Loop over pattern segments until end of pattern or until
62669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	 * segment with meta character found.
62769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	 */
62869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	for (anymeta = 0;;) {
62969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		if (*pattern == EOS) {		/* End of pattern? */
63069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			*pathend = EOS;
63169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			if (g_lstat(pathbuf, &sb, pglob))
63269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				return 0;
63369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
63469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			if ((pglob->gl_flags & GLOB_LIMIT) &&
63569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			    limit->l_stat++ >= GLOB_LIMIT_STAT) {
63669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				errno = 0;
63769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				*pathend++ = SEP;
63869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				*pathend = EOS;
63969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				return GLOB_NOSPACE;
64069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			}
64169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			if (((pglob->gl_flags & GLOB_MARK) &&
64269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			    pathend[-1] != SEP) && (S_ISDIR(sb.st_mode) ||
64369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			    (S_ISLNK(sb.st_mode) &&
64469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			    (g_stat(pathbuf, &sb, pglob) == 0) &&
64569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			    S_ISDIR(sb.st_mode)))) {
64669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				if (pathend >= pathlim)
64769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban					return GLOB_ABORTED;
64869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				*pathend++ = SEP;
64969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				*pathend = EOS;
65069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			}
65169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			++pglob->gl_matchc;
65269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			return globextend(pathbuf, pglob, limit);
65369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		}
65469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
65569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		/* Find end of next segment, copy tentatively to pathend. */
65669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		q = pathend;
65769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		p = pattern;
65869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		while (*p != EOS && *p != SEP) {
65969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			if (ismeta(*p))
66069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				anymeta = 1;
66169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			if (q >= pathlim)
66269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				return GLOB_ABORTED;
66369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			*q++ = *p++;
66469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		}
66569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
66669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban                if (!anymeta) {
66769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			pathend = q;
66869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			pattern = p;
66969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			while (*pattern == SEP) {
67069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				if (pathend >= pathlim)
67169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban					return GLOB_ABORTED;
67269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				*pathend++ = *pattern++;
67369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			}
67469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		} else			/* Need expansion, recurse. */
67569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			return glob3(pathbuf, pathend, pathlim, pattern, p,
67669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			    pattern, pglob, limit);
67769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	}
67869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	/* NOTREACHED */
67969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban}
68069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
68169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanstatic int
68269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanglob3(Char *pathbuf, Char *pathend, Char *pathlim, const Char *pattern,
68369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban    const Char *restpattern, const Char *pglobstar, glob_t *pglob,
68469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban    struct glob_limit *limit)
68569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban{
68669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	struct dirent *dp;
68769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	DIR *dirp;
68869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	__gl_stat_t sbuf;
68969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	int error;
69069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	char buf[MAXPATHLEN];
69169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	int globstar = 0;
69269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	int chase_symlinks = 0;
69369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	const Char *termstar = NULL;
69469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
69569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	/*
69669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	 * The readdirfunc declaration can't be prototyped, because it is
69769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	 * assigned, below, to two functions which are prototyped in glob.h
69869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	 * and dirent.h as taking pointers to differently typed opaque
69969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	 * structures.
70069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	 */
70169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	struct dirent *(*readdirfunc)(void *);
70269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
70369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	_DIAGASSERT(pathbuf != NULL);
70469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	_DIAGASSERT(pathend != NULL);
70569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	_DIAGASSERT(pattern != NULL);
70669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	_DIAGASSERT(restpattern != NULL);
70769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	_DIAGASSERT(pglob != NULL);
70869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
70969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	*pathend = EOS;
71069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	errno = 0;
71169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
71269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	while (pglobstar < restpattern) {
71369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		if ((pglobstar[0] & M_MASK) == M_ALL &&
71469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		    (pglobstar[1] & M_MASK) == M_ALL) {
71569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			globstar = 1;
71669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			chase_symlinks = (pglobstar[2] & M_MASK) == M_ALL;
71769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			termstar = pglobstar + (2 + chase_symlinks);
71869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			break;
71969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		}
72069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		pglobstar++;
72169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	}
72269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
72369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	if (globstar) {
72469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		error = pglobstar == pattern && termstar == restpattern ?
72569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		    *restpattern == EOS ?
72669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		    glob2(pathbuf, pathend, pathlim, restpattern - 1, pglob,
72769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		    limit) :
72869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		    glob2(pathbuf, pathend, pathlim, restpattern + 1, pglob,
72969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		    limit) :
73069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		    glob3(pathbuf, pathend, pathlim, pattern, restpattern,
73169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		    termstar, pglob, limit);
73269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		if (error)
73369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			return error;
73469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		*pathend = EOS;
73569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	}
73669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
73769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	if (*pathbuf && (g_lstat(pathbuf, &sbuf, pglob) ||
73869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	    !S_ISDIR(sbuf.st_mode)
73969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#ifdef S_IFLINK
74069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	     && ((globstar && !chase_symlinks) || !S_ISLNK(sbuf.st_mode))
74169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#endif
74269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	    ))
74369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		return 0;
74469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
74569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	if ((dirp = g_opendir(pathbuf, pglob)) == NULL) {
74669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		if (pglob->gl_errfunc) {
74769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			if (g_Ctoc(pathbuf, buf, sizeof(buf)))
74869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				return GLOB_ABORTED;
74969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			if (pglob->gl_errfunc(buf, errno) ||
75069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			    pglob->gl_flags & GLOB_ERR)
75169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				return GLOB_ABORTED;
75269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		}
75369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		/*
75469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		 * Posix/XOpen: glob should return when it encounters a
75569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		 * directory that it cannot open or read
75669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		 * XXX: Should we ignore ENOTDIR and ENOENT though?
75769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		 * I think that Posix had in mind EPERM...
75869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		 */
75969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		if (pglob->gl_flags & GLOB_ERR)
76069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			return GLOB_ABORTED;
76169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
76269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		return 0;
76369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	}
76469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
76569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	error = 0;
76669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
76769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	/* Search directory for matching names. */
76869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	if (pglob->gl_flags & GLOB_ALTDIRFUNC)
76969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		readdirfunc = pglob->gl_readdir;
77069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	else
77169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		readdirfunc = (struct dirent *(*)(void *)) readdir;
77269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	while ((dp = (*readdirfunc)(dirp)) != NULL) {
77369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		unsigned char *sc;
77469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		Char *dc;
77569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
77669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		if ((pglob->gl_flags & GLOB_LIMIT) &&
77769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		    limit->l_readdir++ >= GLOB_LIMIT_READDIR) {
77869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			errno = 0;
77969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			*pathend++ = SEP;
78069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			*pathend = EOS;
78169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			error = GLOB_NOSPACE;
78269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			break;
78369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		}
78469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
78569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		/*
78669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		 * Initial DOT must be matched literally, unless we have
78769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		 * GLOB_PERIOD set.
78869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		 */
78969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		if ((pglob->gl_flags & GLOB_PERIOD) == 0)
79069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			if (dp->d_name[0] == DOT && *pattern != DOT)
79169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				continue;
79269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		/*
79369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		 * If GLOB_NO_DOTDIRS is set, . and .. vanish.
79469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		 */
79569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		if ((pglob->gl_flags & GLOB_NO_DOTDIRS) &&
79669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		    (dp->d_name[0] == DOT) &&
79769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		    ((dp->d_name[1] == EOS) ||
79869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		     ((dp->d_name[1] == DOT) && (dp->d_name[2] == EOS))))
79969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			continue;
80069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		/*
80169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		 * The resulting string contains EOS, so we can
80269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		 * use the pathlim character, if it is the nul
80369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		 */
80469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		for (sc = (unsigned char *) dp->d_name, dc = pathend;
80569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		     dc <= pathlim && (*dc++ = *sc++) != EOS;)
80669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			continue;
80769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
80869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		/*
80969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		 * Have we filled the buffer without seeing EOS?
81069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		 */
81169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		if (dc > pathlim && *pathlim != EOS) {
81269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			/*
81369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			 * Abort when requested by caller, otherwise
81469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			 * reset pathend back to last SEP and continue
81569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			 * with next dir entry.
81669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			 */
81769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			if (pglob->gl_flags & GLOB_ERR) {
81869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				error = GLOB_ABORTED;
81969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				break;
82069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			}
82169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			else {
82269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				*pathend = EOS;
82369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				continue;
82469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			}
82569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		}
82669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
82769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		if (globstar) {
82869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#ifdef S_IFLNK
82969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			if (!chase_symlinks &&
83069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			    (g_lstat(pathbuf, &sbuf, pglob) ||
83169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			    S_ISLNK(sbuf.st_mode)))
83269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				continue;
83369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#endif
83469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
83569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			if (!match(pathend, pattern, termstar))
83669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				continue;
83769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
83869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			if (--dc < pathlim - 2)
83969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				*dc++ = SEP;
84069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			*dc = EOS;
84169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			error = glob2(pathbuf, dc, pathlim, pglobstar,
84269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			    pglob, limit);
84369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			if (error)
84469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				break;
84569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			*pathend = EOS;
84669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		} else {
84769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			if (!match(pathend, pattern, restpattern)) {
84869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				*pathend = EOS;
84969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				continue;
85069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			}
85169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			error = glob2(pathbuf, --dc, pathlim, restpattern,
85269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			    pglob, limit);
85369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			if (error)
85469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				break;
85569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		}
85669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	}
85769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	if (pglob->gl_flags & GLOB_ALTDIRFUNC)
85869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		(*pglob->gl_closedir)(dirp);
85969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	else
86069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		closedir(dirp);
86169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
86269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	/*
86369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	 * Again Posix X/Open issue with regards to error handling.
86469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	 */
86569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	if ((error || errno) && (pglob->gl_flags & GLOB_ERR))
86669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		return GLOB_ABORTED;
86769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
86869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	return error;
86969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban}
87069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
87169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
87269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban/*
87369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * Extend the gl_pathv member of a glob_t structure to accommodate a new item,
87469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * add the new item, and update gl_pathc.
87569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban *
87669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * This assumes the BSD realloc, which only copies the block when its size
87769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic
87869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * behavior.
87969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban *
88069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * Return 0 if new item added, error code if memory couldn't be allocated.
88169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban *
88269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * Invariant of the glob_t structure:
88369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban *	Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and
88469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban *	gl_pathv points to (gl_offs + gl_pathc + 1) items.
88569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban */
88669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanstatic int
88769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanglobextend(const Char *path, glob_t *pglob, struct glob_limit *limit)
88869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban{
88969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	char **pathv;
89069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	size_t i, newsize, len;
89169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	char *copy;
89269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	const Char *p;
89369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
89469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	_DIAGASSERT(path != NULL);
89569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	_DIAGASSERT(pglob != NULL);
89669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
89769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs);
89869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	if ((pglob->gl_flags & GLOB_LIMIT) &&
89969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	    newsize > GLOB_LIMIT_PATH * sizeof(*pathv))
90069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		goto nospace;
90169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	pathv = pglob->gl_pathv ? realloc(pglob->gl_pathv, newsize) :
90269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	    malloc(newsize);
90369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	if (pathv == NULL)
90469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		return GLOB_NOSPACE;
90569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
90669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) {
90769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		/* first time around -- clear initial gl_offs items */
90869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		pathv += pglob->gl_offs;
90969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		for (i = pglob->gl_offs + 1; --i > 0; )
91069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			*--pathv = NULL;
91169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	}
91269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	pglob->gl_pathv = pathv;
91369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
91469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	for (p = path; *p++;)
91569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		continue;
91669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	len = (size_t)(p - path);
91769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	limit->l_string += len;
91869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	if ((copy = malloc(len)) != NULL) {
91969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		if (g_Ctoc(path, copy, len)) {
92069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			free(copy);
92169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			return GLOB_ABORTED;
92269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		}
92369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		pathv[pglob->gl_offs + pglob->gl_pathc++] = copy;
92469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	}
92569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
92669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
92769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	if ((pglob->gl_flags & GLOB_LIMIT) &&
92869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	    (newsize + limit->l_string) >= GLOB_LIMIT_STRING)
92969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		goto nospace;
93069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
93169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	return copy == NULL ? GLOB_NOSPACE : 0;
93269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbannospace:
93369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	errno = 0;
93469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	return GLOB_NOSPACE;
93569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban}
93669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
93769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
93869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban/*
93969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * pattern matching function for filenames.  Each occurrence of the *
94069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban * pattern causes a recursion level.
94169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban */
94269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanstatic int
94369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanmatch(const Char *name, const Char *pat, const Char *patend)
94469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban{
94569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	int ok, negate_range;
94669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	Char c, k;
94769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
94869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	_DIAGASSERT(name != NULL);
94969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	_DIAGASSERT(pat != NULL);
95069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	_DIAGASSERT(patend != NULL);
95169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
95269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	while (pat < patend) {
95369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		c = *pat++;
95469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		switch (c & M_MASK) {
95569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		case M_ALL:
95669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			while (pat < patend && (*pat & M_MASK) == M_ALL)
95769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				pat++;	/* eat consecutive '*' */
95869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			if (pat == patend)
95969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				return 1;
96069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			for (; !match(name, pat, patend); name++)
96169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				if (*name == EOS)
96269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban					return 0;
96369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			return 1;
96469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		case M_ONE:
96569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			if (*name++ == EOS)
96669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				return 0;
96769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			break;
96869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		case M_SET:
96969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			ok = 0;
97069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			if ((k = *name++) == EOS)
97169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				return 0;
97269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS)
97369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				++pat;
97469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			while (((c = *pat++) & M_MASK) != M_END)
97569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				if ((*pat & M_MASK) == M_RNG) {
97669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban					if (c <= k && k <= pat[1])
97769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban						ok = 1;
97869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban					pat += 2;
97969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				} else if (c == k)
98069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban					ok = 1;
98169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			if (ok == negate_range)
98269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				return 0;
98369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			break;
98469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		default:
98569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			if (*name++ != c)
98669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				return 0;
98769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			break;
98869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		}
98969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	}
99069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	return *name == EOS;
99169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban}
99269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
99369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban/* Free allocated data belonging to a glob_t structure. */
99469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanvoid
99569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanglobfree(glob_t *pglob)
99669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban{
99769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	size_t i;
99869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	char **pp;
99969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
100069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	_DIAGASSERT(pglob != NULL);
100169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
100269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	if (pglob->gl_pathv != NULL) {
100369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		pp = pglob->gl_pathv + pglob->gl_offs;
100469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		for (i = pglob->gl_pathc; i--; ++pp)
100569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			if (*pp)
100669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban				free(*pp);
100769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		free(pglob->gl_pathv);
100869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		pglob->gl_pathv = NULL;
100969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		pglob->gl_pathc = 0;
101069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	}
101169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban}
101269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
101369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#ifndef __LIBC12_SOURCE__
101469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanint
101569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanglob_pattern_p(const char *pattern, int quote)
101669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban{
101769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	int range = 0;
101869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
101969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	for (; *pattern; pattern++)
102069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		switch (*pattern) {
102169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		case QUESTION:
102269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		case STAR:
102369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			return 1;
102469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
102569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		case QUOTE:
102669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			if (quote && pattern[1] != EOS)
102769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			      ++pattern;
102869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			break;
102969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
103069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		case LBRACKET:
103169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			range = 1;
103269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			break;
103369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
103469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		case RBRACKET:
103569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			if (range)
103669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			      return 1;
103769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			break;
103869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		default:
103969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			break;
104069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		}
104169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
104269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	  return 0;
104369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban}
104469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#endif
104569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
104669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanstatic DIR *
104769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbang_opendir(Char *str, glob_t *pglob)
104869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban{
104969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	char buf[MAXPATHLEN];
105069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
105169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	_DIAGASSERT(str != NULL);
105269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	_DIAGASSERT(pglob != NULL);
105369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
105469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	if (!*str)
105569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		(void)strlcpy(buf, ".", sizeof(buf));
105669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	else {
105769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		if (g_Ctoc(str, buf, sizeof(buf)))
105869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			return NULL;
105969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	}
106069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
106169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	if (pglob->gl_flags & GLOB_ALTDIRFUNC)
106269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		return (*pglob->gl_opendir)(buf);
106369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
106469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	return opendir(buf);
106569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban}
106669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
106769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanstatic int
106869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbang_lstat(Char *fn, __gl_stat_t *sb, glob_t *pglob)
106969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban{
107069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	char buf[MAXPATHLEN];
107169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
107269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	_DIAGASSERT(fn != NULL);
107369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	_DIAGASSERT(sb != NULL);
107469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	_DIAGASSERT(pglob != NULL);
107569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
107669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	if (g_Ctoc(fn, buf, sizeof(buf)))
107769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		return -1;
107869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	if (pglob->gl_flags & GLOB_ALTDIRFUNC)
107969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		return (*pglob->gl_lstat)(buf, sb);
108069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	return lstat(buf, sb);
108169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban}
108269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
108369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanstatic int
108469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbang_stat(Char *fn, __gl_stat_t *sb, glob_t *pglob)
108569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban{
108669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	char buf[MAXPATHLEN];
108769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
108869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	_DIAGASSERT(fn != NULL);
108969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	_DIAGASSERT(sb != NULL);
109069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	_DIAGASSERT(pglob != NULL);
109169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
109269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	if (g_Ctoc(fn, buf, sizeof(buf)))
109369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		return -1;
109469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	if (pglob->gl_flags & GLOB_ALTDIRFUNC)
109569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		return (*pglob->gl_stat)(buf, sb);
109669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	return stat(buf, sb);
109769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban}
109869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
109969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanstatic Char *
110069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbang_strchr(const Char *str, int ch)
110169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban{
110269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
110369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	_DIAGASSERT(str != NULL);
110469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
110569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	do {
110669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		if (*str == ch)
110769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban			return __UNCONST(str);
110869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	} while (*str++);
110969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	return NULL;
111069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban}
111169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
111269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanstatic int
111369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbang_Ctoc(const Char *str, char *buf, size_t len)
111469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban{
111569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	char *dc;
111669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
111769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	_DIAGASSERT(str != NULL);
111869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	_DIAGASSERT(buf != NULL);
111969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
112069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	if (len == 0)
112169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		return 1;
112269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
112369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	for (dc = buf; len && (*dc++ = *str++) != EOS; len--)
112469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		continue;
112569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
112669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	return len == 0;
112769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban}
112869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
112969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#ifdef DEBUG
113069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanstatic void
113169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serbanqprintf(const char *str, Char *s)
113269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban{
113369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	Char *p;
113469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
113569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	_DIAGASSERT(str != NULL);
113669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	_DIAGASSERT(s != NULL);
113769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban
113869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	(void)printf("%s:\n", str);
113969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	for (p = s; *p; p++)
114069c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		(void)printf("%c", CHAR(*p));
114169c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	(void)printf("\n");
114269c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	for (p = s; *p; p++)
114369c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		(void)printf("%c", *p & M_PROTECT ? '"' : ' ');
114469c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	(void)printf("\n");
114569c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	for (p = s; *p; p++)
114669c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban		(void)printf("%c", ismeta(*p) ? '_' : ' ');
114769c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban	(void)printf("\n");
114869c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban}
114969c7a112c52c68b9b4654b94789505e7098c1fe7Mihai Serban#endif
1150