122347Spst/* glob.c: The csh et al glob pattern matching routines. 222347Spst 329964Sache%%% copyright-cmetz-96 492906SmarkmThis software is Copyright 1996-2001 by Craig Metz, All Rights Reserved. 592906SmarkmThe Inner Net License Version 3 applies to this software. 622347SpstYou should have received a copy of the license with this software. If 722347Spstyou didn't get a copy, you may request one from <license@inner.net>. 822347Spst 922347SpstPortions of this software are Copyright 1995 by Randall Atkinson and Dan 1022347SpstMcDonald, All Rights Reserved. All Rights under this copyright are assigned 1122347Spstto the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and 1222347SpstLicense Agreement applies to this software. 1322347Spst 1422347Spst History: 1522347Spst 1659118Skris Modified by cmetz for OPIE 2.32. Remove include of dirent.h here; it's 1759118Skris done already (and conditionally) in opie_cfg.h. 1822347Spst Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al. 1922347Spst Remove useless strings. Prototype right. 2022347Spst Modified at NRL for OPIE 2.0. 2122347Spst Originally from BSD. 2222347Spst*/ 2322347Spst/* 2422347Spst * Copyright (c) 1980 Regents of the University of California. 2522347Spst * All rights reserved. 2622347Spst * 2722347Spst * Redistribution and use in source and binary forms, with or without 2822347Spst * modification, are permitted provided that the following conditions 2922347Spst * are met: 3022347Spst * 1. Redistributions of source code must retain the above copyright 3122347Spst * notice, this list of conditions and the following disclaimer. 3222347Spst * 2. Redistributions in binary form must reproduce the above copyright 3322347Spst * notice, this list of conditions and the following disclaimer in the 3422347Spst * documentation and/or other materials provided with the distribution. 3522347Spst * 3. All advertising materials mentioning features or use of this software 3622347Spst * must display the following acknowledgement: 3722347Spst * This product includes software developed by the University of 3822347Spst * California, Berkeley and its contributors. 3922347Spst * 4. Neither the name of the University nor the names of its contributors 4022347Spst * may be used to endorse or promote products derived from this software 4122347Spst * without specific prior written permission. 4222347Spst * 4322347Spst * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 4422347Spst * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4522347Spst * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4622347Spst * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 4722347Spst * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4822347Spst * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 4922347Spst * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 5022347Spst * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 5122347Spst * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5222347Spst * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5322347Spst * SUCH DAMAGE. 5422347Spst */ 5522347Spst 5622347Spst/* 5722347Spst * C-shell glob for random programs. 5822347Spst */ 5922347Spst 6022347Spst#include "opie_cfg.h" 6122347Spst 6222347Spst#if HAVE_SYS_PARAM_H 6322347Spst#include <sys/param.h> 6422347Spst#endif /* HAVE_SYS_PARAM_H */ 6522347Spst#include <sys/stat.h> 6622347Spst 6722347Spst#if HAVE_PWD_H 6822347Spst#include <pwd.h> 6922347Spst#endif /* HAVE_PWD_H */ 7022347Spst#include <errno.h> 7122347Spst#include <stdio.h> 7222347Spst#include <string.h> 7322347Spst#if HAVE_LIMITS_H 7422347Spst#include <limits.h> 7522347Spst#endif /* HAVE_LIMITS_H */ 7622347Spst 7722347Spst#include "opie.h" 7822347Spst 7922347Spst#ifndef NCARGS 8022347Spst#define NCARGS 600 8122347Spst#endif /* NCARGS */ 8222347Spst#define QUOTE 0200 8322347Spst#define TRIM 0177 8422347Spst#define eq(a,b) (strcmp((a),(b)) == (0)) 8522347Spst#define GAVSIZ (NCARGS/6) 8622347Spst#define isdir(d) (((d.st_mode) & S_IFMT) == S_IFDIR) 8722347Spst 8822347Spststatic char **gargv; /* Pointer to the (stack) arglist */ 8922347Spststatic int gargc; /* Number args in gargv */ 9022347Spststatic int gnleft; 9122347Spststatic short gflag; 9222347Spst 9322347Spststatic int letter __P((register char)); 9422347Spststatic int digit __P((register char)); 9522347Spststatic int any __P((int, char *)); 9622347Spststatic int blklen __P((register char **)); 9722347SpstVOIDRET blkfree __P((char **)); 9822347Spststatic char *strspl __P((register char *, register char *)); 9922347Spst 10022347Spststatic int tglob __P((register char c)); 10122347Spst 10222347Spstextern int errno; 10322347Spststatic char *strend __P((char *)); 10422347Spst 10522347Spststatic int globcnt; 10622347Spst 10722347Spststatic char *globchars = "`{[*?"; 10822347Spstchar *globerr = NULL; 10922347Spstchar *home = NULL; 11022347Spst 11122347Spststatic char *gpath, *gpathp, *lastgpathp; 11222347Spststatic int globbed; 11322347Spststatic char *entp; 11422347Spststatic char **sortbas; 11522347Spst 11622347Spststatic int amatch __P((char *p, char *s)); 11722347Spststatic int execbrc __P((register char *p, register char *s)); 11822347SpstVOIDRET opiefatal __P((char *)); 11922347Spstchar **copyblk __P((char **)); 12022347Spst 12122347Spststatic int match FUNCTION((s, p), char *s AND char *p) 12222347Spst{ 12322347Spst register int c; 12422347Spst register char *sentp; 12522347Spst char sglobbed = globbed; 12622347Spst 12722347Spst if (*s == '.' && *p != '.') 12822347Spst return (0); 12922347Spst sentp = entp; 13022347Spst entp = s; 13122347Spst c = amatch(s, p); 13222347Spst entp = sentp; 13322347Spst globbed = sglobbed; 13422347Spst return (c); 13522347Spst} 13622347Spst 13722347Spst 13822347Spststatic int Gmatch FUNCTION((s, p), register char *s AND register char *p) 13922347Spst{ 14022347Spst register int scc; 14122347Spst int ok, lc; 14222347Spst int c, cc; 14322347Spst 14422347Spst for (;;) { 14522347Spst scc = *s++ & TRIM; 14622347Spst switch (c = *p++) { 14722347Spst 14822347Spst case '[': 14922347Spst ok = 0; 15022347Spst lc = 077777; 15122347Spst while (cc = *p++) { 15222347Spst if (cc == ']') { 15322347Spst if (ok) 15422347Spst break; 15522347Spst return (0); 15622347Spst } 15722347Spst if (cc == '-') { 15822347Spst if (lc <= scc && scc <= *p++) 15922347Spst ok++; 16022347Spst } else 16122347Spst if (scc == (lc = cc)) 16222347Spst ok++; 16322347Spst } 16422347Spst if (cc == 0) 16522347Spst if (ok) 16622347Spst p--; 16722347Spst else 16822347Spst return 0; 16922347Spst continue; 17022347Spst 17122347Spst case '*': 17222347Spst if (!*p) 17322347Spst return (1); 17422347Spst for (s--; *s; s++) 17522347Spst if (Gmatch(s, p)) 17622347Spst return (1); 17722347Spst return (0); 17822347Spst 17922347Spst case 0: 18022347Spst return (scc == 0); 18122347Spst 18222347Spst default: 18322347Spst if ((c & TRIM) != scc) 18422347Spst return (0); 18522347Spst continue; 18622347Spst 18722347Spst case '?': 18822347Spst if (scc == 0) 18922347Spst return (0); 19022347Spst continue; 19122347Spst 19222347Spst } 19322347Spst } 19422347Spst} 19522347Spst 19622347Spststatic VOIDRET Gcat FUNCTION((s1, s2), register char *s1 AND register char *s2) 19722347Spst{ 19822347Spst register int len = strlen(s1) + strlen(s2) + 1; 19922347Spst 20022347Spst if (len >= gnleft || gargc >= GAVSIZ - 1) 20122347Spst globerr = "Arguments too long"; 20222347Spst else { 20322347Spst gargc++; 20422347Spst gnleft -= len; 20522347Spst gargv[gargc] = 0; 20622347Spst gargv[gargc - 1] = strspl(s1, s2); 20722347Spst } 20822347Spst} 20922347Spst 21022347Spststatic VOIDRET addpath FUNCTION((c), char c) 21122347Spst{ 21222347Spst 21322347Spst if (gpathp >= lastgpathp) 21422347Spst globerr = "Pathname too long"; 21522347Spst else { 21622347Spst *gpathp++ = c; 21722347Spst *gpathp = 0; 21822347Spst } 21922347Spst} 22022347Spst 22122347Spststatic VOIDRET rscan FUNCTION((t, f), register char **t AND int (*f)__P((char))) 22222347Spst{ 22322347Spst register char *p, c; 22422347Spst 22522347Spst while (p = *t++) { 22622347Spst if (f == tglob) 22722347Spst if (*p == '~') 22822347Spst gflag |= 2; 22922347Spst else 23022347Spst if (eq(p, "{") || eq(p, "{}")) 23122347Spst continue; 23222347Spst while (c = *p++) 23322347Spst (*f) (c); 23422347Spst } 23522347Spst} 23622347Spst 23722347Spststatic int tglob FUNCTION((c), register char c) 23822347Spst{ 23922347Spst if (any(c, globchars)) 24022347Spst gflag |= c == '{' ? 2 : 1; 24122347Spst return (c); 24222347Spst} 24322347Spst 24422347Spststatic int letter FUNCTION((c), register char c) 24522347Spst{ 24622347Spst return (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '_'); 24722347Spst} 24822347Spst 24922347Spststatic int digit FUNCTION((c), register char c) 25022347Spst{ 25122347Spst return (c >= '0' && c <= '9'); 25222347Spst} 25322347Spst 25422347Spststatic int any FUNCTION((c, s), int c AND char *s) 25522347Spst{ 25622347Spst while (*s) 25722347Spst if (*s++ == c) 25822347Spst return (1); 25922347Spst return (0); 26022347Spst} 26122347Spst 26222347Spststatic int blklen FUNCTION((av), register char **av) 26322347Spst{ 26422347Spst register int i = 0; 26522347Spst 26622347Spst while (*av++) 26722347Spst i++; 26822347Spst return (i); 26922347Spst} 27022347Spst 27122347Spststatic char **blkcpy FUNCTION((oav, bv), char **oav AND register char **bv) 27222347Spst{ 27322347Spst register char **av = oav; 27422347Spst 27522347Spst while (*av++ = *bv++) 27622347Spst continue; 27722347Spst return (oav); 27822347Spst} 27922347Spst 28022347SpstVOIDRET blkfree FUNCTION((av0), char **av0) 28122347Spst{ 28222347Spst register char **av = av0; 28322347Spst 28422347Spst while (*av) 28522347Spst free(*av++); 28622347Spst} 28722347Spst 28822347Spststatic char *strspl FUNCTION((cp, dp), register char *cp AND register char *dp) 28922347Spst{ 29022347Spst register char *ep = (char *) malloc((unsigned) (strlen(cp) + 29122347Spst strlen(dp) + 1)); 29222347Spst 29322347Spst if (ep == (char *) 0) 29422347Spst opiefatal("Out of memory"); 29522347Spst strcpy(ep, cp); 29622347Spst strcat(ep, dp); 29722347Spst return (ep); 29822347Spst} 29922347Spst 30022347Spstchar **copyblk FUNCTION((v), char **v) 30122347Spst{ 30222347Spst register char **nv = (char **) malloc((unsigned) ((blklen(v) + 1) * 30322347Spst sizeof(char **))); 30422347Spst 30522347Spst if (nv == (char **) 0) 30622347Spst opiefatal("Out of memory"); 30722347Spst 30822347Spst return (blkcpy(nv, v)); 30922347Spst} 31022347Spst 31122347Spststatic char *strend FUNCTION((cp), register char *cp) 31222347Spst{ 31322347Spst 31422347Spst while (*cp) 31522347Spst cp++; 31622347Spst return (cp); 31722347Spst} 31822347Spst 31922347Spst/* 32022347Spst * Extract a home directory from the password file 32122347Spst * The argument points to a buffer where the name of the 32222347Spst * user whose home directory is sought is currently. 32322347Spst * We write the home directory of the user back there. 32422347Spst */ 32522347Spststatic int gethdir FUNCTION((home), char *home) 32622347Spst{ 32722347Spst register struct passwd *pp = getpwnam(home); 32822347Spst 32922347Spst if (!pp || home + strlen(pp->pw_dir) >= lastgpathp) 33022347Spst return (1); 33122347Spst strcpy(home, pp->pw_dir); 33222347Spst return (0); 33322347Spst} 33422347Spst 33522347Spststatic VOIDRET ginit FUNCTION((agargv), char **agargv) 33622347Spst{ 33722347Spst agargv[0] = 0; 33822347Spst gargv = agargv; 33922347Spst sortbas = agargv; 34022347Spst gargc = 0; 34122347Spst gnleft = NCARGS - 4; 34222347Spst} 34322347Spst 34422347Spststatic VOIDRET sort FUNCTION_NOARGS 34522347Spst{ 34622347Spst register char **p1, **p2, *c; 34722347Spst char **Gvp = &gargv[gargc]; 34822347Spst 34922347Spst p1 = sortbas; 35022347Spst while (p1 < Gvp - 1) { 35122347Spst p2 = p1; 35222347Spst while (++p2 < Gvp) 35322347Spst if (strcmp(*p1, *p2) > 0) 35422347Spst c = *p1, *p1 = *p2, *p2 = c; 35522347Spst p1++; 35622347Spst } 35722347Spst sortbas = Gvp; 35822347Spst} 35922347Spst 36022347Spststatic VOIDRET matchdir FUNCTION((pattern), char *pattern) 36122347Spst{ 36222347Spst struct stat stb; 36322347Spst 36422347Spst register struct dirent *dp; 36522347Spst 36622347Spst DIR *dirp; 36722347Spst 36822347Spst dirp = opendir(*gpath == '\0' ? "." : gpath); 36922347Spst if (dirp == NULL) { 37022347Spst if (globbed) 37122347Spst return; 37222347Spst goto patherr2; 37322347Spst } 37422347Spst#if !defined(linux) 37522347Spst if (fstat(dirp->dd_fd, &stb) < 0) 37622347Spst goto patherr1; 37722347Spst if (!isdir(stb)) { 37822347Spst errno = ENOTDIR; 37922347Spst goto patherr1; 38022347Spst } 38122347Spst#endif /* !defined(linux) */ 38222347Spst while ((dp = readdir(dirp)) != NULL) { 38322347Spst if (dp->d_ino == 0) 38422347Spst continue; 38522347Spst if (match(dp->d_name, pattern)) { 38622347Spst Gcat(gpath, dp->d_name); 38722347Spst globcnt++; 38822347Spst } 38922347Spst } 39022347Spst closedir(dirp); 39122347Spst return; 39222347Spst 39322347Spstpatherr1: 39422347Spst closedir(dirp); 39522347Spstpatherr2: 39622347Spst globerr = "Bad directory components"; 39722347Spst} 39822347Spst 39922347Spststatic VOIDRET expand FUNCTION((as), char *as) 40022347Spst{ 40122347Spst register char *cs; 40222347Spst register char *sgpathp, *oldcs; 40322347Spst struct stat stb; 40422347Spst 40522347Spst sgpathp = gpathp; 40622347Spst cs = as; 40722347Spst if (*cs == '~' && gpathp == gpath) { 40822347Spst addpath('~'); 40922347Spst for (cs++; letter(*cs) || digit(*cs) || *cs == '-';) 41022347Spst addpath(*cs++); 41122347Spst if (!*cs || *cs == '/') { 41222347Spst if (gpathp != gpath + 1) { 41322347Spst *gpathp = 0; 41422347Spst if (gethdir(gpath + 1)) 41522347Spst globerr = "Unknown user name after ~"; 41622347Spst strcpy(gpath, gpath + 1); 41722347Spst } else 41822347Spst strcpy(gpath, home); 41922347Spst gpathp = strend(gpath); 42022347Spst } 42122347Spst } 42222347Spst while (!any(*cs, globchars)) { 42322347Spst if (*cs == 0) { 42422347Spst if (!globbed) 42522347Spst Gcat(gpath, ""); 42622347Spst else 42722347Spst if (stat(gpath, &stb) >= 0) { 42822347Spst Gcat(gpath, ""); 42922347Spst globcnt++; 43022347Spst } 43122347Spst goto endit; 43222347Spst } 43322347Spst addpath(*cs++); 43422347Spst } 43522347Spst oldcs = cs; 43622347Spst while (cs > as && *cs != '/') 43722347Spst cs--, gpathp--; 43822347Spst if (*cs == '/') 43922347Spst cs++, gpathp++; 44022347Spst *gpathp = 0; 44122347Spst if (*oldcs == '{') { 44222347Spst execbrc(cs, ((char *) 0)); 44322347Spst return; 44422347Spst } 44522347Spst matchdir(cs); 44622347Spstendit: 44722347Spst gpathp = sgpathp; 44822347Spst *gpathp = 0; 44922347Spst} 45022347Spst 45122347Spststatic int execbrc FUNCTION((p, s), char *p AND char *s) 45222347Spst{ 45322347Spst char restbuf[BUFSIZ + 2]; 45422347Spst register char *pe, *pm, *pl; 45522347Spst int brclev = 0; 45622347Spst char *lm, savec, *sgpathp; 45722347Spst 45822347Spst for (lm = restbuf; *p != '{'; *lm++ = *p++) 45922347Spst continue; 46022347Spst for (pe = ++p; *pe; pe++) 46122347Spst switch (*pe) { 46222347Spst 46322347Spst case '{': 46422347Spst brclev++; 46522347Spst continue; 46622347Spst 46722347Spst case '}': 46822347Spst if (brclev == 0) 46922347Spst goto pend; 47022347Spst brclev--; 47122347Spst continue; 47222347Spst 47322347Spst case '[': 47422347Spst for (pe++; *pe && *pe != ']'; pe++) 47522347Spst continue; 47622347Spst continue; 47722347Spst } 47822347Spstpend: 47922347Spst brclev = 0; 48022347Spst for (pl = pm = p; pm <= pe; pm++) 48122347Spst switch (*pm & (QUOTE | TRIM)) { 48222347Spst 48322347Spst case '{': 48422347Spst brclev++; 48522347Spst continue; 48622347Spst 48722347Spst case '}': 48822347Spst if (brclev) { 48922347Spst brclev--; 49022347Spst continue; 49122347Spst } 49222347Spst goto doit; 49322347Spst 49422347Spst case ',' | QUOTE: 49522347Spst case ',': 49622347Spst if (brclev) 49722347Spst continue; 49822347Spst doit: 49922347Spst savec = *pm; 50022347Spst *pm = 0; 50122347Spst strcpy(lm, pl); 50222347Spst strcat(restbuf, pe + 1); 50322347Spst *pm = savec; 50422347Spst if (s == 0) { 50522347Spst sgpathp = gpathp; 50622347Spst expand(restbuf); 50722347Spst gpathp = sgpathp; 50822347Spst *gpathp = 0; 50922347Spst } else 51022347Spst if (amatch(s, restbuf)) 51122347Spst return (1); 51222347Spst sort(); 51322347Spst pl = pm + 1; 51422347Spst if (brclev) 51522347Spst return (0); 51622347Spst continue; 51722347Spst 51822347Spst case '[': 51922347Spst for (pm++; *pm && *pm != ']'; pm++) 52022347Spst continue; 52122347Spst if (!*pm) 52222347Spst pm--; 52322347Spst continue; 52422347Spst } 52522347Spst if (brclev) 52622347Spst goto doit; 52722347Spst return (0); 52822347Spst} 52922347Spst 53022347Spststatic VOIDRET acollect FUNCTION((as), register char *as) 53122347Spst{ 53222347Spst register int ogargc = gargc; 53322347Spst 53422347Spst gpathp = gpath; 53522347Spst *gpathp = 0; 53622347Spst globbed = 0; 53722347Spst expand(as); 53822347Spst if (gargc != ogargc) 53922347Spst sort(); 54022347Spst} 54122347Spst 54222347Spststatic VOIDRET collect FUNCTION((as), register char *as) 54322347Spst{ 54422347Spst if (eq(as, "{") || eq(as, "{}")) { 54522347Spst Gcat(as, ""); 54622347Spst sort(); 54722347Spst } else 54822347Spst acollect(as); 54922347Spst} 55022347Spst 55122347Spststatic int amatch FUNCTION((s, p), register char *s AND register char *p) 55222347Spst{ 55322347Spst register int scc; 55422347Spst int ok, lc; 55522347Spst char *sgpathp; 55622347Spst struct stat stb; 55722347Spst int c, cc; 55822347Spst 55922347Spst globbed = 1; 56022347Spst for (;;) { 56122347Spst scc = *s++ & TRIM; 56222347Spst switch (c = *p++) { 56322347Spst 56422347Spst case '{': 56522347Spst return (execbrc(p - 1, s - 1)); 56622347Spst 56722347Spst case '[': 56822347Spst ok = 0; 56922347Spst lc = 077777; 57022347Spst while (cc = *p++) { 57122347Spst if (cc == ']') { 57222347Spst if (ok) 57322347Spst break; 57422347Spst return (0); 57522347Spst } 57622347Spst if (cc == '-') { 57722347Spst if (lc <= scc && scc <= *p++) 57822347Spst ok++; 57922347Spst } else 58022347Spst if (scc == (lc = cc)) 58122347Spst ok++; 58222347Spst } 58322347Spst if (cc == 0) 58422347Spst if (ok) 58522347Spst p--; 58622347Spst else 58722347Spst return 0; 58822347Spst continue; 58922347Spst 59022347Spst case '*': 59122347Spst if (!*p) 59222347Spst return (1); 59322347Spst if (*p == '/') { 59422347Spst p++; 59522347Spst goto slash; 59622347Spst } 59722347Spst s--; 59822347Spst do { 59922347Spst if (amatch(s, p)) 60022347Spst return (1); 60122347Spst } 60222347Spst while (*s++); 60322347Spst return (0); 60422347Spst 60522347Spst case 0: 60622347Spst return (scc == 0); 60722347Spst 60822347Spst default: 60922347Spst if (c != scc) 61022347Spst return (0); 61122347Spst continue; 61222347Spst 61322347Spst case '?': 61422347Spst if (scc == 0) 61522347Spst return (0); 61622347Spst continue; 61722347Spst 61822347Spst case '/': 61922347Spst if (scc) 62022347Spst return (0); 62122347Spst slash: 62222347Spst s = entp; 62322347Spst sgpathp = gpathp; 62422347Spst while (*s) 62522347Spst addpath(*s++); 62622347Spst addpath('/'); 62722347Spst if (stat(gpath, &stb) == 0 && isdir(stb)) 62822347Spst if (*p == 0) { 62922347Spst Gcat(gpath, ""); 63022347Spst globcnt++; 63122347Spst } else 63222347Spst expand(p); 63322347Spst gpathp = sgpathp; 63422347Spst *gpathp = 0; 63522347Spst return (0); 63622347Spst } 63722347Spst } 63822347Spst} 63922347Spst 64022347Spst 64122347Spstchar **ftpglob FUNCTION((v), register char *v) 64222347Spst{ 64322347Spst char agpath[BUFSIZ]; 64422347Spst char *agargv[GAVSIZ]; 64522347Spst char *vv[2]; 64622347Spst 64722347Spst vv[0] = v; 64822347Spst vv[1] = 0; 64922347Spst gflag = 0; 65022347Spst rscan(vv, tglob); 65122347Spst if (gflag == 0) { 65222347Spst vv[0] = strspl(v, ""); 65322347Spst return (copyblk(vv)); 65422347Spst } 65522347Spst globerr = 0; 65622347Spst gpath = agpath; 65722347Spst gpathp = gpath; 65822347Spst *gpathp = 0; 65922347Spst lastgpathp = &gpath[sizeof agpath - 2]; 66022347Spst ginit(agargv); 66122347Spst globcnt = 0; 66222347Spst collect(v); 66322347Spst if (globcnt == 0 && (gflag & 1)) { 66422347Spst blkfree(gargv), gargv = 0; 66522347Spst return (0); 66622347Spst } else 66722347Spst return (gargv = copyblk(gargv)); 66822347Spst} 669