1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2002 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 28*0Sstevel@tonic-gate /* All Rights Reserved */ 29*0Sstevel@tonic-gate 30*0Sstevel@tonic-gate /* 31*0Sstevel@tonic-gate * University Copyright- Copyright (c) 1982, 1986, 1988 32*0Sstevel@tonic-gate * The Regents of the University of California 33*0Sstevel@tonic-gate * All Rights Reserved 34*0Sstevel@tonic-gate * 35*0Sstevel@tonic-gate * University Acknowledgment- Portions of this document are derived from 36*0Sstevel@tonic-gate * software developed by the University of California, Berkeley, and its 37*0Sstevel@tonic-gate * contributors. 38*0Sstevel@tonic-gate */ 39*0Sstevel@tonic-gate 40*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 41*0Sstevel@tonic-gate 42*0Sstevel@tonic-gate /* 43*0Sstevel@tonic-gate * C-shell glob for random programs. 44*0Sstevel@tonic-gate */ 45*0Sstevel@tonic-gate 46*0Sstevel@tonic-gate #include "ftp_var.h" 47*0Sstevel@tonic-gate 48*0Sstevel@tonic-gate #ifndef NCARGS 49*0Sstevel@tonic-gate #define NCARGS 5120 50*0Sstevel@tonic-gate #endif 51*0Sstevel@tonic-gate 52*0Sstevel@tonic-gate #define QUOTE 0200 53*0Sstevel@tonic-gate #define TRIM 0177 54*0Sstevel@tonic-gate #define eq(a, b) (strcmp(a, b) == 0) 55*0Sstevel@tonic-gate 56*0Sstevel@tonic-gate /* 57*0Sstevel@tonic-gate * According to the person who wrote the C shell "glob" code, a reasonable 58*0Sstevel@tonic-gate * limit on number of arguments would seem to be the maximum number of 59*0Sstevel@tonic-gate * characters in an arg list / 6. 60*0Sstevel@tonic-gate * 61*0Sstevel@tonic-gate * XXX: With the new VM system, NCARGS has become enormous, making 62*0Sstevel@tonic-gate * it impractical to allocate arrays with NCARGS / 6 entries on 63*0Sstevel@tonic-gate * the stack. The proper fix is to revamp code elsewhere (in 64*0Sstevel@tonic-gate * sh.dol.c and sh.glob.c) to use a different technique for handling 65*0Sstevel@tonic-gate * command line arguments. In the meantime, we simply fall back 66*0Sstevel@tonic-gate * on using the old value of NCARGS. 67*0Sstevel@tonic-gate */ 68*0Sstevel@tonic-gate #ifdef notyet 69*0Sstevel@tonic-gate #define GAVSIZ (NCARGS / 6) 70*0Sstevel@tonic-gate #else /* notyet */ 71*0Sstevel@tonic-gate #define GAVSIZ (10240 / 6) 72*0Sstevel@tonic-gate #endif /* notyet */ 73*0Sstevel@tonic-gate 74*0Sstevel@tonic-gate static char **gargv; /* Pointer to the (stack) arglist */ 75*0Sstevel@tonic-gate static char **agargv; 76*0Sstevel@tonic-gate static int agargv_size; 77*0Sstevel@tonic-gate static long gargc; /* Number args in gargv */ 78*0Sstevel@tonic-gate static short gflag; 79*0Sstevel@tonic-gate static char *strspl(); 80*0Sstevel@tonic-gate static char *strend(char *cp); 81*0Sstevel@tonic-gate static char *strspl(char *cp, char *dp); 82*0Sstevel@tonic-gate static int tglob(char c); 83*0Sstevel@tonic-gate static char **copyblk(char **v); 84*0Sstevel@tonic-gate static void ginit(char **agargv); 85*0Sstevel@tonic-gate static void addpath(char c); 86*0Sstevel@tonic-gate static int any(int c, char *s); 87*0Sstevel@tonic-gate static void Gcat(char *s1, char *s2); 88*0Sstevel@tonic-gate static void collect(char *as); 89*0Sstevel@tonic-gate static void acollect(char *as); 90*0Sstevel@tonic-gate static void sort(void); 91*0Sstevel@tonic-gate static void expand(char *as); 92*0Sstevel@tonic-gate static void matchdir(char *pattern); 93*0Sstevel@tonic-gate static int execbrc(char *p, char *s); 94*0Sstevel@tonic-gate static int ftp_fnmatch(wchar_t t_ch, wchar_t t_fch, wchar_t t_lch); 95*0Sstevel@tonic-gate static int gethdir(char *home); 96*0Sstevel@tonic-gate static void xfree(char *cp); 97*0Sstevel@tonic-gate static void rscan(char **t, int (*f)(char)); 98*0Sstevel@tonic-gate static int letter(char c); 99*0Sstevel@tonic-gate static int digit(char c); 100*0Sstevel@tonic-gate static int match(char *s, char *p); 101*0Sstevel@tonic-gate static int amatch(char *s, char *p); 102*0Sstevel@tonic-gate static int blklen(char **av); 103*0Sstevel@tonic-gate static char **blkcpy(char **oav, char **bv); 104*0Sstevel@tonic-gate 105*0Sstevel@tonic-gate static int globcnt; 106*0Sstevel@tonic-gate 107*0Sstevel@tonic-gate static char *globchars = "`{[*?"; 108*0Sstevel@tonic-gate 109*0Sstevel@tonic-gate static char *gpath, *gpathp, *lastgpathp; 110*0Sstevel@tonic-gate static int globbed; 111*0Sstevel@tonic-gate static char *entp; 112*0Sstevel@tonic-gate static char **sortbas; 113*0Sstevel@tonic-gate 114*0Sstevel@tonic-gate char ** 115*0Sstevel@tonic-gate glob(char *v) 116*0Sstevel@tonic-gate { 117*0Sstevel@tonic-gate char agpath[FTPBUFSIZ]; 118*0Sstevel@tonic-gate char *vv[2]; 119*0Sstevel@tonic-gate 120*0Sstevel@tonic-gate if (agargv == NULL) { 121*0Sstevel@tonic-gate agargv = (char **)malloc(GAVSIZ * sizeof (char *)); 122*0Sstevel@tonic-gate agargv_size = GAVSIZ; 123*0Sstevel@tonic-gate if (agargv == NULL) { 124*0Sstevel@tonic-gate globerr = "Arguments too long."; 125*0Sstevel@tonic-gate return (0); 126*0Sstevel@tonic-gate } 127*0Sstevel@tonic-gate } 128*0Sstevel@tonic-gate vv[0] = v; 129*0Sstevel@tonic-gate vv[1] = 0; 130*0Sstevel@tonic-gate globerr = 0; 131*0Sstevel@tonic-gate gflag = 0; 132*0Sstevel@tonic-gate rscan(vv, tglob); 133*0Sstevel@tonic-gate if (gflag == 0) 134*0Sstevel@tonic-gate return (copyblk(vv)); 135*0Sstevel@tonic-gate 136*0Sstevel@tonic-gate gpath = agpath; 137*0Sstevel@tonic-gate gpathp = gpath; 138*0Sstevel@tonic-gate *gpathp = 0; 139*0Sstevel@tonic-gate lastgpathp = &gpath[sizeof (agpath) - 2]; 140*0Sstevel@tonic-gate ginit(agargv); 141*0Sstevel@tonic-gate globcnt = 0; 142*0Sstevel@tonic-gate collect(v); 143*0Sstevel@tonic-gate if (globcnt == 0 && (gflag&1)) { 144*0Sstevel@tonic-gate blkfree(gargv); 145*0Sstevel@tonic-gate if (gargv == agargv) 146*0Sstevel@tonic-gate agargv = 0; 147*0Sstevel@tonic-gate gargv = 0; 148*0Sstevel@tonic-gate return (0); 149*0Sstevel@tonic-gate } else 150*0Sstevel@tonic-gate return (gargv = copyblk(gargv)); 151*0Sstevel@tonic-gate } 152*0Sstevel@tonic-gate 153*0Sstevel@tonic-gate static void 154*0Sstevel@tonic-gate ginit(char **agargv) 155*0Sstevel@tonic-gate { 156*0Sstevel@tonic-gate 157*0Sstevel@tonic-gate agargv[0] = 0; 158*0Sstevel@tonic-gate gargv = agargv; 159*0Sstevel@tonic-gate sortbas = agargv; 160*0Sstevel@tonic-gate gargc = 0; 161*0Sstevel@tonic-gate } 162*0Sstevel@tonic-gate 163*0Sstevel@tonic-gate static void 164*0Sstevel@tonic-gate collect(char *as) 165*0Sstevel@tonic-gate { 166*0Sstevel@tonic-gate if (eq(as, "{") || eq(as, "{}")) { 167*0Sstevel@tonic-gate Gcat(as, ""); 168*0Sstevel@tonic-gate sort(); 169*0Sstevel@tonic-gate } else 170*0Sstevel@tonic-gate acollect(as); 171*0Sstevel@tonic-gate } 172*0Sstevel@tonic-gate 173*0Sstevel@tonic-gate static void 174*0Sstevel@tonic-gate acollect(char *as) 175*0Sstevel@tonic-gate { 176*0Sstevel@tonic-gate register long ogargc = gargc; 177*0Sstevel@tonic-gate 178*0Sstevel@tonic-gate gpathp = gpath; *gpathp = 0; globbed = 0; 179*0Sstevel@tonic-gate expand(as); 180*0Sstevel@tonic-gate if (gargc != ogargc) 181*0Sstevel@tonic-gate sort(); 182*0Sstevel@tonic-gate } 183*0Sstevel@tonic-gate 184*0Sstevel@tonic-gate static void 185*0Sstevel@tonic-gate sort(void) 186*0Sstevel@tonic-gate { 187*0Sstevel@tonic-gate register char **p1, **p2, *c; 188*0Sstevel@tonic-gate char **Gvp = &gargv[gargc]; 189*0Sstevel@tonic-gate 190*0Sstevel@tonic-gate p1 = sortbas; 191*0Sstevel@tonic-gate while (p1 < Gvp-1) { 192*0Sstevel@tonic-gate p2 = p1; 193*0Sstevel@tonic-gate while (++p2 < Gvp) 194*0Sstevel@tonic-gate if (strcmp(*p1, *p2) > 0) 195*0Sstevel@tonic-gate c = *p1, *p1 = *p2, *p2 = c; 196*0Sstevel@tonic-gate p1++; 197*0Sstevel@tonic-gate } 198*0Sstevel@tonic-gate sortbas = Gvp; 199*0Sstevel@tonic-gate } 200*0Sstevel@tonic-gate 201*0Sstevel@tonic-gate static void 202*0Sstevel@tonic-gate expand(char *as) 203*0Sstevel@tonic-gate { 204*0Sstevel@tonic-gate register char *cs; 205*0Sstevel@tonic-gate register char *sgpathp, *oldcs; 206*0Sstevel@tonic-gate struct stat stb; 207*0Sstevel@tonic-gate 208*0Sstevel@tonic-gate sgpathp = gpathp; 209*0Sstevel@tonic-gate cs = as; 210*0Sstevel@tonic-gate if (*cs == '~' && gpathp == gpath) { 211*0Sstevel@tonic-gate addpath('~'); 212*0Sstevel@tonic-gate cs++; 213*0Sstevel@tonic-gate while (letter(*cs) || digit(*cs) || *cs == '-') 214*0Sstevel@tonic-gate addpath(*cs++); 215*0Sstevel@tonic-gate if (!*cs || *cs == '/') { 216*0Sstevel@tonic-gate if (gpathp != gpath + 1) { 217*0Sstevel@tonic-gate *gpathp = 0; 218*0Sstevel@tonic-gate if (gethdir(gpath + 1)) 219*0Sstevel@tonic-gate globerr = "Unknown user name after ~"; 220*0Sstevel@tonic-gate (void) strcpy(gpath, gpath + 1); 221*0Sstevel@tonic-gate } else 222*0Sstevel@tonic-gate (void) strcpy(gpath, home); 223*0Sstevel@tonic-gate gpathp = strend(gpath); 224*0Sstevel@tonic-gate } 225*0Sstevel@tonic-gate } 226*0Sstevel@tonic-gate while (!any(*cs, globchars)) { 227*0Sstevel@tonic-gate if (*cs == 0) { 228*0Sstevel@tonic-gate if (!globbed) 229*0Sstevel@tonic-gate Gcat(gpath, ""); 230*0Sstevel@tonic-gate else if (stat(gpath, &stb) >= 0) { 231*0Sstevel@tonic-gate Gcat(gpath, ""); 232*0Sstevel@tonic-gate globcnt++; 233*0Sstevel@tonic-gate } 234*0Sstevel@tonic-gate goto endit; 235*0Sstevel@tonic-gate } 236*0Sstevel@tonic-gate addpath(*cs++); 237*0Sstevel@tonic-gate } 238*0Sstevel@tonic-gate oldcs = cs; 239*0Sstevel@tonic-gate while (cs > as && *cs != '/') 240*0Sstevel@tonic-gate cs--, gpathp--; 241*0Sstevel@tonic-gate if (*cs == '/') 242*0Sstevel@tonic-gate cs++, gpathp++; 243*0Sstevel@tonic-gate *gpathp = 0; 244*0Sstevel@tonic-gate if (*oldcs == '{') { 245*0Sstevel@tonic-gate (void) execbrc(cs, ((char *)0)); 246*0Sstevel@tonic-gate return; 247*0Sstevel@tonic-gate } 248*0Sstevel@tonic-gate matchdir(cs); 249*0Sstevel@tonic-gate endit: 250*0Sstevel@tonic-gate gpathp = sgpathp; 251*0Sstevel@tonic-gate *gpathp = 0; 252*0Sstevel@tonic-gate } 253*0Sstevel@tonic-gate 254*0Sstevel@tonic-gate static void 255*0Sstevel@tonic-gate matchdir(char *pattern) 256*0Sstevel@tonic-gate { 257*0Sstevel@tonic-gate struct stat stb; 258*0Sstevel@tonic-gate register struct dirent *dp; 259*0Sstevel@tonic-gate DIR *dirp; 260*0Sstevel@tonic-gate 261*0Sstevel@tonic-gate /* 262*0Sstevel@tonic-gate * BSD/SunOS open() system call maps a null pathname into 263*0Sstevel@tonic-gate * "." while System V does not. 264*0Sstevel@tonic-gate */ 265*0Sstevel@tonic-gate if (*gpath == (char)0) { 266*0Sstevel@tonic-gate dirp = opendir("."); 267*0Sstevel@tonic-gate } else 268*0Sstevel@tonic-gate dirp = opendir(gpath); 269*0Sstevel@tonic-gate if (dirp == NULL) { 270*0Sstevel@tonic-gate if (globbed) 271*0Sstevel@tonic-gate return; 272*0Sstevel@tonic-gate goto patherr2; 273*0Sstevel@tonic-gate } 274*0Sstevel@tonic-gate if (fstat(dirp->dd_fd, &stb) < 0) 275*0Sstevel@tonic-gate goto patherr1; 276*0Sstevel@tonic-gate if (!S_ISDIR(stb.st_mode)) { 277*0Sstevel@tonic-gate errno = ENOTDIR; 278*0Sstevel@tonic-gate goto patherr1; 279*0Sstevel@tonic-gate } 280*0Sstevel@tonic-gate while ((dp = readdir(dirp)) != NULL) { 281*0Sstevel@tonic-gate if (dp->d_ino == 0) 282*0Sstevel@tonic-gate continue; 283*0Sstevel@tonic-gate if (match(dp->d_name, pattern)) { 284*0Sstevel@tonic-gate Gcat(gpath, dp->d_name); 285*0Sstevel@tonic-gate globcnt++; 286*0Sstevel@tonic-gate } 287*0Sstevel@tonic-gate } 288*0Sstevel@tonic-gate closedir(dirp); 289*0Sstevel@tonic-gate return; 290*0Sstevel@tonic-gate 291*0Sstevel@tonic-gate patherr1: 292*0Sstevel@tonic-gate closedir(dirp); 293*0Sstevel@tonic-gate patherr2: 294*0Sstevel@tonic-gate globerr = "Bad directory components"; 295*0Sstevel@tonic-gate } 296*0Sstevel@tonic-gate 297*0Sstevel@tonic-gate static int 298*0Sstevel@tonic-gate execbrc(char *p, char *s) 299*0Sstevel@tonic-gate { 300*0Sstevel@tonic-gate char restbuf[FTPBUFSIZ + 2]; 301*0Sstevel@tonic-gate register char *pe, *pm, *pl; 302*0Sstevel@tonic-gate int brclev = 0; 303*0Sstevel@tonic-gate char *lm, savec, *sgpathp; 304*0Sstevel@tonic-gate int len; 305*0Sstevel@tonic-gate 306*0Sstevel@tonic-gate for (lm = restbuf; *p != '{'; *lm += len, p += len) { 307*0Sstevel@tonic-gate if ((len = mblen(p, MB_CUR_MAX)) <= 0) 308*0Sstevel@tonic-gate len = 1; 309*0Sstevel@tonic-gate memcpy(lm, p, len); 310*0Sstevel@tonic-gate } 311*0Sstevel@tonic-gate 312*0Sstevel@tonic-gate for (pe = ++p; *pe; pe += len) { 313*0Sstevel@tonic-gate if ((len = mblen(pe, MB_CUR_MAX)) <= 0) 314*0Sstevel@tonic-gate len = 1; 315*0Sstevel@tonic-gate 316*0Sstevel@tonic-gate switch (*pe) { 317*0Sstevel@tonic-gate 318*0Sstevel@tonic-gate case '{': 319*0Sstevel@tonic-gate brclev++; 320*0Sstevel@tonic-gate continue; 321*0Sstevel@tonic-gate 322*0Sstevel@tonic-gate case '}': 323*0Sstevel@tonic-gate if (brclev == 0) 324*0Sstevel@tonic-gate goto pend; 325*0Sstevel@tonic-gate brclev--; 326*0Sstevel@tonic-gate continue; 327*0Sstevel@tonic-gate 328*0Sstevel@tonic-gate case '[': 329*0Sstevel@tonic-gate for (pe++; *pe && *pe != ']'; pe += len) { 330*0Sstevel@tonic-gate if ((len = mblen(pe, MB_CUR_MAX)) <= 0) 331*0Sstevel@tonic-gate len = 1; 332*0Sstevel@tonic-gate } 333*0Sstevel@tonic-gate len = 1; 334*0Sstevel@tonic-gate continue; 335*0Sstevel@tonic-gate } 336*0Sstevel@tonic-gate } 337*0Sstevel@tonic-gate pend: 338*0Sstevel@tonic-gate brclev = 0; 339*0Sstevel@tonic-gate for (pl = pm = p; pm <= pe; pm += len) { 340*0Sstevel@tonic-gate if ((len = mblen(pm, MB_CUR_MAX)) <= 0) 341*0Sstevel@tonic-gate len = 1; 342*0Sstevel@tonic-gate 343*0Sstevel@tonic-gate switch (*pm & (QUOTE|TRIM)) { 344*0Sstevel@tonic-gate 345*0Sstevel@tonic-gate case '{': 346*0Sstevel@tonic-gate brclev++; 347*0Sstevel@tonic-gate continue; 348*0Sstevel@tonic-gate 349*0Sstevel@tonic-gate case '}': 350*0Sstevel@tonic-gate if (brclev) { 351*0Sstevel@tonic-gate brclev--; 352*0Sstevel@tonic-gate continue; 353*0Sstevel@tonic-gate } 354*0Sstevel@tonic-gate goto doit; 355*0Sstevel@tonic-gate 356*0Sstevel@tonic-gate case ','|QUOTE: 357*0Sstevel@tonic-gate case ',': 358*0Sstevel@tonic-gate if (brclev) 359*0Sstevel@tonic-gate continue; 360*0Sstevel@tonic-gate doit: 361*0Sstevel@tonic-gate savec = *pm; 362*0Sstevel@tonic-gate *pm = 0; 363*0Sstevel@tonic-gate (void) strcpy(lm, pl); 364*0Sstevel@tonic-gate (void) strcat(restbuf, pe + 1); 365*0Sstevel@tonic-gate *pm = savec; 366*0Sstevel@tonic-gate if (s == 0) { 367*0Sstevel@tonic-gate sgpathp = gpathp; 368*0Sstevel@tonic-gate expand(restbuf); 369*0Sstevel@tonic-gate gpathp = sgpathp; 370*0Sstevel@tonic-gate *gpathp = 0; 371*0Sstevel@tonic-gate } else if (amatch(s, restbuf)) 372*0Sstevel@tonic-gate return (1); 373*0Sstevel@tonic-gate sort(); 374*0Sstevel@tonic-gate pl = pm + 1; 375*0Sstevel@tonic-gate if (brclev) 376*0Sstevel@tonic-gate return (0); 377*0Sstevel@tonic-gate continue; 378*0Sstevel@tonic-gate 379*0Sstevel@tonic-gate case '[': 380*0Sstevel@tonic-gate for (pm++; *pm && *pm != ']'; pm += len) { 381*0Sstevel@tonic-gate if ((len = mblen(pm, MB_CUR_MAX)) <= 0) 382*0Sstevel@tonic-gate len = 1; 383*0Sstevel@tonic-gate } 384*0Sstevel@tonic-gate len = 1; 385*0Sstevel@tonic-gate if (!*pm) 386*0Sstevel@tonic-gate pm--; 387*0Sstevel@tonic-gate continue; 388*0Sstevel@tonic-gate } 389*0Sstevel@tonic-gate } 390*0Sstevel@tonic-gate if (brclev) 391*0Sstevel@tonic-gate goto doit; 392*0Sstevel@tonic-gate return (0); 393*0Sstevel@tonic-gate } 394*0Sstevel@tonic-gate 395*0Sstevel@tonic-gate static int 396*0Sstevel@tonic-gate match(char *s, char *p) 397*0Sstevel@tonic-gate { 398*0Sstevel@tonic-gate register int c; 399*0Sstevel@tonic-gate register char *sentp; 400*0Sstevel@tonic-gate char sglobbed = globbed; 401*0Sstevel@tonic-gate 402*0Sstevel@tonic-gate if (*s == '.' && *p != '.') 403*0Sstevel@tonic-gate return (0); 404*0Sstevel@tonic-gate sentp = entp; 405*0Sstevel@tonic-gate entp = s; 406*0Sstevel@tonic-gate c = amatch(s, p); 407*0Sstevel@tonic-gate entp = sentp; 408*0Sstevel@tonic-gate globbed = sglobbed; 409*0Sstevel@tonic-gate return (c); 410*0Sstevel@tonic-gate } 411*0Sstevel@tonic-gate 412*0Sstevel@tonic-gate static int 413*0Sstevel@tonic-gate amatch(char *s, char *p) 414*0Sstevel@tonic-gate { 415*0Sstevel@tonic-gate wchar_t scc; 416*0Sstevel@tonic-gate int ok; 417*0Sstevel@tonic-gate wchar_t lc1, lc2; 418*0Sstevel@tonic-gate char *sgpathp; 419*0Sstevel@tonic-gate struct stat stb; 420*0Sstevel@tonic-gate wchar_t c, cc; 421*0Sstevel@tonic-gate int len_s, len_p; 422*0Sstevel@tonic-gate 423*0Sstevel@tonic-gate globbed = 1; 424*0Sstevel@tonic-gate for (;;) { 425*0Sstevel@tonic-gate if ((len_s = mbtowc(&scc, s, MB_CUR_MAX)) <= 0) { 426*0Sstevel@tonic-gate scc = (unsigned char)*s; 427*0Sstevel@tonic-gate len_s = 1; 428*0Sstevel@tonic-gate } 429*0Sstevel@tonic-gate /* scc = *s++ & TRIM; */ 430*0Sstevel@tonic-gate s += len_s; 431*0Sstevel@tonic-gate 432*0Sstevel@tonic-gate if ((len_p = mbtowc(&c, p, MB_CUR_MAX)) <= 0) { 433*0Sstevel@tonic-gate c = (unsigned char)*p; 434*0Sstevel@tonic-gate len_p = 1; 435*0Sstevel@tonic-gate } 436*0Sstevel@tonic-gate p += len_p; 437*0Sstevel@tonic-gate switch (c) { 438*0Sstevel@tonic-gate 439*0Sstevel@tonic-gate case '{': 440*0Sstevel@tonic-gate return (execbrc(p - len_p, s - len_s)); 441*0Sstevel@tonic-gate 442*0Sstevel@tonic-gate case '[': 443*0Sstevel@tonic-gate ok = 0; 444*0Sstevel@tonic-gate lc1 = 0; 445*0Sstevel@tonic-gate while ((cc = *p) != '\0') { 446*0Sstevel@tonic-gate if ((len_p = mbtowc(&cc, p, MB_CUR_MAX)) <= 0) { 447*0Sstevel@tonic-gate cc = (unsigned char)*p; 448*0Sstevel@tonic-gate len_p = 1; 449*0Sstevel@tonic-gate } 450*0Sstevel@tonic-gate p += len_p; 451*0Sstevel@tonic-gate if (cc == ']') { 452*0Sstevel@tonic-gate if (ok) 453*0Sstevel@tonic-gate break; 454*0Sstevel@tonic-gate return (0); 455*0Sstevel@tonic-gate } 456*0Sstevel@tonic-gate if (cc == '-') { 457*0Sstevel@tonic-gate if ((len_p = mbtowc(&lc2, p, 458*0Sstevel@tonic-gate MB_CUR_MAX)) <= 0) { 459*0Sstevel@tonic-gate lc2 = (unsigned char)*p; 460*0Sstevel@tonic-gate len_p = 1; 461*0Sstevel@tonic-gate } 462*0Sstevel@tonic-gate p += len_p; 463*0Sstevel@tonic-gate if (ftp_fnmatch(scc, lc1, lc2)) 464*0Sstevel@tonic-gate ok++; 465*0Sstevel@tonic-gate } else 466*0Sstevel@tonic-gate if (scc == (lc1 = cc)) 467*0Sstevel@tonic-gate ok++; 468*0Sstevel@tonic-gate } 469*0Sstevel@tonic-gate if (cc == 0) 470*0Sstevel@tonic-gate if (!ok) 471*0Sstevel@tonic-gate return (0); 472*0Sstevel@tonic-gate continue; 473*0Sstevel@tonic-gate 474*0Sstevel@tonic-gate case '*': 475*0Sstevel@tonic-gate if (!*p) 476*0Sstevel@tonic-gate return (1); 477*0Sstevel@tonic-gate if (*p == '/') { 478*0Sstevel@tonic-gate p++; 479*0Sstevel@tonic-gate goto slash; 480*0Sstevel@tonic-gate } 481*0Sstevel@tonic-gate s -= len_s; 482*0Sstevel@tonic-gate do { 483*0Sstevel@tonic-gate if (amatch(s, p)) 484*0Sstevel@tonic-gate return (1); 485*0Sstevel@tonic-gate } while (*s++); 486*0Sstevel@tonic-gate return (0); 487*0Sstevel@tonic-gate 488*0Sstevel@tonic-gate case 0: 489*0Sstevel@tonic-gate return (scc == 0); 490*0Sstevel@tonic-gate 491*0Sstevel@tonic-gate default: 492*0Sstevel@tonic-gate if (c != scc) 493*0Sstevel@tonic-gate return (0); 494*0Sstevel@tonic-gate continue; 495*0Sstevel@tonic-gate 496*0Sstevel@tonic-gate case '?': 497*0Sstevel@tonic-gate if (scc == 0) 498*0Sstevel@tonic-gate return (0); 499*0Sstevel@tonic-gate continue; 500*0Sstevel@tonic-gate 501*0Sstevel@tonic-gate case '/': 502*0Sstevel@tonic-gate if (scc) 503*0Sstevel@tonic-gate return (0); 504*0Sstevel@tonic-gate slash: 505*0Sstevel@tonic-gate s = entp; 506*0Sstevel@tonic-gate sgpathp = gpathp; 507*0Sstevel@tonic-gate while (*s) 508*0Sstevel@tonic-gate addpath(*s++); 509*0Sstevel@tonic-gate addpath('/'); 510*0Sstevel@tonic-gate if (stat(gpath, &stb) == 0 && S_ISDIR(stb.st_mode)) 511*0Sstevel@tonic-gate if (*p == 0) { 512*0Sstevel@tonic-gate Gcat(gpath, ""); 513*0Sstevel@tonic-gate globcnt++; 514*0Sstevel@tonic-gate } else 515*0Sstevel@tonic-gate expand(p); 516*0Sstevel@tonic-gate gpathp = sgpathp; 517*0Sstevel@tonic-gate *gpathp = 0; 518*0Sstevel@tonic-gate return (0); 519*0Sstevel@tonic-gate } 520*0Sstevel@tonic-gate } 521*0Sstevel@tonic-gate } 522*0Sstevel@tonic-gate 523*0Sstevel@tonic-gate #ifdef notdef 524*0Sstevel@tonic-gate static 525*0Sstevel@tonic-gate Gmatch(s, p) 526*0Sstevel@tonic-gate register char *s, *p; 527*0Sstevel@tonic-gate { 528*0Sstevel@tonic-gate register int scc; 529*0Sstevel@tonic-gate int ok, lc; 530*0Sstevel@tonic-gate int c, cc; 531*0Sstevel@tonic-gate 532*0Sstevel@tonic-gate for (;;) { 533*0Sstevel@tonic-gate scc = *s++ & TRIM; 534*0Sstevel@tonic-gate switch (c = *p++) { 535*0Sstevel@tonic-gate 536*0Sstevel@tonic-gate case '[': 537*0Sstevel@tonic-gate ok = 0; 538*0Sstevel@tonic-gate lc = 077777; 539*0Sstevel@tonic-gate while (cc = *p++) { 540*0Sstevel@tonic-gate if (cc == ']') { 541*0Sstevel@tonic-gate if (ok) 542*0Sstevel@tonic-gate break; 543*0Sstevel@tonic-gate return (0); 544*0Sstevel@tonic-gate } 545*0Sstevel@tonic-gate if (cc == '-') { 546*0Sstevel@tonic-gate if (lc <= scc && scc <= *p++) 547*0Sstevel@tonic-gate ok++; 548*0Sstevel@tonic-gate } else 549*0Sstevel@tonic-gate if (scc == (lc = cc)) 550*0Sstevel@tonic-gate ok++; 551*0Sstevel@tonic-gate } 552*0Sstevel@tonic-gate if (cc == 0) 553*0Sstevel@tonic-gate if (ok) 554*0Sstevel@tonic-gate p--; 555*0Sstevel@tonic-gate else 556*0Sstevel@tonic-gate return (0); 557*0Sstevel@tonic-gate continue; 558*0Sstevel@tonic-gate 559*0Sstevel@tonic-gate case '*': 560*0Sstevel@tonic-gate if (!*p) 561*0Sstevel@tonic-gate return (1); 562*0Sstevel@tonic-gate for (s--; *s; s++) 563*0Sstevel@tonic-gate if (Gmatch(s, p)) 564*0Sstevel@tonic-gate return (1); 565*0Sstevel@tonic-gate return (0); 566*0Sstevel@tonic-gate 567*0Sstevel@tonic-gate case 0: 568*0Sstevel@tonic-gate return (scc == 0); 569*0Sstevel@tonic-gate 570*0Sstevel@tonic-gate default: 571*0Sstevel@tonic-gate if ((c & TRIM) != scc) 572*0Sstevel@tonic-gate return (0); 573*0Sstevel@tonic-gate continue; 574*0Sstevel@tonic-gate 575*0Sstevel@tonic-gate case '?': 576*0Sstevel@tonic-gate if (scc == 0) 577*0Sstevel@tonic-gate return (0); 578*0Sstevel@tonic-gate continue; 579*0Sstevel@tonic-gate 580*0Sstevel@tonic-gate } 581*0Sstevel@tonic-gate } 582*0Sstevel@tonic-gate } 583*0Sstevel@tonic-gate #endif 584*0Sstevel@tonic-gate 585*0Sstevel@tonic-gate static void 586*0Sstevel@tonic-gate Gcat(char *s1, char *s2) 587*0Sstevel@tonic-gate { 588*0Sstevel@tonic-gate if (gargc >= agargv_size - 1) { 589*0Sstevel@tonic-gate char **tmp; 590*0Sstevel@tonic-gate 591*0Sstevel@tonic-gate if (globerr) { 592*0Sstevel@tonic-gate return; 593*0Sstevel@tonic-gate } 594*0Sstevel@tonic-gate tmp = (char **)realloc(agargv, 595*0Sstevel@tonic-gate (agargv_size + GAVSIZ) * sizeof (char *)); 596*0Sstevel@tonic-gate if (tmp == NULL) { 597*0Sstevel@tonic-gate globerr = "Arguments too long"; 598*0Sstevel@tonic-gate return; 599*0Sstevel@tonic-gate } else { 600*0Sstevel@tonic-gate agargv = tmp; 601*0Sstevel@tonic-gate agargv_size += GAVSIZ; 602*0Sstevel@tonic-gate } 603*0Sstevel@tonic-gate gargv = agargv; 604*0Sstevel@tonic-gate sortbas = agargv; 605*0Sstevel@tonic-gate } 606*0Sstevel@tonic-gate gargc++; 607*0Sstevel@tonic-gate gargv[gargc] = 0; 608*0Sstevel@tonic-gate gargv[gargc - 1] = strspl(s1, s2); 609*0Sstevel@tonic-gate } 610*0Sstevel@tonic-gate 611*0Sstevel@tonic-gate static void 612*0Sstevel@tonic-gate addpath(char c) 613*0Sstevel@tonic-gate { 614*0Sstevel@tonic-gate 615*0Sstevel@tonic-gate if (gpathp >= lastgpathp) 616*0Sstevel@tonic-gate globerr = "Pathname too long"; 617*0Sstevel@tonic-gate else { 618*0Sstevel@tonic-gate *gpathp++ = c; 619*0Sstevel@tonic-gate *gpathp = 0; 620*0Sstevel@tonic-gate } 621*0Sstevel@tonic-gate } 622*0Sstevel@tonic-gate 623*0Sstevel@tonic-gate static void 624*0Sstevel@tonic-gate rscan(char **t, int (*f)(char)) 625*0Sstevel@tonic-gate { 626*0Sstevel@tonic-gate register char *p, c; 627*0Sstevel@tonic-gate int len; 628*0Sstevel@tonic-gate 629*0Sstevel@tonic-gate while (p = *t++) { 630*0Sstevel@tonic-gate if (f == tglob) 631*0Sstevel@tonic-gate if (*p == '~') 632*0Sstevel@tonic-gate gflag |= 2; 633*0Sstevel@tonic-gate else if (eq(p, "{") || eq(p, "{}")) 634*0Sstevel@tonic-gate continue; 635*0Sstevel@tonic-gate while ((c = *p) != '\0') { 636*0Sstevel@tonic-gate (void) (*f)(c); 637*0Sstevel@tonic-gate if ((len = mblen(p, MB_CUR_MAX)) <= 0) 638*0Sstevel@tonic-gate len = 1; 639*0Sstevel@tonic-gate p += len; 640*0Sstevel@tonic-gate } 641*0Sstevel@tonic-gate } 642*0Sstevel@tonic-gate } 643*0Sstevel@tonic-gate 644*0Sstevel@tonic-gate static int 645*0Sstevel@tonic-gate tglob(char c) 646*0Sstevel@tonic-gate { 647*0Sstevel@tonic-gate if (any(c, globchars)) 648*0Sstevel@tonic-gate gflag |= c == '{' ? 2 : 1; 649*0Sstevel@tonic-gate return (c); 650*0Sstevel@tonic-gate } 651*0Sstevel@tonic-gate 652*0Sstevel@tonic-gate static int 653*0Sstevel@tonic-gate letter(char c) 654*0Sstevel@tonic-gate { 655*0Sstevel@tonic-gate return (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '_'); 656*0Sstevel@tonic-gate } 657*0Sstevel@tonic-gate 658*0Sstevel@tonic-gate static int 659*0Sstevel@tonic-gate digit(char c) 660*0Sstevel@tonic-gate { 661*0Sstevel@tonic-gate return (c >= '0' && c <= '9'); 662*0Sstevel@tonic-gate } 663*0Sstevel@tonic-gate 664*0Sstevel@tonic-gate static int 665*0Sstevel@tonic-gate any(int c, char *s) 666*0Sstevel@tonic-gate { 667*0Sstevel@tonic-gate int len; 668*0Sstevel@tonic-gate 669*0Sstevel@tonic-gate while (*s) { 670*0Sstevel@tonic-gate if (*s == c) 671*0Sstevel@tonic-gate return (1); 672*0Sstevel@tonic-gate if ((len = mblen(s, MB_CUR_MAX)) <= 0) 673*0Sstevel@tonic-gate len = 1; 674*0Sstevel@tonic-gate s += len; 675*0Sstevel@tonic-gate } 676*0Sstevel@tonic-gate return (0); 677*0Sstevel@tonic-gate } 678*0Sstevel@tonic-gate 679*0Sstevel@tonic-gate static int 680*0Sstevel@tonic-gate blklen(char **av) 681*0Sstevel@tonic-gate { 682*0Sstevel@tonic-gate register int i = 0; 683*0Sstevel@tonic-gate 684*0Sstevel@tonic-gate while (*av++) 685*0Sstevel@tonic-gate i++; 686*0Sstevel@tonic-gate return (i); 687*0Sstevel@tonic-gate } 688*0Sstevel@tonic-gate 689*0Sstevel@tonic-gate static char ** 690*0Sstevel@tonic-gate blkcpy(char **oav, char **bv) 691*0Sstevel@tonic-gate { 692*0Sstevel@tonic-gate register char **av = oav; 693*0Sstevel@tonic-gate 694*0Sstevel@tonic-gate while (*av++ = *bv++) 695*0Sstevel@tonic-gate continue; 696*0Sstevel@tonic-gate return (oav); 697*0Sstevel@tonic-gate } 698*0Sstevel@tonic-gate 699*0Sstevel@tonic-gate void 700*0Sstevel@tonic-gate blkfree(char **av0) 701*0Sstevel@tonic-gate { 702*0Sstevel@tonic-gate register char **av = av0; 703*0Sstevel@tonic-gate 704*0Sstevel@tonic-gate while (*av) 705*0Sstevel@tonic-gate xfree(*av++); 706*0Sstevel@tonic-gate free(av0); 707*0Sstevel@tonic-gate } 708*0Sstevel@tonic-gate 709*0Sstevel@tonic-gate static void 710*0Sstevel@tonic-gate xfree(char *cp) 711*0Sstevel@tonic-gate { 712*0Sstevel@tonic-gate extern char end[]; 713*0Sstevel@tonic-gate 714*0Sstevel@tonic-gate if (cp >= end && cp < (char *)&cp) 715*0Sstevel@tonic-gate free(cp); 716*0Sstevel@tonic-gate } 717*0Sstevel@tonic-gate 718*0Sstevel@tonic-gate static char * 719*0Sstevel@tonic-gate strspl(char *cp, char *dp) 720*0Sstevel@tonic-gate { 721*0Sstevel@tonic-gate register char *ep = malloc((unsigned)(strlen(cp) + strlen(dp) + 1)); 722*0Sstevel@tonic-gate 723*0Sstevel@tonic-gate if (ep == (char *)0) 724*0Sstevel@tonic-gate fatal("Out of memory"); 725*0Sstevel@tonic-gate (void) strcpy(ep, cp); 726*0Sstevel@tonic-gate (void) strcat(ep, dp); 727*0Sstevel@tonic-gate return (ep); 728*0Sstevel@tonic-gate } 729*0Sstevel@tonic-gate 730*0Sstevel@tonic-gate static char ** 731*0Sstevel@tonic-gate copyblk(char **v) 732*0Sstevel@tonic-gate { 733*0Sstevel@tonic-gate register char **nv = (char **)malloc((unsigned)((blklen(v) + 1) * 734*0Sstevel@tonic-gate sizeof (char **))); 735*0Sstevel@tonic-gate 736*0Sstevel@tonic-gate if (nv == (char **)0) 737*0Sstevel@tonic-gate fatal("Out of memory"); 738*0Sstevel@tonic-gate 739*0Sstevel@tonic-gate return (blkcpy(nv, v)); 740*0Sstevel@tonic-gate } 741*0Sstevel@tonic-gate 742*0Sstevel@tonic-gate static char * 743*0Sstevel@tonic-gate strend(char *cp) 744*0Sstevel@tonic-gate { 745*0Sstevel@tonic-gate 746*0Sstevel@tonic-gate while (*cp) 747*0Sstevel@tonic-gate cp++; 748*0Sstevel@tonic-gate return (cp); 749*0Sstevel@tonic-gate } 750*0Sstevel@tonic-gate /* 751*0Sstevel@tonic-gate * Extract a home directory from the password file 752*0Sstevel@tonic-gate * The argument points to a buffer where the name of the 753*0Sstevel@tonic-gate * user whose home directory is sought is currently. 754*0Sstevel@tonic-gate * We write the home directory of the user back there. 755*0Sstevel@tonic-gate */ 756*0Sstevel@tonic-gate gethdir(char *home) 757*0Sstevel@tonic-gate { 758*0Sstevel@tonic-gate register struct passwd *pp = getpwnam(home); 759*0Sstevel@tonic-gate 760*0Sstevel@tonic-gate if (!pp || home + strlen(pp->pw_dir) >= lastgpathp) 761*0Sstevel@tonic-gate return (1); 762*0Sstevel@tonic-gate (void) strcpy(home, pp->pw_dir); 763*0Sstevel@tonic-gate return (0); 764*0Sstevel@tonic-gate } 765*0Sstevel@tonic-gate 766*0Sstevel@tonic-gate static int 767*0Sstevel@tonic-gate ftp_fnmatch(wchar_t t_ch, wchar_t t_fch, wchar_t t_lch) 768*0Sstevel@tonic-gate { 769*0Sstevel@tonic-gate char t_char[MB_LEN_MAX + 1]; 770*0Sstevel@tonic-gate char t_patan[MB_LEN_MAX * 2 + 8]; 771*0Sstevel@tonic-gate char *p; 772*0Sstevel@tonic-gate int i; 773*0Sstevel@tonic-gate 774*0Sstevel@tonic-gate if ((t_ch == t_fch) || (t_ch == t_lch)) 775*0Sstevel@tonic-gate return (1); 776*0Sstevel@tonic-gate 777*0Sstevel@tonic-gate p = t_patan; 778*0Sstevel@tonic-gate if ((i = wctomb(t_char, (wchar_t)t_ch)) <= 0) 779*0Sstevel@tonic-gate return (0); 780*0Sstevel@tonic-gate t_char[i] = 0; 781*0Sstevel@tonic-gate 782*0Sstevel@tonic-gate *p++ = '['; 783*0Sstevel@tonic-gate if ((i = wctomb(p, (wchar_t)t_fch)) <= 0) 784*0Sstevel@tonic-gate return (0); 785*0Sstevel@tonic-gate p += i; 786*0Sstevel@tonic-gate *p++ = '-'; 787*0Sstevel@tonic-gate if ((i = wctomb(p, (wchar_t)t_lch)) <= 0) 788*0Sstevel@tonic-gate return (0); 789*0Sstevel@tonic-gate p += i; 790*0Sstevel@tonic-gate *p++ = ']'; 791*0Sstevel@tonic-gate *p = 0; 792*0Sstevel@tonic-gate 793*0Sstevel@tonic-gate if (fnmatch(t_patan, t_char, FNM_NOESCAPE)) 794*0Sstevel@tonic-gate return (0); 795*0Sstevel@tonic-gate return (1); 796*0Sstevel@tonic-gate } 797