xref: /onnv-gate/usr/src/cmd/cmd-inet/usr.sbin/in.ftpd/glob.c (revision 12333:f835be4545bb)
10Sstevel@tonic-gate /*
2*12333SMilan.Jurik@Sun.COM  * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
30Sstevel@tonic-gate  */
40Sstevel@tonic-gate 
50Sstevel@tonic-gate /****************************************************************************
60Sstevel@tonic-gate   Copyright (c) 1999,2000,2001 WU-FTPD Development Group.
70Sstevel@tonic-gate   All rights reserved.
80Sstevel@tonic-gate 
90Sstevel@tonic-gate   Portions Copyright (c) 1980, 1985, 1988, 1989, 1990, 1991, 1993, 1994
100Sstevel@tonic-gate     The Regents of the University of California.
110Sstevel@tonic-gate   Portions Copyright (c) 1993, 1994 Washington University in Saint Louis.
120Sstevel@tonic-gate   Portions Copyright (c) 1996, 1998 Berkeley Software Design, Inc.
130Sstevel@tonic-gate   Portions Copyright (c) 1989 Massachusetts Institute of Technology.
140Sstevel@tonic-gate   Portions Copyright (c) 1998 Sendmail, Inc.
150Sstevel@tonic-gate   Portions Copyright (c) 1983, 1995, 1996, 1997 Eric P.  Allman.
160Sstevel@tonic-gate   Portions Copyright (c) 1997 by Stan Barber.
170Sstevel@tonic-gate   Portions Copyright (c) 1997 by Kent Landfield.
180Sstevel@tonic-gate   Portions Copyright (c) 1991, 1992, 1993, 1994, 1995, 1996, 1997
190Sstevel@tonic-gate     Free Software Foundation, Inc.
200Sstevel@tonic-gate 
210Sstevel@tonic-gate   Use and distribution of this software and its source code are governed
220Sstevel@tonic-gate   by the terms and conditions of the WU-FTPD Software License ("LICENSE").
230Sstevel@tonic-gate 
240Sstevel@tonic-gate   If you did not receive a copy of the license, it may be obtained online
250Sstevel@tonic-gate   at http://www.wu-ftpd.org/license.html.
260Sstevel@tonic-gate 
270Sstevel@tonic-gate   $Id: glob.c,v 1.14.2.2 2001/11/29 17:01:38 wuftpd Exp $
280Sstevel@tonic-gate 
290Sstevel@tonic-gate ****************************************************************************/
300Sstevel@tonic-gate /*
310Sstevel@tonic-gate  * C-shell glob for random programs.
320Sstevel@tonic-gate  */
330Sstevel@tonic-gate 
340Sstevel@tonic-gate #include "config.h"
350Sstevel@tonic-gate 
360Sstevel@tonic-gate #include <sys/param.h>
370Sstevel@tonic-gate #include <sys/stat.h>
380Sstevel@tonic-gate 
390Sstevel@tonic-gate #ifdef HAVE_DIRENT_H
400Sstevel@tonic-gate #include <dirent.h>
410Sstevel@tonic-gate #else
420Sstevel@tonic-gate #include <sys/dir.h>
430Sstevel@tonic-gate #endif
440Sstevel@tonic-gate 
450Sstevel@tonic-gate #include <pwd.h>
460Sstevel@tonic-gate #include <errno.h>
470Sstevel@tonic-gate #include <stdio.h>
480Sstevel@tonic-gate #include <stdlib.h>
490Sstevel@tonic-gate #include <string.h>
500Sstevel@tonic-gate 
510Sstevel@tonic-gate #include "proto.h"
520Sstevel@tonic-gate 
530Sstevel@tonic-gate #define	QUOTE 0200
540Sstevel@tonic-gate #define	TRIM 0177
550Sstevel@tonic-gate #define	eq(a,b)		(strcmp(a, b)==0)
560Sstevel@tonic-gate #define	GAVSIZ		(1024 * 8)
570Sstevel@tonic-gate #define	isdir(d)	((d.st_mode & S_IFMT) == S_IFDIR)
580Sstevel@tonic-gate 
590Sstevel@tonic-gate static char **gargv;		/* Pointer to the (stack) arglist */
600Sstevel@tonic-gate static char **agargv;
610Sstevel@tonic-gate static size_t agargv_size;
620Sstevel@tonic-gate static int gargc;		/* Number args in gargv */
630Sstevel@tonic-gate static size_t gnleft;
640Sstevel@tonic-gate static short gflag;
650Sstevel@tonic-gate static int tglob(register char);
660Sstevel@tonic-gate 
670Sstevel@tonic-gate /* Prototypes */
680Sstevel@tonic-gate 
690Sstevel@tonic-gate static char *strend(register char *);
700Sstevel@tonic-gate static void addpath(char);
710Sstevel@tonic-gate static void ginit(char **);
72*12333SMilan.Jurik@Sun.COM static void collect(register char *, boolean_t check_ncargs);
73*12333SMilan.Jurik@Sun.COM static void acollect(register char *, boolean_t check_ncargs);
740Sstevel@tonic-gate static void sort(void);
75*12333SMilan.Jurik@Sun.COM static void expand(char *, boolean_t check_ncargs);
76*12333SMilan.Jurik@Sun.COM static void matchdir(char *, boolean_t check_ncargs);
770Sstevel@tonic-gate static int execbrc(char *, char *);
78*12333SMilan.Jurik@Sun.COM static int match(char *, char *, boolean_t check_ncargs);
79*12333SMilan.Jurik@Sun.COM static int amatch(char *, char *, boolean_t check_ncargs);
80*12333SMilan.Jurik@Sun.COM static void Gcat(register char *, register char *, boolean_t check_ncargs);
810Sstevel@tonic-gate static void rscan(register char **, int (*f) (register char));
820Sstevel@tonic-gate static int tglob(register char c);
830Sstevel@tonic-gate static int gethdir(char *);
840Sstevel@tonic-gate 
850Sstevel@tonic-gate int letter(register char);
860Sstevel@tonic-gate int digit(register char);
870Sstevel@tonic-gate int any(register int, register char *);
880Sstevel@tonic-gate int blklen(register char **);
890Sstevel@tonic-gate char **blkcpy(char **, register char **);
900Sstevel@tonic-gate 
910Sstevel@tonic-gate char *globerr;
920Sstevel@tonic-gate char *home;
930Sstevel@tonic-gate extern int errno;
940Sstevel@tonic-gate 
950Sstevel@tonic-gate static int globcnt;
960Sstevel@tonic-gate 
970Sstevel@tonic-gate char *globchars = "`{[*?";
980Sstevel@tonic-gate 
990Sstevel@tonic-gate static char *gpath, *gpathp, *lastgpathp;
1000Sstevel@tonic-gate static int globbed;
1010Sstevel@tonic-gate static char *entp;
1020Sstevel@tonic-gate static char **sortbas;
1030Sstevel@tonic-gate 
1040Sstevel@tonic-gate #ifdef OTHER_PASSWD
1050Sstevel@tonic-gate #include "getpwnam.h"
1060Sstevel@tonic-gate extern char _path_passwd[];
1070Sstevel@tonic-gate #endif
1080Sstevel@tonic-gate 
ftpglob(register char * v,boolean_t check_ncargs)109*12333SMilan.Jurik@Sun.COM char **ftpglob(register char *v, boolean_t check_ncargs)
1100Sstevel@tonic-gate {
1110Sstevel@tonic-gate     char agpath[BUFSIZ];
1120Sstevel@tonic-gate     char *vv[2];
1130Sstevel@tonic-gate 
1140Sstevel@tonic-gate     if (agargv == NULL) {
1150Sstevel@tonic-gate 	agargv = (char **) malloc(GAVSIZ * sizeof (char *));
1160Sstevel@tonic-gate 	if (agargv == NULL) {
1170Sstevel@tonic-gate 	    fatal("Out of memory");
1180Sstevel@tonic-gate 	}
1190Sstevel@tonic-gate 	agargv_size = GAVSIZ;
1200Sstevel@tonic-gate     }
1210Sstevel@tonic-gate     fixpath(v);
1220Sstevel@tonic-gate     if (v[0] == '\0')
1237143Sjk217608 	v = ".";
1240Sstevel@tonic-gate     else if ((strlen(v) > 1) && (v[strlen(v) - 1] == '/'))
1250Sstevel@tonic-gate 	v[strlen(v) - 1] = '\0';
1260Sstevel@tonic-gate 
1270Sstevel@tonic-gate     vv[0] = v;
1280Sstevel@tonic-gate     vv[1] = NULL;
1290Sstevel@tonic-gate     globerr = NULL;
1300Sstevel@tonic-gate     gflag = 0;
1310Sstevel@tonic-gate     rscan(vv, tglob);
1320Sstevel@tonic-gate     if (gflag == 0) {
1330Sstevel@tonic-gate 	vv[0] = strspl(v, "");
1340Sstevel@tonic-gate 	return (copyblk(vv));
1350Sstevel@tonic-gate     }
1360Sstevel@tonic-gate 
1370Sstevel@tonic-gate     globerr = NULL;
1380Sstevel@tonic-gate     gpath = agpath;
1390Sstevel@tonic-gate     gpathp = gpath;
1400Sstevel@tonic-gate     *gpathp = 0;
1410Sstevel@tonic-gate     lastgpathp = &gpath[sizeof agpath - 2];
1420Sstevel@tonic-gate     ginit(agargv);
1430Sstevel@tonic-gate     globcnt = 0;
144*12333SMilan.Jurik@Sun.COM     collect(v, check_ncargs);
1450Sstevel@tonic-gate     if (globcnt == 0 && (gflag & 1)) {
1460Sstevel@tonic-gate 	blkfree(gargv), gargv = 0;
1470Sstevel@tonic-gate 	return (0);
1480Sstevel@tonic-gate     }
1490Sstevel@tonic-gate     else
1500Sstevel@tonic-gate 	return (gargv = copyblk(gargv));
1510Sstevel@tonic-gate }
1520Sstevel@tonic-gate 
ginit(char ** agargv)1530Sstevel@tonic-gate static void ginit(char **agargv)
1540Sstevel@tonic-gate {
1550Sstevel@tonic-gate 
1560Sstevel@tonic-gate     agargv[0] = 0;
1570Sstevel@tonic-gate     gargv = agargv;
1580Sstevel@tonic-gate     sortbas = agargv;
1590Sstevel@tonic-gate     gargc = 0;
1600Sstevel@tonic-gate     gnleft = NCARGS - 4;
1610Sstevel@tonic-gate }
1620Sstevel@tonic-gate 
collect(register char * as,boolean_t check_ncargs)163*12333SMilan.Jurik@Sun.COM static void collect(register char *as, boolean_t check_ncargs)
1640Sstevel@tonic-gate {
1650Sstevel@tonic-gate     if (eq(as, "{") || eq(as, "{}")) {
166*12333SMilan.Jurik@Sun.COM 	Gcat(as, "", check_ncargs);
1670Sstevel@tonic-gate 	sort();
1680Sstevel@tonic-gate     }
1690Sstevel@tonic-gate     else
170*12333SMilan.Jurik@Sun.COM 	acollect(as, check_ncargs);
1710Sstevel@tonic-gate }
1720Sstevel@tonic-gate 
acollect(register char * as,boolean_t check_ncargs)173*12333SMilan.Jurik@Sun.COM static void acollect(register char *as, boolean_t check_ncargs)
1740Sstevel@tonic-gate {
1750Sstevel@tonic-gate     register int ogargc = gargc;
1760Sstevel@tonic-gate 
1770Sstevel@tonic-gate     gpathp = gpath;
1780Sstevel@tonic-gate     *gpathp = 0;
1790Sstevel@tonic-gate     globbed = 0;
180*12333SMilan.Jurik@Sun.COM     expand(as, check_ncargs);
1810Sstevel@tonic-gate     if (gargc != ogargc)
1820Sstevel@tonic-gate 	sort();
1830Sstevel@tonic-gate }
1840Sstevel@tonic-gate 
1850Sstevel@tonic-gate static int
argcmp(const void * p1,const void * p2)1860Sstevel@tonic-gate argcmp(const void *p1, const void *p2)
1870Sstevel@tonic-gate {
1880Sstevel@tonic-gate     char *s1 = *(char **) p1;
1890Sstevel@tonic-gate     char *s2 = *(char **) p2;
1900Sstevel@tonic-gate 
1910Sstevel@tonic-gate     return (strcmp(s1, s2));
1920Sstevel@tonic-gate }
1930Sstevel@tonic-gate 
sort(void)1940Sstevel@tonic-gate static void sort(void)
1950Sstevel@tonic-gate {
1960Sstevel@tonic-gate     char **Gvp = &gargv[gargc];
1970Sstevel@tonic-gate 
1980Sstevel@tonic-gate     if (!globerr)
1990Sstevel@tonic-gate 	qsort(sortbas, Gvp - sortbas, sizeof (*sortbas), argcmp);
2000Sstevel@tonic-gate     sortbas = Gvp;
2010Sstevel@tonic-gate }
2020Sstevel@tonic-gate 
expand(char * as,boolean_t check_ncargs)203*12333SMilan.Jurik@Sun.COM static void expand(char *as, boolean_t check_ncargs)
2040Sstevel@tonic-gate {
2050Sstevel@tonic-gate     register char *cs;
2060Sstevel@tonic-gate     register char *sgpathp, *oldcs;
2070Sstevel@tonic-gate     struct stat stb;
2080Sstevel@tonic-gate 
2090Sstevel@tonic-gate     if (globerr)
2100Sstevel@tonic-gate 	return;
2110Sstevel@tonic-gate     sgpathp = gpathp;
2120Sstevel@tonic-gate     cs = as;
2130Sstevel@tonic-gate     if (*cs == '~' && gpathp == gpath) {
2140Sstevel@tonic-gate 	addpath('~');
2150Sstevel@tonic-gate 	for (cs++; letter(*cs) || digit(*cs) || *cs == '-';)
2160Sstevel@tonic-gate 	    addpath(*cs++);
2170Sstevel@tonic-gate 	if (!*cs || *cs == '/') {
2180Sstevel@tonic-gate 	    if (gpathp != gpath + 1) {
2190Sstevel@tonic-gate 		*gpathp = 0;
2200Sstevel@tonic-gate 		if (gethdir(gpath + 1))
2210Sstevel@tonic-gate 		    globerr = "Unknown user name after ~";
2220Sstevel@tonic-gate 		/* memmove used as strings overlap */
2230Sstevel@tonic-gate 		(void) memmove(gpath, gpath + 1, strlen(gpath + 1) + 1);
2240Sstevel@tonic-gate 	    }
2250Sstevel@tonic-gate 	    else
2260Sstevel@tonic-gate 		(void) strlcpy(gpath, home, BUFSIZ);
2270Sstevel@tonic-gate 	    gpathp = strend(gpath);
2280Sstevel@tonic-gate 	}
2290Sstevel@tonic-gate     }
2300Sstevel@tonic-gate     while (!any(*cs, globchars)) {
2310Sstevel@tonic-gate 	if (*cs == 0) {
2320Sstevel@tonic-gate 	    if (!globbed)
233*12333SMilan.Jurik@Sun.COM 		Gcat(gpath, "", check_ncargs);
2340Sstevel@tonic-gate 	    else if (stat(gpath, &stb) >= 0) {
235*12333SMilan.Jurik@Sun.COM 		Gcat(gpath, "", check_ncargs);
2360Sstevel@tonic-gate 		globcnt++;
2370Sstevel@tonic-gate 	    }
2380Sstevel@tonic-gate 	    goto endit;
2390Sstevel@tonic-gate 	}
2400Sstevel@tonic-gate 	addpath(*cs++);
2410Sstevel@tonic-gate     }
2420Sstevel@tonic-gate     oldcs = cs;
2430Sstevel@tonic-gate     while (cs > as && *cs != '/')
2440Sstevel@tonic-gate 	cs--, gpathp--;
2450Sstevel@tonic-gate     if (*cs == '/')
2460Sstevel@tonic-gate 	cs++, gpathp++;
2470Sstevel@tonic-gate     *gpathp = 0;
2480Sstevel@tonic-gate     if (*oldcs == '{') {
2490Sstevel@tonic-gate 	(void) execbrc(cs, ((char *) 0));
2500Sstevel@tonic-gate 	return;
2510Sstevel@tonic-gate     }
252*12333SMilan.Jurik@Sun.COM     matchdir(cs, check_ncargs);
2530Sstevel@tonic-gate   endit:
2540Sstevel@tonic-gate     gpathp = sgpathp;
2550Sstevel@tonic-gate     *gpathp = 0;
2560Sstevel@tonic-gate }
2570Sstevel@tonic-gate 
matchdir(char * pattern,boolean_t check_ncargs)258*12333SMilan.Jurik@Sun.COM static void matchdir(char *pattern, boolean_t check_ncargs)
2590Sstevel@tonic-gate {
2600Sstevel@tonic-gate     struct stat stb;
2610Sstevel@tonic-gate 
2620Sstevel@tonic-gate #ifdef HAVE_DIRENT_H
2630Sstevel@tonic-gate     register struct dirent *dp;
2640Sstevel@tonic-gate #else
2650Sstevel@tonic-gate     register struct direct *dp;
2660Sstevel@tonic-gate #endif
2670Sstevel@tonic-gate 
2680Sstevel@tonic-gate     DIR *dirp;
2690Sstevel@tonic-gate 
2700Sstevel@tonic-gate     dirp = opendir(*gpath == '\0' ? "." : gpath);
2710Sstevel@tonic-gate     if (dirp == NULL) {
2720Sstevel@tonic-gate 	if (globbed)
2730Sstevel@tonic-gate 	    return;
2740Sstevel@tonic-gate 	goto patherr2;
2750Sstevel@tonic-gate     }
2760Sstevel@tonic-gate #ifdef HAVE_DIRFD
2770Sstevel@tonic-gate     if (fstat(dirfd(dirp), &stb) < 0)
2780Sstevel@tonic-gate #else /* HAVE_DIRFD */
2790Sstevel@tonic-gate     if (fstat(dirp->dd_fd, &stb) < 0)
2800Sstevel@tonic-gate #endif /* HAVE_DIRFD */
2810Sstevel@tonic-gate 	goto patherr1;
2820Sstevel@tonic-gate     if (!isdir(stb)) {
2830Sstevel@tonic-gate 	errno = ENOTDIR;
2840Sstevel@tonic-gate 	goto patherr1;
2850Sstevel@tonic-gate     }
2860Sstevel@tonic-gate     while (!globerr && ((dp = readdir(dirp)) != NULL)) {
2870Sstevel@tonic-gate 	if (dp->d_ino == 0)
2880Sstevel@tonic-gate 	    continue;
289*12333SMilan.Jurik@Sun.COM 	if (match(dp->d_name, pattern, check_ncargs)) {
290*12333SMilan.Jurik@Sun.COM 	    Gcat(gpath, dp->d_name, check_ncargs);
2910Sstevel@tonic-gate 	    globcnt++;
2920Sstevel@tonic-gate 	}
2930Sstevel@tonic-gate     }
2940Sstevel@tonic-gate     closedir(dirp);
2950Sstevel@tonic-gate     return;
2960Sstevel@tonic-gate 
2970Sstevel@tonic-gate   patherr1:
2980Sstevel@tonic-gate     closedir(dirp);
2990Sstevel@tonic-gate   patherr2:
3000Sstevel@tonic-gate     globerr = "Bad directory components";
3010Sstevel@tonic-gate }
3020Sstevel@tonic-gate 
execbrc(char * p,char * s)3030Sstevel@tonic-gate static int execbrc(char *p, char *s)
3040Sstevel@tonic-gate {
3050Sstevel@tonic-gate     char restbuf[BUFSIZ + 2];
3060Sstevel@tonic-gate     char *restbufend = &restbuf[sizeof(restbuf)];
3070Sstevel@tonic-gate     register char *pe, *pm, *pl;
3080Sstevel@tonic-gate     int brclev = 0;
3090Sstevel@tonic-gate     char *lm, savec, *sgpathp;
3100Sstevel@tonic-gate 
3110Sstevel@tonic-gate     for (lm = restbuf; *p != '{'; *lm++ = *p++) {
3120Sstevel@tonic-gate 	if (lm >= restbufend)
3130Sstevel@tonic-gate 	    return (0);
3140Sstevel@tonic-gate     }
3150Sstevel@tonic-gate     for (pe = ++p; *pe; pe++) {
3160Sstevel@tonic-gate 	switch (*pe) {
3170Sstevel@tonic-gate 
3180Sstevel@tonic-gate 	case '{':
3190Sstevel@tonic-gate 	    brclev++;
3200Sstevel@tonic-gate 	    continue;
3210Sstevel@tonic-gate 
3220Sstevel@tonic-gate 	case '}':
3230Sstevel@tonic-gate 	    if (brclev == 0)
3240Sstevel@tonic-gate 		goto pend;
3250Sstevel@tonic-gate 	    brclev--;
3260Sstevel@tonic-gate 	    continue;
3270Sstevel@tonic-gate 
3280Sstevel@tonic-gate 	case '[':
3290Sstevel@tonic-gate 	    for (pe++; *pe && *pe != ']'; pe++)
3300Sstevel@tonic-gate 		continue;
3310Sstevel@tonic-gate 	    if (!*pe) {
3320Sstevel@tonic-gate 		globerr = "Missing ]";
3330Sstevel@tonic-gate 		return (0);
3340Sstevel@tonic-gate 	    }
3350Sstevel@tonic-gate 	    continue;
3360Sstevel@tonic-gate 	}
3370Sstevel@tonic-gate     }
3380Sstevel@tonic-gate   pend:
3390Sstevel@tonic-gate     if (brclev || !*pe) {
3400Sstevel@tonic-gate 	globerr = "Missing }";
3410Sstevel@tonic-gate 	return (0);
3420Sstevel@tonic-gate     }
3430Sstevel@tonic-gate     for (pl = pm = p; pm <= pe; pm++) {
3440Sstevel@tonic-gate 	switch (*pm & (QUOTE | TRIM)) {
3450Sstevel@tonic-gate 
3460Sstevel@tonic-gate 	case '{':
3470Sstevel@tonic-gate 	    brclev++;
3480Sstevel@tonic-gate 	    continue;
3490Sstevel@tonic-gate 
3500Sstevel@tonic-gate 	case '}':
3510Sstevel@tonic-gate 	    if (brclev) {
3520Sstevel@tonic-gate 		brclev--;
3530Sstevel@tonic-gate 		continue;
3540Sstevel@tonic-gate 	    }
3550Sstevel@tonic-gate 	    goto doit;
3560Sstevel@tonic-gate 
3570Sstevel@tonic-gate 	case ',' | QUOTE:
3580Sstevel@tonic-gate 	case ',':
3590Sstevel@tonic-gate 	    if (brclev)
3600Sstevel@tonic-gate 		continue;
3610Sstevel@tonic-gate 	  doit:
3620Sstevel@tonic-gate 	    savec = *pm;
3630Sstevel@tonic-gate 	    *pm = 0;
3640Sstevel@tonic-gate 	    if (lm + strlen(pl) + strlen(pe + 1) >= restbufend)
3650Sstevel@tonic-gate 		return (0);
3660Sstevel@tonic-gate 	    (void) strlcpy(lm, pl, restbufend - lm);
3670Sstevel@tonic-gate 	    (void) strlcat(restbuf, pe + 1, sizeof(restbuf));
3680Sstevel@tonic-gate 	    *pm = savec;
3690Sstevel@tonic-gate 	    if (s == 0) {
3700Sstevel@tonic-gate 		sgpathp = gpathp;
371*12333SMilan.Jurik@Sun.COM 		expand(restbuf, B_TRUE);
3720Sstevel@tonic-gate 		gpathp = sgpathp;
3730Sstevel@tonic-gate 		*gpathp = 0;
3740Sstevel@tonic-gate 	    }
375*12333SMilan.Jurik@Sun.COM 	    else if (amatch(s, restbuf, B_TRUE))
3760Sstevel@tonic-gate 		return (1);
3770Sstevel@tonic-gate 	    sort();
3780Sstevel@tonic-gate 	    pl = pm + 1;
3790Sstevel@tonic-gate 	    continue;
3800Sstevel@tonic-gate 
3810Sstevel@tonic-gate 	case '[':
3820Sstevel@tonic-gate 	    for (pm++; *pm && *pm != ']'; pm++)
3830Sstevel@tonic-gate 		continue;
3840Sstevel@tonic-gate 	    if (!*pm) {
3850Sstevel@tonic-gate 		globerr = "Missing ]";
3860Sstevel@tonic-gate 		return (0);
3870Sstevel@tonic-gate 	    }
3880Sstevel@tonic-gate 	    continue;
3890Sstevel@tonic-gate 	}
3900Sstevel@tonic-gate     }
3910Sstevel@tonic-gate     return (0);
3920Sstevel@tonic-gate }
3930Sstevel@tonic-gate 
match(char * s,char * p,boolean_t check_ncargs)394*12333SMilan.Jurik@Sun.COM static int match(char *s, char *p, boolean_t check_ncargs)
3950Sstevel@tonic-gate {
3960Sstevel@tonic-gate     register int c;
3970Sstevel@tonic-gate     register char *sentp;
3980Sstevel@tonic-gate     char sglobbed = globbed;
3990Sstevel@tonic-gate 
4000Sstevel@tonic-gate     if (*s == '.' && *p != '.')
4010Sstevel@tonic-gate 	return (0);
4020Sstevel@tonic-gate     sentp = entp;
4030Sstevel@tonic-gate     entp = s;
404*12333SMilan.Jurik@Sun.COM     c = amatch(s, p, check_ncargs);
4050Sstevel@tonic-gate     entp = sentp;
4060Sstevel@tonic-gate     globbed = sglobbed;
4070Sstevel@tonic-gate     return (c);
4080Sstevel@tonic-gate }
4090Sstevel@tonic-gate 
amatch(char * s,char * p,boolean_t check_ncargs)410*12333SMilan.Jurik@Sun.COM static int amatch(char *s, char *p, boolean_t check_ncargs)
4110Sstevel@tonic-gate {
4120Sstevel@tonic-gate     register int scc;
4130Sstevel@tonic-gate     int ok, lc;
4140Sstevel@tonic-gate     char *sgpathp;
4150Sstevel@tonic-gate     struct stat stb;
4160Sstevel@tonic-gate     int c, cc;
4170Sstevel@tonic-gate 
4180Sstevel@tonic-gate     globbed = 1;
4190Sstevel@tonic-gate     for (;;) {
4200Sstevel@tonic-gate 	scc = *s++ & TRIM;
4210Sstevel@tonic-gate 	switch (c = *p++) {
4220Sstevel@tonic-gate 
4230Sstevel@tonic-gate 	case '{':
4240Sstevel@tonic-gate 	    return (execbrc(p - 1, s - 1));
4250Sstevel@tonic-gate 
4260Sstevel@tonic-gate 	case '[':
4270Sstevel@tonic-gate 	    ok = 0;
4280Sstevel@tonic-gate 	    lc = 077777;
4290Sstevel@tonic-gate 	    while ((cc = *p++)) {
4300Sstevel@tonic-gate 		if (cc == ']') {
4310Sstevel@tonic-gate 		    if (ok)
4320Sstevel@tonic-gate 			break;
4330Sstevel@tonic-gate 		    return (0);
4340Sstevel@tonic-gate 		}
4350Sstevel@tonic-gate 		if (cc == '-') {
4360Sstevel@tonic-gate 		    if (lc <= scc && scc <= *p++)
4370Sstevel@tonic-gate 			ok++;
4380Sstevel@tonic-gate 		}
4390Sstevel@tonic-gate 		else if (scc == (lc = cc))
4400Sstevel@tonic-gate 		    ok++;
4410Sstevel@tonic-gate 	    }
4420Sstevel@tonic-gate 	    if (cc == 0) {
4430Sstevel@tonic-gate 		globerr = "Missing ]";
4440Sstevel@tonic-gate 		return (0);
4450Sstevel@tonic-gate 	    }
4460Sstevel@tonic-gate 	    continue;
4470Sstevel@tonic-gate 
4480Sstevel@tonic-gate 	case '*':
4490Sstevel@tonic-gate 	    if (!*p)
4500Sstevel@tonic-gate 		return (1);
4510Sstevel@tonic-gate 	    if (*p == '/') {
4520Sstevel@tonic-gate 		p++;
4530Sstevel@tonic-gate 		goto slash;
4540Sstevel@tonic-gate 	    } else if (*p == '*') {
4550Sstevel@tonic-gate 		s--;
4560Sstevel@tonic-gate 		continue;
4570Sstevel@tonic-gate 	    }
4580Sstevel@tonic-gate 	    s--;
4590Sstevel@tonic-gate 	    do {
460*12333SMilan.Jurik@Sun.COM 		if (amatch(s, p, check_ncargs))
4610Sstevel@tonic-gate 		    return (1);
4620Sstevel@tonic-gate 	    } while (*s++);
4630Sstevel@tonic-gate 	    return (0);
4640Sstevel@tonic-gate 
4650Sstevel@tonic-gate 	case 0:
4660Sstevel@tonic-gate 	    return (scc == 0);
4670Sstevel@tonic-gate 
4680Sstevel@tonic-gate 	default:
4690Sstevel@tonic-gate 	    if (c != scc)
4700Sstevel@tonic-gate 		return (0);
4710Sstevel@tonic-gate 	    continue;
4720Sstevel@tonic-gate 
4730Sstevel@tonic-gate 	case '?':
4740Sstevel@tonic-gate 	    if (scc == 0)
4750Sstevel@tonic-gate 		return (0);
4760Sstevel@tonic-gate 	    continue;
4770Sstevel@tonic-gate 
4780Sstevel@tonic-gate 	case '/':
4790Sstevel@tonic-gate 	    if (scc)
4800Sstevel@tonic-gate 		return (0);
4810Sstevel@tonic-gate 	  slash:
4820Sstevel@tonic-gate 	    s = entp;
4830Sstevel@tonic-gate 	    sgpathp = gpathp;
4840Sstevel@tonic-gate 	    while (*s)
4850Sstevel@tonic-gate 		addpath(*s++);
4860Sstevel@tonic-gate 	    addpath('/');
4870Sstevel@tonic-gate 	    if (stat(gpath, &stb) == 0 && isdir(stb))
4880Sstevel@tonic-gate 		if (*p == 0) {
489*12333SMilan.Jurik@Sun.COM 		    Gcat(gpath, "", check_ncargs);
4900Sstevel@tonic-gate 		    globcnt++;
4910Sstevel@tonic-gate 		}
4920Sstevel@tonic-gate 		else
493*12333SMilan.Jurik@Sun.COM 		    expand(p, check_ncargs);
4940Sstevel@tonic-gate 	    gpathp = sgpathp;
4950Sstevel@tonic-gate 	    *gpathp = 0;
4960Sstevel@tonic-gate 	    return (0);
4970Sstevel@tonic-gate 	}
4980Sstevel@tonic-gate     }
4990Sstevel@tonic-gate }
5000Sstevel@tonic-gate 
Gcat(register char * s1,register char * s2,boolean_t check_ncargs)501*12333SMilan.Jurik@Sun.COM static void Gcat(register char *s1, register char *s2, boolean_t check_ncargs)
5020Sstevel@tonic-gate {
5030Sstevel@tonic-gate     register size_t len = strlen(s1) + strlen(s2) + 1;
5040Sstevel@tonic-gate 
5050Sstevel@tonic-gate     if (globerr)
5060Sstevel@tonic-gate 	return;
507*12333SMilan.Jurik@Sun.COM     if ((check_ncargs) && ((len + sizeof (char *)) >= gnleft)) {
5080Sstevel@tonic-gate 	globerr = "Arguments too long";
5090Sstevel@tonic-gate 	return;
5100Sstevel@tonic-gate     }
5110Sstevel@tonic-gate     if (len > MAXPATHLEN) {
5120Sstevel@tonic-gate 	globerr = "Pathname too long";
5130Sstevel@tonic-gate 	return;
5140Sstevel@tonic-gate     }
5150Sstevel@tonic-gate     if (gargc >= agargv_size - 1) {
5160Sstevel@tonic-gate 	char **tmp;
5170Sstevel@tonic-gate 
5180Sstevel@tonic-gate 	tmp = (char **)realloc(agargv,
5190Sstevel@tonic-gate 		(agargv_size + GAVSIZ) * sizeof (char *));
5200Sstevel@tonic-gate 	if (tmp == NULL) {
5210Sstevel@tonic-gate 	    fatal("Out of memory");
5220Sstevel@tonic-gate 	} else {
5230Sstevel@tonic-gate 	    agargv = tmp;
5240Sstevel@tonic-gate 	    agargv_size += GAVSIZ;
5250Sstevel@tonic-gate 	}
5260Sstevel@tonic-gate 	gargv = agargv;
5270Sstevel@tonic-gate 	sortbas = agargv;
5280Sstevel@tonic-gate     }
5290Sstevel@tonic-gate     gargc++;
530*12333SMilan.Jurik@Sun.COM     if (check_ncargs)
531*12333SMilan.Jurik@Sun.COM 	gnleft -= len + sizeof (char *);
5320Sstevel@tonic-gate     gargv[gargc] = 0;
5330Sstevel@tonic-gate     gargv[gargc - 1] = strspl(s1, s2);
5340Sstevel@tonic-gate }
5350Sstevel@tonic-gate 
addpath(char c)5360Sstevel@tonic-gate static void addpath(char c)
5370Sstevel@tonic-gate {
5380Sstevel@tonic-gate 
5390Sstevel@tonic-gate     if (gpathp >= lastgpathp)
5400Sstevel@tonic-gate 	globerr = "Pathname too long";
5410Sstevel@tonic-gate     else {
5420Sstevel@tonic-gate 	*gpathp++ = c;
5430Sstevel@tonic-gate 	*gpathp = 0;
5440Sstevel@tonic-gate     }
5450Sstevel@tonic-gate }
5460Sstevel@tonic-gate 
rscan(register char ** t,int (* f)(register char))5470Sstevel@tonic-gate static void rscan(register char **t, int (*f) (register char))
5480Sstevel@tonic-gate {
5490Sstevel@tonic-gate     register char *p, c;
5500Sstevel@tonic-gate 
5510Sstevel@tonic-gate     while ((p = *t++)) {
5520Sstevel@tonic-gate 	if (*p == '~')
5530Sstevel@tonic-gate 	    gflag |= 2;
5540Sstevel@tonic-gate 	else if (eq(p, "{") || eq(p, "{}"))
5550Sstevel@tonic-gate 	    continue;
5560Sstevel@tonic-gate 	while ((c = *p++))
5570Sstevel@tonic-gate 	    (*f) (c);
5580Sstevel@tonic-gate     }
5590Sstevel@tonic-gate }
tglob(register char c)5600Sstevel@tonic-gate static int tglob(register char c)
5610Sstevel@tonic-gate {
5620Sstevel@tonic-gate     if (any(c, globchars))
5630Sstevel@tonic-gate 	gflag |= c == '{' ? 2 : 1;
5640Sstevel@tonic-gate     return (c);
5650Sstevel@tonic-gate }
5660Sstevel@tonic-gate 
letter(register char c)5670Sstevel@tonic-gate int letter(register char c)
5680Sstevel@tonic-gate {
5690Sstevel@tonic-gate     return (((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z'))
5700Sstevel@tonic-gate 	    || (c == '_'));
5710Sstevel@tonic-gate }
5720Sstevel@tonic-gate 
digit(register char c)5730Sstevel@tonic-gate int digit(register char c)
5740Sstevel@tonic-gate {
5750Sstevel@tonic-gate     return (c >= '0' && c <= '9');
5760Sstevel@tonic-gate }
5770Sstevel@tonic-gate 
any(register int c,register char * s)5780Sstevel@tonic-gate int any(register int c, register char *s)
5790Sstevel@tonic-gate {
5800Sstevel@tonic-gate     while (*s)
5810Sstevel@tonic-gate 	if (*s++ == c)
5820Sstevel@tonic-gate 	    return (1);
5830Sstevel@tonic-gate     return (0);
5840Sstevel@tonic-gate }
5850Sstevel@tonic-gate 
blklen(register char ** av)5860Sstevel@tonic-gate int blklen(register char **av)
5870Sstevel@tonic-gate {
5880Sstevel@tonic-gate     register int i = 0;
5890Sstevel@tonic-gate 
5900Sstevel@tonic-gate     while (*av++)
5910Sstevel@tonic-gate 	i++;
5920Sstevel@tonic-gate     return (i);
5930Sstevel@tonic-gate }
5940Sstevel@tonic-gate 
blkcpy(char ** oav,register char ** bv)5950Sstevel@tonic-gate char **blkcpy(char **oav, register char **bv)
5960Sstevel@tonic-gate {
5970Sstevel@tonic-gate     register char **av = oav;
5980Sstevel@tonic-gate 
5990Sstevel@tonic-gate     while ((*av++ = *bv++))
6000Sstevel@tonic-gate 	continue;
6010Sstevel@tonic-gate     return (oav);
6020Sstevel@tonic-gate }
6030Sstevel@tonic-gate 
blkfree(char ** av0)6040Sstevel@tonic-gate void blkfree(char **av0)
6050Sstevel@tonic-gate {
6060Sstevel@tonic-gate     register char **av = av0;
6070Sstevel@tonic-gate 
6080Sstevel@tonic-gate     if (av) {
6090Sstevel@tonic-gate 	while (*av)
6100Sstevel@tonic-gate 	    free(*av++);
6110Sstevel@tonic-gate     }
6120Sstevel@tonic-gate }
6130Sstevel@tonic-gate 
strspl(register char * cp,register char * dp)6140Sstevel@tonic-gate char *strspl(register char *cp, register char *dp)
6150Sstevel@tonic-gate {
6160Sstevel@tonic-gate     int bufsize = strlen(cp) + strlen(dp) + 1;
6170Sstevel@tonic-gate     char *ep = malloc(bufsize);
6180Sstevel@tonic-gate 
6190Sstevel@tonic-gate     if (ep == NULL)
6200Sstevel@tonic-gate 	fatal("Out of memory");
6210Sstevel@tonic-gate     (void) strlcpy(ep, cp, bufsize);
6220Sstevel@tonic-gate     (void) strlcat(ep, dp, bufsize);
6230Sstevel@tonic-gate     return (ep);
6240Sstevel@tonic-gate }
6250Sstevel@tonic-gate 
copyblk(register char ** v)6260Sstevel@tonic-gate char **copyblk(register char **v)
6270Sstevel@tonic-gate {
6280Sstevel@tonic-gate     register char **nv = (char **) malloc((unsigned) ((blklen(v) + 1) *
6290Sstevel@tonic-gate 						      sizeof(char **)));
6300Sstevel@tonic-gate     if (nv == (char **) 0)
6310Sstevel@tonic-gate 	fatal("Out of memory");
6320Sstevel@tonic-gate 
6330Sstevel@tonic-gate     return (blkcpy(nv, v));
6340Sstevel@tonic-gate }
6350Sstevel@tonic-gate 
strend(register char * cp)6360Sstevel@tonic-gate static char *strend(register char *cp)
6370Sstevel@tonic-gate {
6380Sstevel@tonic-gate     while (*cp)
6390Sstevel@tonic-gate 	cp++;
6400Sstevel@tonic-gate     return (cp);
6410Sstevel@tonic-gate }
6420Sstevel@tonic-gate /*
6430Sstevel@tonic-gate  * Extract a home directory from the password file
6440Sstevel@tonic-gate  * The argument points to a buffer where the name of the
6450Sstevel@tonic-gate  * user whose home directory is sought is currently.
6460Sstevel@tonic-gate  * We write the home directory of the user back there.
6470Sstevel@tonic-gate  */
gethdir(char * home)6480Sstevel@tonic-gate static int gethdir(char *home)
6490Sstevel@tonic-gate {
6500Sstevel@tonic-gate #ifdef OTHER_PASSWD
6510Sstevel@tonic-gate     register struct passwd *pp = bero_getpwnam(home, _path_passwd);
6520Sstevel@tonic-gate #else
6530Sstevel@tonic-gate     register struct passwd *pp = getpwnam(home);
6540Sstevel@tonic-gate #endif
6550Sstevel@tonic-gate     register char *root = NULL;
6560Sstevel@tonic-gate     if (!pp || home + strlen(pp->pw_dir) >= lastgpathp)
6570Sstevel@tonic-gate 	return (1);
6580Sstevel@tonic-gate     root = strstr(pp->pw_dir, "/./");
6590Sstevel@tonic-gate     (void) strlcpy(home, root ? (root + 2) : pp->pw_dir, lastgpathp - home);
6600Sstevel@tonic-gate 
6610Sstevel@tonic-gate     return (0);
6620Sstevel@tonic-gate }
663