perl

 view release on metacpan or  search on metacpan

ext/File-Glob/bsd_glob.c  view on Meta::CPAN

 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)glob.c	8.3 (Berkeley) 10/13/93";
/* most changes between the version above and the one below have been ported:
static char sscsid[]=  "$OpenBSD: glob.c,v 1.8.10.1 2001/04/10 jason Exp $";
 */
#endif /* LIBC_SCCS and not lint */

/*
 * glob(3) -- a superset of the one defined in POSIX 1003.2.
 *
 * The [!...] convention to negate a range is supported (SysV, Posix, ksh).
 *
 * Optional extra services, controlled by flags not defined by POSIX:
 *
 * GLOB_QUOTE:
 *	Escaping convention: \ inhibits any special meaning the following
 *	character might have (except \ at end of string is retained).
 * GLOB_MAGCHAR:
 *	Set in gl_flags if pattern contained a globbing character.
 * GLOB_NOMAGIC:
 *	Same as GLOB_NOCHECK, but it will only append pattern if it did
 *	not contain any magic characters.  [Used in csh style globbing]
 * GLOB_ALTDIRFUNC:
 *	Use alternately specified directory access functions.
 * GLOB_TILDE:
 *	expand ~user/foo to the /home/dir/of/user/foo
 * GLOB_BRACE:
 *	expand {1,2}{a,b} to 1a 1b 2a 2b
 * gl_matchc:
 *	Number of matches in the current invocation of glob.
 * GLOB_ALPHASORT:
 *	sort alphabetically like csh (case doesn't matter) instead of in ASCII
 *	order
 */

#include <EXTERN.h>
#include <perl.h>
#include <XSUB.h>

#include "bsd_glob.h"
#ifdef I_PWD
#	include <pwd.h>
#else
#if defined(HAS_PASSWD) && !defined(VMS)
        struct passwd *getpwnam(char *);
        struct passwd *getpwuid(Uid_t);
#endif
#endif

#ifndef MAXPATHLEN
#  ifdef PATH_MAX
#    define MAXPATHLEN  PATH_MAX
#  else
#    define MAXPATHLEN  1024
#  endif
#endif

#include <limits.h>

#ifndef ARG_MAX
#  ifdef _SC_ARG_MAX
#    define     ARG_MAX         (sysconf(_SC_ARG_MAX))
#  else
#    ifdef _POSIX_ARG_MAX
#      define   ARG_MAX         _POSIX_ARG_MAX
#    else
#      ifdef WIN32
#        define ARG_MAX         14500   /* from VC's limits.h */
#      else
#        define ARG_MAX         4096    /* from POSIX, be conservative */
#      endif
#    endif
#  endif
#endif

#define BG_DOLLAR       '$'
#define BG_DOT          '.'
#define BG_EOS          '\0'
#define BG_LBRACKET     '['
#define BG_NOT          '!'
#define BG_QUESTION     '?'
#define BG_QUOTE        '\\'
#define BG_RANGE        '-'
#define BG_RBRACKET     ']'
#define BG_SEP  '/'
#ifdef DOSISH
#define BG_SEP2		'\\'
#endif
#define BG_STAR         '*'
#define BG_TILDE        '~'
#define BG_UNDERSCORE   '_'
#define BG_LBRACE       '{'
#define BG_RBRACE       '}'
#define BG_SLASH        '/'
#define BG_COMMA        ','

#ifndef GLOB_DEBUG

#define M_QUOTE         0x8000
#define M_PROTECT       0x4000
#define M_MASK          0xffff
#define M_ASCII         0x00ff

typedef U16 Char;

#else

ext/File-Glob/bsd_glob.c  view on Meta::CPAN

                                 */
                                for (pl = pe + 1; (*lm++ = *pl++) != BG_EOS; )
                                        ;

                                /* Expand the current pattern */
#ifdef GLOB_DEBUG
                                qprintf("globexp2:", patbuf);
#endif /* GLOB_DEBUG */
                                *rv = globexp1(patbuf, pglob);

                                /* move after the comma, to the next string */
                                pl = pm + 1;
                        }
                        break;

                default:
                        break;
                }
        }
        *rv = 0;
        return 0;
}



/*
 * expand tilde from the passwd file.
 */
static const Char *
globtilde(const Char *pattern, Char *patbuf, size_t patbuf_len, glob_t *pglob)
{
        char *h;
        const Char *p;
        Char *b, *eb;

        if (*pattern != BG_TILDE || !(pglob->gl_flags & GLOB_TILDE))
                return pattern;

        /* Copy up to the end of the string or / */
        eb = &patbuf[patbuf_len - 1];
        for (p = pattern + 1, h = (char *) patbuf;
             h < (char*)eb && *p && *p != BG_SLASH; *h++ = (char)*p++)
                ;

        *h = BG_EOS;

#if 0
        if (h == (char *)eb)
                return what;
#endif

        if (((char *) patbuf)[0] == BG_EOS) {
                /*
                 * handle a plain ~ or ~/ by expanding $HOME
                 * first and then trying the password file
                 * or $USERPROFILE on DOSISH systems
                 */
                if ((h = PerlEnv_getenv("HOME")) == NULL) {
#ifdef HAS_PASSWD
                        struct passwd *pwd;
                        if ((pwd = getpwuid(getuid())) == NULL)
                                return pattern;
                        else
                                h = pwd->pw_dir;
#elif DOSISH
                        /*
                         * When no passwd file, fallback to the USERPROFILE
                         * environment variable on DOSish systems.
                         */
                        if ((h = PerlEnv_getenv("USERPROFILE")) == NULL) {
                            return pattern;
                        }
#else
                        return pattern;
#endif
                }
        } else {
                /*
                 * Expand a ~user
                 */
#ifdef HAS_PASSWD
                struct passwd *pwd;
                if ((pwd = getpwnam((char*) patbuf)) == NULL)
                        return pattern;
                else
                        h = pwd->pw_dir;
#else
                return pattern;
#endif
        }

        /* Copy the home directory */
        for (b = patbuf; b < eb && *h; *b++ = *h++)
                ;

        /* Append the rest of the pattern */
        while (b < eb && (*b++ = *p++) != BG_EOS)
                ;
        *b = BG_EOS;

        return patbuf;
}


/*
 * The main glob() routine: compiles the pattern (optionally processing
 * quotes), calls glob1() to do the real pattern matching, and finally
 * sorts the list (unless unsorted operation is requested).  Returns 0
 * if things went well, nonzero if errors occurred.  It is not an error
 * to find no matches.
 */
static int
glob0(const Char *pattern, glob_t *pglob)
{
        const Char *qpat, *qpatnext;
        int c, err, oldflags, oldpathc;
        Char *bufnext, patbuf[MAXPATHLEN];
        size_t limit = 0;

        qpat = globtilde(pattern, patbuf, MAXPATHLEN, pglob);
        qpatnext = qpat;



( run in 1.477 second using v1.01-cache-2.11-cpan-140bd7fdf52 )