1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 3*0Sstevel@tonic-gate * Use is subject to license terms. 4*0Sstevel@tonic-gate */ 5*0Sstevel@tonic-gate 6*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 7*0Sstevel@tonic-gate 8*0Sstevel@tonic-gate /**************************************************************************** 9*0Sstevel@tonic-gate Copyright (c) 1999,2000,2001 WU-FTPD Development Group. 10*0Sstevel@tonic-gate All rights reserved. 11*0Sstevel@tonic-gate 12*0Sstevel@tonic-gate Portions Copyright (c) 1980, 1985, 1988, 1989, 1990, 1991, 1993, 1994 13*0Sstevel@tonic-gate The Regents of the University of California. 14*0Sstevel@tonic-gate Portions Copyright (c) 1993, 1994 Washington University in Saint Louis. 15*0Sstevel@tonic-gate Portions Copyright (c) 1996, 1998 Berkeley Software Design, Inc. 16*0Sstevel@tonic-gate Portions Copyright (c) 1989 Massachusetts Institute of Technology. 17*0Sstevel@tonic-gate Portions Copyright (c) 1998 Sendmail, Inc. 18*0Sstevel@tonic-gate Portions Copyright (c) 1983, 1995, 1996, 1997 Eric P. Allman. 19*0Sstevel@tonic-gate Portions Copyright (c) 1997 by Stan Barber. 20*0Sstevel@tonic-gate Portions Copyright (c) 1997 by Kent Landfield. 21*0Sstevel@tonic-gate Portions Copyright (c) 1991, 1992, 1993, 1994, 1995, 1996, 1997 22*0Sstevel@tonic-gate Free Software Foundation, Inc. 23*0Sstevel@tonic-gate 24*0Sstevel@tonic-gate Use and distribution of this software and its source code are governed 25*0Sstevel@tonic-gate by the terms and conditions of the WU-FTPD Software License ("LICENSE"). 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate If you did not receive a copy of the license, it may be obtained online 28*0Sstevel@tonic-gate at http://www.wu-ftpd.org/license.html. 29*0Sstevel@tonic-gate 30*0Sstevel@tonic-gate $Id: glob.c,v 1.14.2.2 2001/11/29 17:01:38 wuftpd Exp $ 31*0Sstevel@tonic-gate 32*0Sstevel@tonic-gate ****************************************************************************/ 33*0Sstevel@tonic-gate /* 34*0Sstevel@tonic-gate * C-shell glob for random programs. 35*0Sstevel@tonic-gate */ 36*0Sstevel@tonic-gate 37*0Sstevel@tonic-gate #include "config.h" 38*0Sstevel@tonic-gate 39*0Sstevel@tonic-gate #include <sys/param.h> 40*0Sstevel@tonic-gate #include <sys/stat.h> 41*0Sstevel@tonic-gate 42*0Sstevel@tonic-gate #ifdef HAVE_DIRENT_H 43*0Sstevel@tonic-gate #include <dirent.h> 44*0Sstevel@tonic-gate #else 45*0Sstevel@tonic-gate #include <sys/dir.h> 46*0Sstevel@tonic-gate #endif 47*0Sstevel@tonic-gate 48*0Sstevel@tonic-gate #include <pwd.h> 49*0Sstevel@tonic-gate #include <errno.h> 50*0Sstevel@tonic-gate #include <stdio.h> 51*0Sstevel@tonic-gate #include <stdlib.h> 52*0Sstevel@tonic-gate #include <string.h> 53*0Sstevel@tonic-gate 54*0Sstevel@tonic-gate #include "proto.h" 55*0Sstevel@tonic-gate 56*0Sstevel@tonic-gate #define QUOTE 0200 57*0Sstevel@tonic-gate #define TRIM 0177 58*0Sstevel@tonic-gate #define eq(a,b) (strcmp(a, b)==0) 59*0Sstevel@tonic-gate #define GAVSIZ (1024 * 8) 60*0Sstevel@tonic-gate #define isdir(d) ((d.st_mode & S_IFMT) == S_IFDIR) 61*0Sstevel@tonic-gate 62*0Sstevel@tonic-gate static char **gargv; /* Pointer to the (stack) arglist */ 63*0Sstevel@tonic-gate static char **agargv; 64*0Sstevel@tonic-gate static size_t agargv_size; 65*0Sstevel@tonic-gate static int gargc; /* Number args in gargv */ 66*0Sstevel@tonic-gate static size_t gnleft; 67*0Sstevel@tonic-gate static short gflag; 68*0Sstevel@tonic-gate static int tglob(register char); 69*0Sstevel@tonic-gate 70*0Sstevel@tonic-gate /* Prototypes */ 71*0Sstevel@tonic-gate 72*0Sstevel@tonic-gate static char *strend(register char *); 73*0Sstevel@tonic-gate static void addpath(char); 74*0Sstevel@tonic-gate static void ginit(char **); 75*0Sstevel@tonic-gate static void collect(register char *); 76*0Sstevel@tonic-gate static void acollect(register char *); 77*0Sstevel@tonic-gate static void sort(void); 78*0Sstevel@tonic-gate static void expand(char *); 79*0Sstevel@tonic-gate static void matchdir(char *); 80*0Sstevel@tonic-gate static int execbrc(char *, char *); 81*0Sstevel@tonic-gate static int match(char *, char *); 82*0Sstevel@tonic-gate static int amatch(char *, char *); 83*0Sstevel@tonic-gate static void Gcat(register char *, register char *); 84*0Sstevel@tonic-gate static void rscan(register char **, int (*f) (register char)); 85*0Sstevel@tonic-gate static int tglob(register char c); 86*0Sstevel@tonic-gate static int gethdir(char *); 87*0Sstevel@tonic-gate 88*0Sstevel@tonic-gate int letter(register char); 89*0Sstevel@tonic-gate int digit(register char); 90*0Sstevel@tonic-gate int any(register int, register char *); 91*0Sstevel@tonic-gate int blklen(register char **); 92*0Sstevel@tonic-gate char **blkcpy(char **, register char **); 93*0Sstevel@tonic-gate 94*0Sstevel@tonic-gate char *globerr; 95*0Sstevel@tonic-gate char *home; 96*0Sstevel@tonic-gate extern int errno; 97*0Sstevel@tonic-gate 98*0Sstevel@tonic-gate static int globcnt; 99*0Sstevel@tonic-gate 100*0Sstevel@tonic-gate char *globchars = "`{[*?"; 101*0Sstevel@tonic-gate 102*0Sstevel@tonic-gate static char *gpath, *gpathp, *lastgpathp; 103*0Sstevel@tonic-gate static int globbed; 104*0Sstevel@tonic-gate static char *entp; 105*0Sstevel@tonic-gate static char **sortbas; 106*0Sstevel@tonic-gate 107*0Sstevel@tonic-gate #ifdef OTHER_PASSWD 108*0Sstevel@tonic-gate #include "getpwnam.h" 109*0Sstevel@tonic-gate extern char _path_passwd[]; 110*0Sstevel@tonic-gate #endif 111*0Sstevel@tonic-gate 112*0Sstevel@tonic-gate char **ftpglob(register char *v) 113*0Sstevel@tonic-gate { 114*0Sstevel@tonic-gate char agpath[BUFSIZ]; 115*0Sstevel@tonic-gate char *vv[2]; 116*0Sstevel@tonic-gate 117*0Sstevel@tonic-gate if (agargv == NULL) { 118*0Sstevel@tonic-gate agargv = (char **) malloc(GAVSIZ * sizeof (char *)); 119*0Sstevel@tonic-gate if (agargv == NULL) { 120*0Sstevel@tonic-gate fatal("Out of memory"); 121*0Sstevel@tonic-gate } 122*0Sstevel@tonic-gate agargv_size = GAVSIZ; 123*0Sstevel@tonic-gate } 124*0Sstevel@tonic-gate fixpath(v); 125*0Sstevel@tonic-gate if (v[0] == '\0') 126*0Sstevel@tonic-gate v = "*"; 127*0Sstevel@tonic-gate else if ((strlen(v) > 1) && (v[strlen(v) - 1] == '/')) 128*0Sstevel@tonic-gate v[strlen(v) - 1] = '\0'; 129*0Sstevel@tonic-gate 130*0Sstevel@tonic-gate vv[0] = v; 131*0Sstevel@tonic-gate vv[1] = NULL; 132*0Sstevel@tonic-gate globerr = NULL; 133*0Sstevel@tonic-gate gflag = 0; 134*0Sstevel@tonic-gate rscan(vv, tglob); 135*0Sstevel@tonic-gate if (gflag == 0) { 136*0Sstevel@tonic-gate vv[0] = strspl(v, ""); 137*0Sstevel@tonic-gate return (copyblk(vv)); 138*0Sstevel@tonic-gate } 139*0Sstevel@tonic-gate 140*0Sstevel@tonic-gate globerr = NULL; 141*0Sstevel@tonic-gate gpath = agpath; 142*0Sstevel@tonic-gate gpathp = gpath; 143*0Sstevel@tonic-gate *gpathp = 0; 144*0Sstevel@tonic-gate lastgpathp = &gpath[sizeof agpath - 2]; 145*0Sstevel@tonic-gate ginit(agargv); 146*0Sstevel@tonic-gate globcnt = 0; 147*0Sstevel@tonic-gate collect(v); 148*0Sstevel@tonic-gate if (globcnt == 0 && (gflag & 1)) { 149*0Sstevel@tonic-gate blkfree(gargv), gargv = 0; 150*0Sstevel@tonic-gate return (0); 151*0Sstevel@tonic-gate } 152*0Sstevel@tonic-gate else 153*0Sstevel@tonic-gate return (gargv = copyblk(gargv)); 154*0Sstevel@tonic-gate } 155*0Sstevel@tonic-gate 156*0Sstevel@tonic-gate static void ginit(char **agargv) 157*0Sstevel@tonic-gate { 158*0Sstevel@tonic-gate 159*0Sstevel@tonic-gate agargv[0] = 0; 160*0Sstevel@tonic-gate gargv = agargv; 161*0Sstevel@tonic-gate sortbas = agargv; 162*0Sstevel@tonic-gate gargc = 0; 163*0Sstevel@tonic-gate gnleft = NCARGS - 4; 164*0Sstevel@tonic-gate } 165*0Sstevel@tonic-gate 166*0Sstevel@tonic-gate static void collect(register char *as) 167*0Sstevel@tonic-gate { 168*0Sstevel@tonic-gate if (eq(as, "{") || eq(as, "{}")) { 169*0Sstevel@tonic-gate Gcat(as, ""); 170*0Sstevel@tonic-gate sort(); 171*0Sstevel@tonic-gate } 172*0Sstevel@tonic-gate else 173*0Sstevel@tonic-gate acollect(as); 174*0Sstevel@tonic-gate } 175*0Sstevel@tonic-gate 176*0Sstevel@tonic-gate static void acollect(register char *as) 177*0Sstevel@tonic-gate { 178*0Sstevel@tonic-gate register int ogargc = gargc; 179*0Sstevel@tonic-gate 180*0Sstevel@tonic-gate gpathp = gpath; 181*0Sstevel@tonic-gate *gpathp = 0; 182*0Sstevel@tonic-gate globbed = 0; 183*0Sstevel@tonic-gate expand(as); 184*0Sstevel@tonic-gate if (gargc != ogargc) 185*0Sstevel@tonic-gate sort(); 186*0Sstevel@tonic-gate } 187*0Sstevel@tonic-gate 188*0Sstevel@tonic-gate static int 189*0Sstevel@tonic-gate argcmp(const void *p1, const void *p2) 190*0Sstevel@tonic-gate { 191*0Sstevel@tonic-gate char *s1 = *(char **) p1; 192*0Sstevel@tonic-gate char *s2 = *(char **) p2; 193*0Sstevel@tonic-gate 194*0Sstevel@tonic-gate return (strcmp(s1, s2)); 195*0Sstevel@tonic-gate } 196*0Sstevel@tonic-gate 197*0Sstevel@tonic-gate static void sort(void) 198*0Sstevel@tonic-gate { 199*0Sstevel@tonic-gate char **Gvp = &gargv[gargc]; 200*0Sstevel@tonic-gate 201*0Sstevel@tonic-gate if (!globerr) 202*0Sstevel@tonic-gate qsort(sortbas, Gvp - sortbas, sizeof (*sortbas), argcmp); 203*0Sstevel@tonic-gate sortbas = Gvp; 204*0Sstevel@tonic-gate } 205*0Sstevel@tonic-gate 206*0Sstevel@tonic-gate static void expand(char *as) 207*0Sstevel@tonic-gate { 208*0Sstevel@tonic-gate register char *cs; 209*0Sstevel@tonic-gate register char *sgpathp, *oldcs; 210*0Sstevel@tonic-gate struct stat stb; 211*0Sstevel@tonic-gate 212*0Sstevel@tonic-gate if (globerr) 213*0Sstevel@tonic-gate return; 214*0Sstevel@tonic-gate sgpathp = gpathp; 215*0Sstevel@tonic-gate cs = as; 216*0Sstevel@tonic-gate if (*cs == '~' && gpathp == gpath) { 217*0Sstevel@tonic-gate addpath('~'); 218*0Sstevel@tonic-gate for (cs++; letter(*cs) || digit(*cs) || *cs == '-';) 219*0Sstevel@tonic-gate addpath(*cs++); 220*0Sstevel@tonic-gate if (!*cs || *cs == '/') { 221*0Sstevel@tonic-gate if (gpathp != gpath + 1) { 222*0Sstevel@tonic-gate *gpathp = 0; 223*0Sstevel@tonic-gate if (gethdir(gpath + 1)) 224*0Sstevel@tonic-gate globerr = "Unknown user name after ~"; 225*0Sstevel@tonic-gate /* memmove used as strings overlap */ 226*0Sstevel@tonic-gate (void) memmove(gpath, gpath + 1, strlen(gpath + 1) + 1); 227*0Sstevel@tonic-gate } 228*0Sstevel@tonic-gate else 229*0Sstevel@tonic-gate (void) strlcpy(gpath, home, BUFSIZ); 230*0Sstevel@tonic-gate gpathp = strend(gpath); 231*0Sstevel@tonic-gate } 232*0Sstevel@tonic-gate } 233*0Sstevel@tonic-gate while (!any(*cs, globchars)) { 234*0Sstevel@tonic-gate if (*cs == 0) { 235*0Sstevel@tonic-gate if (!globbed) 236*0Sstevel@tonic-gate Gcat(gpath, ""); 237*0Sstevel@tonic-gate else if (stat(gpath, &stb) >= 0) { 238*0Sstevel@tonic-gate Gcat(gpath, ""); 239*0Sstevel@tonic-gate globcnt++; 240*0Sstevel@tonic-gate } 241*0Sstevel@tonic-gate goto endit; 242*0Sstevel@tonic-gate } 243*0Sstevel@tonic-gate addpath(*cs++); 244*0Sstevel@tonic-gate } 245*0Sstevel@tonic-gate oldcs = cs; 246*0Sstevel@tonic-gate while (cs > as && *cs != '/') 247*0Sstevel@tonic-gate cs--, gpathp--; 248*0Sstevel@tonic-gate if (*cs == '/') 249*0Sstevel@tonic-gate cs++, gpathp++; 250*0Sstevel@tonic-gate *gpathp = 0; 251*0Sstevel@tonic-gate if (*oldcs == '{') { 252*0Sstevel@tonic-gate (void) execbrc(cs, ((char *) 0)); 253*0Sstevel@tonic-gate return; 254*0Sstevel@tonic-gate } 255*0Sstevel@tonic-gate matchdir(cs); 256*0Sstevel@tonic-gate endit: 257*0Sstevel@tonic-gate gpathp = sgpathp; 258*0Sstevel@tonic-gate *gpathp = 0; 259*0Sstevel@tonic-gate } 260*0Sstevel@tonic-gate 261*0Sstevel@tonic-gate static void matchdir(char *pattern) 262*0Sstevel@tonic-gate { 263*0Sstevel@tonic-gate struct stat stb; 264*0Sstevel@tonic-gate 265*0Sstevel@tonic-gate #ifdef HAVE_DIRENT_H 266*0Sstevel@tonic-gate register struct dirent *dp; 267*0Sstevel@tonic-gate #else 268*0Sstevel@tonic-gate register struct direct *dp; 269*0Sstevel@tonic-gate #endif 270*0Sstevel@tonic-gate 271*0Sstevel@tonic-gate DIR *dirp; 272*0Sstevel@tonic-gate 273*0Sstevel@tonic-gate dirp = opendir(*gpath == '\0' ? "." : gpath); 274*0Sstevel@tonic-gate if (dirp == NULL) { 275*0Sstevel@tonic-gate if (globbed) 276*0Sstevel@tonic-gate return; 277*0Sstevel@tonic-gate goto patherr2; 278*0Sstevel@tonic-gate } 279*0Sstevel@tonic-gate #ifdef HAVE_DIRFD 280*0Sstevel@tonic-gate if (fstat(dirfd(dirp), &stb) < 0) 281*0Sstevel@tonic-gate #else /* HAVE_DIRFD */ 282*0Sstevel@tonic-gate if (fstat(dirp->dd_fd, &stb) < 0) 283*0Sstevel@tonic-gate #endif /* HAVE_DIRFD */ 284*0Sstevel@tonic-gate goto patherr1; 285*0Sstevel@tonic-gate if (!isdir(stb)) { 286*0Sstevel@tonic-gate errno = ENOTDIR; 287*0Sstevel@tonic-gate goto patherr1; 288*0Sstevel@tonic-gate } 289*0Sstevel@tonic-gate while (!globerr && ((dp = readdir(dirp)) != NULL)) { 290*0Sstevel@tonic-gate if (dp->d_ino == 0) 291*0Sstevel@tonic-gate continue; 292*0Sstevel@tonic-gate if (match(dp->d_name, pattern)) { 293*0Sstevel@tonic-gate Gcat(gpath, dp->d_name); 294*0Sstevel@tonic-gate globcnt++; 295*0Sstevel@tonic-gate } 296*0Sstevel@tonic-gate } 297*0Sstevel@tonic-gate closedir(dirp); 298*0Sstevel@tonic-gate return; 299*0Sstevel@tonic-gate 300*0Sstevel@tonic-gate patherr1: 301*0Sstevel@tonic-gate closedir(dirp); 302*0Sstevel@tonic-gate patherr2: 303*0Sstevel@tonic-gate globerr = "Bad directory components"; 304*0Sstevel@tonic-gate } 305*0Sstevel@tonic-gate 306*0Sstevel@tonic-gate static int execbrc(char *p, char *s) 307*0Sstevel@tonic-gate { 308*0Sstevel@tonic-gate char restbuf[BUFSIZ + 2]; 309*0Sstevel@tonic-gate char *restbufend = &restbuf[sizeof(restbuf)]; 310*0Sstevel@tonic-gate register char *pe, *pm, *pl; 311*0Sstevel@tonic-gate int brclev = 0; 312*0Sstevel@tonic-gate char *lm, savec, *sgpathp; 313*0Sstevel@tonic-gate 314*0Sstevel@tonic-gate for (lm = restbuf; *p != '{'; *lm++ = *p++) { 315*0Sstevel@tonic-gate if (lm >= restbufend) 316*0Sstevel@tonic-gate return (0); 317*0Sstevel@tonic-gate } 318*0Sstevel@tonic-gate for (pe = ++p; *pe; pe++) { 319*0Sstevel@tonic-gate switch (*pe) { 320*0Sstevel@tonic-gate 321*0Sstevel@tonic-gate case '{': 322*0Sstevel@tonic-gate brclev++; 323*0Sstevel@tonic-gate continue; 324*0Sstevel@tonic-gate 325*0Sstevel@tonic-gate case '}': 326*0Sstevel@tonic-gate if (brclev == 0) 327*0Sstevel@tonic-gate goto pend; 328*0Sstevel@tonic-gate brclev--; 329*0Sstevel@tonic-gate continue; 330*0Sstevel@tonic-gate 331*0Sstevel@tonic-gate case '[': 332*0Sstevel@tonic-gate for (pe++; *pe && *pe != ']'; pe++) 333*0Sstevel@tonic-gate continue; 334*0Sstevel@tonic-gate if (!*pe) { 335*0Sstevel@tonic-gate globerr = "Missing ]"; 336*0Sstevel@tonic-gate return (0); 337*0Sstevel@tonic-gate } 338*0Sstevel@tonic-gate continue; 339*0Sstevel@tonic-gate } 340*0Sstevel@tonic-gate } 341*0Sstevel@tonic-gate pend: 342*0Sstevel@tonic-gate if (brclev || !*pe) { 343*0Sstevel@tonic-gate globerr = "Missing }"; 344*0Sstevel@tonic-gate return (0); 345*0Sstevel@tonic-gate } 346*0Sstevel@tonic-gate for (pl = pm = p; pm <= pe; pm++) { 347*0Sstevel@tonic-gate switch (*pm & (QUOTE | TRIM)) { 348*0Sstevel@tonic-gate 349*0Sstevel@tonic-gate case '{': 350*0Sstevel@tonic-gate brclev++; 351*0Sstevel@tonic-gate continue; 352*0Sstevel@tonic-gate 353*0Sstevel@tonic-gate case '}': 354*0Sstevel@tonic-gate if (brclev) { 355*0Sstevel@tonic-gate brclev--; 356*0Sstevel@tonic-gate continue; 357*0Sstevel@tonic-gate } 358*0Sstevel@tonic-gate goto doit; 359*0Sstevel@tonic-gate 360*0Sstevel@tonic-gate case ',' | QUOTE: 361*0Sstevel@tonic-gate case ',': 362*0Sstevel@tonic-gate if (brclev) 363*0Sstevel@tonic-gate continue; 364*0Sstevel@tonic-gate doit: 365*0Sstevel@tonic-gate savec = *pm; 366*0Sstevel@tonic-gate *pm = 0; 367*0Sstevel@tonic-gate if (lm + strlen(pl) + strlen(pe + 1) >= restbufend) 368*0Sstevel@tonic-gate return (0); 369*0Sstevel@tonic-gate (void) strlcpy(lm, pl, restbufend - lm); 370*0Sstevel@tonic-gate (void) strlcat(restbuf, pe + 1, sizeof(restbuf)); 371*0Sstevel@tonic-gate *pm = savec; 372*0Sstevel@tonic-gate if (s == 0) { 373*0Sstevel@tonic-gate sgpathp = gpathp; 374*0Sstevel@tonic-gate expand(restbuf); 375*0Sstevel@tonic-gate gpathp = sgpathp; 376*0Sstevel@tonic-gate *gpathp = 0; 377*0Sstevel@tonic-gate } 378*0Sstevel@tonic-gate else if (amatch(s, restbuf)) 379*0Sstevel@tonic-gate return (1); 380*0Sstevel@tonic-gate sort(); 381*0Sstevel@tonic-gate pl = pm + 1; 382*0Sstevel@tonic-gate continue; 383*0Sstevel@tonic-gate 384*0Sstevel@tonic-gate case '[': 385*0Sstevel@tonic-gate for (pm++; *pm && *pm != ']'; pm++) 386*0Sstevel@tonic-gate continue; 387*0Sstevel@tonic-gate if (!*pm) { 388*0Sstevel@tonic-gate globerr = "Missing ]"; 389*0Sstevel@tonic-gate return (0); 390*0Sstevel@tonic-gate } 391*0Sstevel@tonic-gate continue; 392*0Sstevel@tonic-gate } 393*0Sstevel@tonic-gate } 394*0Sstevel@tonic-gate return (0); 395*0Sstevel@tonic-gate } 396*0Sstevel@tonic-gate 397*0Sstevel@tonic-gate static int match(char *s, char *p) 398*0Sstevel@tonic-gate { 399*0Sstevel@tonic-gate register int c; 400*0Sstevel@tonic-gate register char *sentp; 401*0Sstevel@tonic-gate char sglobbed = globbed; 402*0Sstevel@tonic-gate 403*0Sstevel@tonic-gate if (*s == '.' && *p != '.') 404*0Sstevel@tonic-gate return (0); 405*0Sstevel@tonic-gate sentp = entp; 406*0Sstevel@tonic-gate entp = s; 407*0Sstevel@tonic-gate c = amatch(s, p); 408*0Sstevel@tonic-gate entp = sentp; 409*0Sstevel@tonic-gate globbed = sglobbed; 410*0Sstevel@tonic-gate return (c); 411*0Sstevel@tonic-gate } 412*0Sstevel@tonic-gate 413*0Sstevel@tonic-gate static int amatch(char *s, char *p) 414*0Sstevel@tonic-gate { 415*0Sstevel@tonic-gate register int scc; 416*0Sstevel@tonic-gate int ok, lc; 417*0Sstevel@tonic-gate char *sgpathp; 418*0Sstevel@tonic-gate struct stat stb; 419*0Sstevel@tonic-gate int c, cc; 420*0Sstevel@tonic-gate 421*0Sstevel@tonic-gate globbed = 1; 422*0Sstevel@tonic-gate for (;;) { 423*0Sstevel@tonic-gate scc = *s++ & TRIM; 424*0Sstevel@tonic-gate switch (c = *p++) { 425*0Sstevel@tonic-gate 426*0Sstevel@tonic-gate case '{': 427*0Sstevel@tonic-gate return (execbrc(p - 1, s - 1)); 428*0Sstevel@tonic-gate 429*0Sstevel@tonic-gate case '[': 430*0Sstevel@tonic-gate ok = 0; 431*0Sstevel@tonic-gate lc = 077777; 432*0Sstevel@tonic-gate while ((cc = *p++)) { 433*0Sstevel@tonic-gate if (cc == ']') { 434*0Sstevel@tonic-gate if (ok) 435*0Sstevel@tonic-gate break; 436*0Sstevel@tonic-gate return (0); 437*0Sstevel@tonic-gate } 438*0Sstevel@tonic-gate if (cc == '-') { 439*0Sstevel@tonic-gate if (lc <= scc && scc <= *p++) 440*0Sstevel@tonic-gate ok++; 441*0Sstevel@tonic-gate } 442*0Sstevel@tonic-gate else if (scc == (lc = cc)) 443*0Sstevel@tonic-gate ok++; 444*0Sstevel@tonic-gate } 445*0Sstevel@tonic-gate if (cc == 0) { 446*0Sstevel@tonic-gate globerr = "Missing ]"; 447*0Sstevel@tonic-gate return (0); 448*0Sstevel@tonic-gate } 449*0Sstevel@tonic-gate continue; 450*0Sstevel@tonic-gate 451*0Sstevel@tonic-gate case '*': 452*0Sstevel@tonic-gate if (!*p) 453*0Sstevel@tonic-gate return (1); 454*0Sstevel@tonic-gate if (*p == '/') { 455*0Sstevel@tonic-gate p++; 456*0Sstevel@tonic-gate goto slash; 457*0Sstevel@tonic-gate } else if (*p == '*') { 458*0Sstevel@tonic-gate s--; 459*0Sstevel@tonic-gate continue; 460*0Sstevel@tonic-gate } 461*0Sstevel@tonic-gate s--; 462*0Sstevel@tonic-gate do { 463*0Sstevel@tonic-gate if (amatch(s, p)) 464*0Sstevel@tonic-gate return (1); 465*0Sstevel@tonic-gate } while (*s++); 466*0Sstevel@tonic-gate return (0); 467*0Sstevel@tonic-gate 468*0Sstevel@tonic-gate case 0: 469*0Sstevel@tonic-gate return (scc == 0); 470*0Sstevel@tonic-gate 471*0Sstevel@tonic-gate default: 472*0Sstevel@tonic-gate if (c != scc) 473*0Sstevel@tonic-gate return (0); 474*0Sstevel@tonic-gate continue; 475*0Sstevel@tonic-gate 476*0Sstevel@tonic-gate case '?': 477*0Sstevel@tonic-gate if (scc == 0) 478*0Sstevel@tonic-gate return (0); 479*0Sstevel@tonic-gate continue; 480*0Sstevel@tonic-gate 481*0Sstevel@tonic-gate case '/': 482*0Sstevel@tonic-gate if (scc) 483*0Sstevel@tonic-gate return (0); 484*0Sstevel@tonic-gate slash: 485*0Sstevel@tonic-gate s = entp; 486*0Sstevel@tonic-gate sgpathp = gpathp; 487*0Sstevel@tonic-gate while (*s) 488*0Sstevel@tonic-gate addpath(*s++); 489*0Sstevel@tonic-gate addpath('/'); 490*0Sstevel@tonic-gate if (stat(gpath, &stb) == 0 && isdir(stb)) 491*0Sstevel@tonic-gate if (*p == 0) { 492*0Sstevel@tonic-gate Gcat(gpath, ""); 493*0Sstevel@tonic-gate globcnt++; 494*0Sstevel@tonic-gate } 495*0Sstevel@tonic-gate else 496*0Sstevel@tonic-gate expand(p); 497*0Sstevel@tonic-gate gpathp = sgpathp; 498*0Sstevel@tonic-gate *gpathp = 0; 499*0Sstevel@tonic-gate return (0); 500*0Sstevel@tonic-gate } 501*0Sstevel@tonic-gate } 502*0Sstevel@tonic-gate } 503*0Sstevel@tonic-gate 504*0Sstevel@tonic-gate static void Gcat(register char *s1, register char *s2) 505*0Sstevel@tonic-gate { 506*0Sstevel@tonic-gate register size_t len = strlen(s1) + strlen(s2) + 1; 507*0Sstevel@tonic-gate 508*0Sstevel@tonic-gate if (globerr) 509*0Sstevel@tonic-gate return; 510*0Sstevel@tonic-gate 511*0Sstevel@tonic-gate if ((len + sizeof (char *)) >= gnleft) { 512*0Sstevel@tonic-gate globerr = "Arguments too long"; 513*0Sstevel@tonic-gate return; 514*0Sstevel@tonic-gate } 515*0Sstevel@tonic-gate if (len > MAXPATHLEN) { 516*0Sstevel@tonic-gate globerr = "Pathname too long"; 517*0Sstevel@tonic-gate return; 518*0Sstevel@tonic-gate } 519*0Sstevel@tonic-gate if (gargc >= agargv_size - 1) { 520*0Sstevel@tonic-gate char **tmp; 521*0Sstevel@tonic-gate 522*0Sstevel@tonic-gate tmp = (char **)realloc(agargv, 523*0Sstevel@tonic-gate (agargv_size + GAVSIZ) * sizeof (char *)); 524*0Sstevel@tonic-gate if (tmp == NULL) { 525*0Sstevel@tonic-gate fatal("Out of memory"); 526*0Sstevel@tonic-gate } else { 527*0Sstevel@tonic-gate agargv = tmp; 528*0Sstevel@tonic-gate agargv_size += GAVSIZ; 529*0Sstevel@tonic-gate } 530*0Sstevel@tonic-gate gargv = agargv; 531*0Sstevel@tonic-gate sortbas = agargv; 532*0Sstevel@tonic-gate } 533*0Sstevel@tonic-gate gargc++; 534*0Sstevel@tonic-gate gnleft -= len + sizeof (char *); 535*0Sstevel@tonic-gate gargv[gargc] = 0; 536*0Sstevel@tonic-gate gargv[gargc - 1] = strspl(s1, s2); 537*0Sstevel@tonic-gate } 538*0Sstevel@tonic-gate 539*0Sstevel@tonic-gate static void addpath(char c) 540*0Sstevel@tonic-gate { 541*0Sstevel@tonic-gate 542*0Sstevel@tonic-gate if (gpathp >= lastgpathp) 543*0Sstevel@tonic-gate globerr = "Pathname too long"; 544*0Sstevel@tonic-gate else { 545*0Sstevel@tonic-gate *gpathp++ = c; 546*0Sstevel@tonic-gate *gpathp = 0; 547*0Sstevel@tonic-gate } 548*0Sstevel@tonic-gate } 549*0Sstevel@tonic-gate 550*0Sstevel@tonic-gate static void rscan(register char **t, int (*f) (register char)) 551*0Sstevel@tonic-gate { 552*0Sstevel@tonic-gate register char *p, c; 553*0Sstevel@tonic-gate 554*0Sstevel@tonic-gate while ((p = *t++)) { 555*0Sstevel@tonic-gate if (*p == '~') 556*0Sstevel@tonic-gate gflag |= 2; 557*0Sstevel@tonic-gate else if (eq(p, "{") || eq(p, "{}")) 558*0Sstevel@tonic-gate continue; 559*0Sstevel@tonic-gate while ((c = *p++)) 560*0Sstevel@tonic-gate (*f) (c); 561*0Sstevel@tonic-gate } 562*0Sstevel@tonic-gate } 563*0Sstevel@tonic-gate static int tglob(register char c) 564*0Sstevel@tonic-gate { 565*0Sstevel@tonic-gate if (any(c, globchars)) 566*0Sstevel@tonic-gate gflag |= c == '{' ? 2 : 1; 567*0Sstevel@tonic-gate return (c); 568*0Sstevel@tonic-gate } 569*0Sstevel@tonic-gate 570*0Sstevel@tonic-gate int letter(register char c) 571*0Sstevel@tonic-gate { 572*0Sstevel@tonic-gate return (((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')) 573*0Sstevel@tonic-gate || (c == '_')); 574*0Sstevel@tonic-gate } 575*0Sstevel@tonic-gate 576*0Sstevel@tonic-gate int digit(register char c) 577*0Sstevel@tonic-gate { 578*0Sstevel@tonic-gate return (c >= '0' && c <= '9'); 579*0Sstevel@tonic-gate } 580*0Sstevel@tonic-gate 581*0Sstevel@tonic-gate int any(register int c, register char *s) 582*0Sstevel@tonic-gate { 583*0Sstevel@tonic-gate while (*s) 584*0Sstevel@tonic-gate if (*s++ == c) 585*0Sstevel@tonic-gate return (1); 586*0Sstevel@tonic-gate return (0); 587*0Sstevel@tonic-gate } 588*0Sstevel@tonic-gate 589*0Sstevel@tonic-gate int blklen(register char **av) 590*0Sstevel@tonic-gate { 591*0Sstevel@tonic-gate register int i = 0; 592*0Sstevel@tonic-gate 593*0Sstevel@tonic-gate while (*av++) 594*0Sstevel@tonic-gate i++; 595*0Sstevel@tonic-gate return (i); 596*0Sstevel@tonic-gate } 597*0Sstevel@tonic-gate 598*0Sstevel@tonic-gate char **blkcpy(char **oav, register char **bv) 599*0Sstevel@tonic-gate { 600*0Sstevel@tonic-gate register char **av = oav; 601*0Sstevel@tonic-gate 602*0Sstevel@tonic-gate while ((*av++ = *bv++)) 603*0Sstevel@tonic-gate continue; 604*0Sstevel@tonic-gate return (oav); 605*0Sstevel@tonic-gate } 606*0Sstevel@tonic-gate 607*0Sstevel@tonic-gate void blkfree(char **av0) 608*0Sstevel@tonic-gate { 609*0Sstevel@tonic-gate register char **av = av0; 610*0Sstevel@tonic-gate 611*0Sstevel@tonic-gate if (av) { 612*0Sstevel@tonic-gate while (*av) 613*0Sstevel@tonic-gate free(*av++); 614*0Sstevel@tonic-gate } 615*0Sstevel@tonic-gate } 616*0Sstevel@tonic-gate 617*0Sstevel@tonic-gate char *strspl(register char *cp, register char *dp) 618*0Sstevel@tonic-gate { 619*0Sstevel@tonic-gate int bufsize = strlen(cp) + strlen(dp) + 1; 620*0Sstevel@tonic-gate char *ep = malloc(bufsize); 621*0Sstevel@tonic-gate 622*0Sstevel@tonic-gate if (ep == NULL) 623*0Sstevel@tonic-gate fatal("Out of memory"); 624*0Sstevel@tonic-gate (void) strlcpy(ep, cp, bufsize); 625*0Sstevel@tonic-gate (void) strlcat(ep, dp, bufsize); 626*0Sstevel@tonic-gate return (ep); 627*0Sstevel@tonic-gate } 628*0Sstevel@tonic-gate 629*0Sstevel@tonic-gate char **copyblk(register char **v) 630*0Sstevel@tonic-gate { 631*0Sstevel@tonic-gate register char **nv = (char **) malloc((unsigned) ((blklen(v) + 1) * 632*0Sstevel@tonic-gate sizeof(char **))); 633*0Sstevel@tonic-gate if (nv == (char **) 0) 634*0Sstevel@tonic-gate fatal("Out of memory"); 635*0Sstevel@tonic-gate 636*0Sstevel@tonic-gate return (blkcpy(nv, v)); 637*0Sstevel@tonic-gate } 638*0Sstevel@tonic-gate 639*0Sstevel@tonic-gate static char *strend(register char *cp) 640*0Sstevel@tonic-gate { 641*0Sstevel@tonic-gate while (*cp) 642*0Sstevel@tonic-gate cp++; 643*0Sstevel@tonic-gate return (cp); 644*0Sstevel@tonic-gate } 645*0Sstevel@tonic-gate /* 646*0Sstevel@tonic-gate * Extract a home directory from the password file 647*0Sstevel@tonic-gate * The argument points to a buffer where the name of the 648*0Sstevel@tonic-gate * user whose home directory is sought is currently. 649*0Sstevel@tonic-gate * We write the home directory of the user back there. 650*0Sstevel@tonic-gate */ 651*0Sstevel@tonic-gate static int gethdir(char *home) 652*0Sstevel@tonic-gate { 653*0Sstevel@tonic-gate #ifdef OTHER_PASSWD 654*0Sstevel@tonic-gate register struct passwd *pp = bero_getpwnam(home, _path_passwd); 655*0Sstevel@tonic-gate #else 656*0Sstevel@tonic-gate register struct passwd *pp = getpwnam(home); 657*0Sstevel@tonic-gate #endif 658*0Sstevel@tonic-gate register char *root = NULL; 659*0Sstevel@tonic-gate if (!pp || home + strlen(pp->pw_dir) >= lastgpathp) 660*0Sstevel@tonic-gate return (1); 661*0Sstevel@tonic-gate root = strstr(pp->pw_dir, "/./"); 662*0Sstevel@tonic-gate (void) strlcpy(home, root ? (root + 2) : pp->pw_dir, lastgpathp - home); 663*0Sstevel@tonic-gate 664*0Sstevel@tonic-gate return (0); 665*0Sstevel@tonic-gate } 666