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