1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * Copyright 2001 Sun Microsystems, Inc. All rights reserved. 3*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 4*7c478bd9Sstevel@tonic-gate */ 5*7c478bd9Sstevel@tonic-gate 6*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 7*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 8*7c478bd9Sstevel@tonic-gate 9*7c478bd9Sstevel@tonic-gate /* 10*7c478bd9Sstevel@tonic-gate * Copyright (c) 1980 Regents of the University of California. 11*7c478bd9Sstevel@tonic-gate * All rights reserved. The Berkeley Software License Agreement 12*7c478bd9Sstevel@tonic-gate * specifies the terms and conditions for redistribution. 13*7c478bd9Sstevel@tonic-gate */ 14*7c478bd9Sstevel@tonic-gate 15*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 16*7c478bd9Sstevel@tonic-gate 17*7c478bd9Sstevel@tonic-gate #include "sh.h" 18*7c478bd9Sstevel@tonic-gate #include "sh.tconst.h" 19*7c478bd9Sstevel@tonic-gate #include <dirent.h> 20*7c478bd9Sstevel@tonic-gate #ifdef MBCHAR 21*7c478bd9Sstevel@tonic-gate #include <widec.h> /* wcsetno() */ 22*7c478bd9Sstevel@tonic-gate #include <fnmatch.h> /* fnmatch() */ 23*7c478bd9Sstevel@tonic-gate #endif /* MBCHAR */ 24*7c478bd9Sstevel@tonic-gate 25*7c478bd9Sstevel@tonic-gate /* 26*7c478bd9Sstevel@tonic-gate * C Shell 27*7c478bd9Sstevel@tonic-gate */ 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate int globcnt; 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate tchar *gpath, *gpathp, *lastgpathp; 32*7c478bd9Sstevel@tonic-gate int globbed; 33*7c478bd9Sstevel@tonic-gate bool noglob; 34*7c478bd9Sstevel@tonic-gate bool nonomatch; 35*7c478bd9Sstevel@tonic-gate tchar *entp; 36*7c478bd9Sstevel@tonic-gate tchar **sortbas; 37*7c478bd9Sstevel@tonic-gate int sortscmp(); 38*7c478bd9Sstevel@tonic-gate extern DIR *opendir_(); 39*7c478bd9Sstevel@tonic-gate 40*7c478bd9Sstevel@tonic-gate #define sort() qsort((char *)sortbas, &gargv[gargc] - sortbas, \ 41*7c478bd9Sstevel@tonic-gate sizeof (*sortbas), (int (*)(const void *, \ 42*7c478bd9Sstevel@tonic-gate const void *)) sortscmp), sortbas = &gargv[gargc] 43*7c478bd9Sstevel@tonic-gate 44*7c478bd9Sstevel@tonic-gate 45*7c478bd9Sstevel@tonic-gate tchar ** 46*7c478bd9Sstevel@tonic-gate glob(v) 47*7c478bd9Sstevel@tonic-gate register tchar **v; 48*7c478bd9Sstevel@tonic-gate { 49*7c478bd9Sstevel@tonic-gate tchar agpath[BUFSIZ]; 50*7c478bd9Sstevel@tonic-gate tchar *agargv[GAVSIZ]; 51*7c478bd9Sstevel@tonic-gate 52*7c478bd9Sstevel@tonic-gate gpath = agpath; gpathp = gpath; *gpathp = 0; 53*7c478bd9Sstevel@tonic-gate lastgpathp = &gpath[BUFSIZ - 2]; 54*7c478bd9Sstevel@tonic-gate ginit(agargv); globcnt = 0; 55*7c478bd9Sstevel@tonic-gate #ifdef TRACE 56*7c478bd9Sstevel@tonic-gate tprintf("TRACE- glob()\n"); 57*7c478bd9Sstevel@tonic-gate #endif 58*7c478bd9Sstevel@tonic-gate #ifdef GDEBUG 59*7c478bd9Sstevel@tonic-gate printf("glob entered: "); blkpr(v); printf("\n"); 60*7c478bd9Sstevel@tonic-gate #endif 61*7c478bd9Sstevel@tonic-gate noglob = adrof(S_noglob /* "noglob" */) != 0; 62*7c478bd9Sstevel@tonic-gate nonomatch = adrof(S_nonomatch /* "nonomatch" */) != 0; 63*7c478bd9Sstevel@tonic-gate globcnt = noglob | nonomatch; 64*7c478bd9Sstevel@tonic-gate while (*v) 65*7c478bd9Sstevel@tonic-gate collect(*v++); 66*7c478bd9Sstevel@tonic-gate #ifdef GDEBUG 67*7c478bd9Sstevel@tonic-gate printf("glob done, globcnt=%d, gflag=%d: ", globcnt, gflag); 68*7c478bd9Sstevel@tonic-gate blkpr(gargv); printf("\n"); 69*7c478bd9Sstevel@tonic-gate #endif 70*7c478bd9Sstevel@tonic-gate if (globcnt == 0 && (gflag&1)) { 71*7c478bd9Sstevel@tonic-gate blkfree(gargv), gargv = 0; 72*7c478bd9Sstevel@tonic-gate return (0); 73*7c478bd9Sstevel@tonic-gate } else 74*7c478bd9Sstevel@tonic-gate return (gargv = copyblk(gargv)); 75*7c478bd9Sstevel@tonic-gate } 76*7c478bd9Sstevel@tonic-gate 77*7c478bd9Sstevel@tonic-gate ginit(agargv) 78*7c478bd9Sstevel@tonic-gate tchar **agargv; 79*7c478bd9Sstevel@tonic-gate { 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate agargv[0] = 0; gargv = agargv; sortbas = agargv; gargc = 0; 82*7c478bd9Sstevel@tonic-gate gnleft = NCARGS - 4; 83*7c478bd9Sstevel@tonic-gate } 84*7c478bd9Sstevel@tonic-gate 85*7c478bd9Sstevel@tonic-gate collect(as) 86*7c478bd9Sstevel@tonic-gate register tchar *as; 87*7c478bd9Sstevel@tonic-gate { 88*7c478bd9Sstevel@tonic-gate register int i; 89*7c478bd9Sstevel@tonic-gate 90*7c478bd9Sstevel@tonic-gate #ifdef TRACE 91*7c478bd9Sstevel@tonic-gate tprintf("TRACE- collect()\n"); 92*7c478bd9Sstevel@tonic-gate #endif 93*7c478bd9Sstevel@tonic-gate if (any('`', as)) { 94*7c478bd9Sstevel@tonic-gate #ifdef GDEBUG 95*7c478bd9Sstevel@tonic-gate printf("doing backp of %t\n", as); 96*7c478bd9Sstevel@tonic-gate #endif 97*7c478bd9Sstevel@tonic-gate (void) dobackp(as, 0); 98*7c478bd9Sstevel@tonic-gate #ifdef GDEBUG 99*7c478bd9Sstevel@tonic-gate printf("backp done, acollect'ing\n"); 100*7c478bd9Sstevel@tonic-gate #endif 101*7c478bd9Sstevel@tonic-gate /* 102*7c478bd9Sstevel@tonic-gate * dobackp has the side effect of messing with 103*7c478bd9Sstevel@tonic-gate * gflag, since it does more globbing, so check 104*7c478bd9Sstevel@tonic-gate * if the results is still globbable 105*7c478bd9Sstevel@tonic-gate */ 106*7c478bd9Sstevel@tonic-gate tglob(pargv); 107*7c478bd9Sstevel@tonic-gate 108*7c478bd9Sstevel@tonic-gate for (i = 0; i < pargc; i++) 109*7c478bd9Sstevel@tonic-gate if (noglob) { 110*7c478bd9Sstevel@tonic-gate Gcat(pargv[i], S_ /* "" */); 111*7c478bd9Sstevel@tonic-gate sortbas = &gargv[gargc]; 112*7c478bd9Sstevel@tonic-gate } else 113*7c478bd9Sstevel@tonic-gate acollect(pargv[i]); 114*7c478bd9Sstevel@tonic-gate if (pargv) 115*7c478bd9Sstevel@tonic-gate blkfree(pargv), pargv = 0; 116*7c478bd9Sstevel@tonic-gate #ifdef GDEBUG 117*7c478bd9Sstevel@tonic-gate printf("acollect done\n"); 118*7c478bd9Sstevel@tonic-gate #endif 119*7c478bd9Sstevel@tonic-gate } else if (noglob || eq(as, S_LBRA /* "{" */) || 120*7c478bd9Sstevel@tonic-gate eq(as, S_BRABRA /* "{}" */)) { 121*7c478bd9Sstevel@tonic-gate Gcat(as, S_ /* "" */); 122*7c478bd9Sstevel@tonic-gate sort(); 123*7c478bd9Sstevel@tonic-gate } else 124*7c478bd9Sstevel@tonic-gate acollect(as); 125*7c478bd9Sstevel@tonic-gate } 126*7c478bd9Sstevel@tonic-gate 127*7c478bd9Sstevel@tonic-gate acollect(as) 128*7c478bd9Sstevel@tonic-gate register tchar *as; 129*7c478bd9Sstevel@tonic-gate { 130*7c478bd9Sstevel@tonic-gate register long ogargc = gargc; 131*7c478bd9Sstevel@tonic-gate 132*7c478bd9Sstevel@tonic-gate #ifdef TRACE 133*7c478bd9Sstevel@tonic-gate tprintf("TRACE- acollect()\n"); 134*7c478bd9Sstevel@tonic-gate #endif 135*7c478bd9Sstevel@tonic-gate gpathp = gpath; *gpathp = 0; globbed = 0; 136*7c478bd9Sstevel@tonic-gate expand(as); 137*7c478bd9Sstevel@tonic-gate if (gargc == ogargc) { 138*7c478bd9Sstevel@tonic-gate if (nonomatch) { 139*7c478bd9Sstevel@tonic-gate Gcat(as, S_ /* "" */); 140*7c478bd9Sstevel@tonic-gate sort(); 141*7c478bd9Sstevel@tonic-gate } 142*7c478bd9Sstevel@tonic-gate } else 143*7c478bd9Sstevel@tonic-gate sort(); 144*7c478bd9Sstevel@tonic-gate } 145*7c478bd9Sstevel@tonic-gate 146*7c478bd9Sstevel@tonic-gate /* 147*7c478bd9Sstevel@tonic-gate * String compare for qsort. Also used by filec code in sh.file.c. 148*7c478bd9Sstevel@tonic-gate */ 149*7c478bd9Sstevel@tonic-gate sortscmp(a1, a2) 150*7c478bd9Sstevel@tonic-gate tchar **a1, **a2; 151*7c478bd9Sstevel@tonic-gate { 152*7c478bd9Sstevel@tonic-gate 153*7c478bd9Sstevel@tonic-gate return (strcoll_(*a1, *a2)); 154*7c478bd9Sstevel@tonic-gate } 155*7c478bd9Sstevel@tonic-gate 156*7c478bd9Sstevel@tonic-gate expand(as) 157*7c478bd9Sstevel@tonic-gate tchar *as; 158*7c478bd9Sstevel@tonic-gate { 159*7c478bd9Sstevel@tonic-gate register tchar *cs; 160*7c478bd9Sstevel@tonic-gate register tchar *sgpathp, *oldcs; 161*7c478bd9Sstevel@tonic-gate struct stat stb; 162*7c478bd9Sstevel@tonic-gate 163*7c478bd9Sstevel@tonic-gate #ifdef TRACE 164*7c478bd9Sstevel@tonic-gate tprintf("TRACE- expand()\n"); 165*7c478bd9Sstevel@tonic-gate #endif 166*7c478bd9Sstevel@tonic-gate sgpathp = gpathp; 167*7c478bd9Sstevel@tonic-gate cs = as; 168*7c478bd9Sstevel@tonic-gate if (*cs == '~' && gpathp == gpath) { 169*7c478bd9Sstevel@tonic-gate addpath('~'); 170*7c478bd9Sstevel@tonic-gate for (cs++; alnum(*cs) || *cs == '-'; ) 171*7c478bd9Sstevel@tonic-gate addpath(*cs++); 172*7c478bd9Sstevel@tonic-gate if (!*cs || *cs == '/') { 173*7c478bd9Sstevel@tonic-gate if (gpathp != gpath + 1) { 174*7c478bd9Sstevel@tonic-gate *gpathp = 0; 175*7c478bd9Sstevel@tonic-gate if (gethdir(gpath + 1)) 176*7c478bd9Sstevel@tonic-gate /* 177*7c478bd9Sstevel@tonic-gate * modified from %s to %t 178*7c478bd9Sstevel@tonic-gate */ 179*7c478bd9Sstevel@tonic-gate error("Unknown user: %t", gpath + 1); 180*7c478bd9Sstevel@tonic-gate (void) strcpy_(gpath, gpath + 1); 181*7c478bd9Sstevel@tonic-gate } else 182*7c478bd9Sstevel@tonic-gate (void) strcpy_(gpath, 183*7c478bd9Sstevel@tonic-gate value(S_home /* "home" */)); 184*7c478bd9Sstevel@tonic-gate gpathp = strend(gpath); 185*7c478bd9Sstevel@tonic-gate } 186*7c478bd9Sstevel@tonic-gate } 187*7c478bd9Sstevel@tonic-gate while (!isglob(*cs)) { 188*7c478bd9Sstevel@tonic-gate if (*cs == 0) { 189*7c478bd9Sstevel@tonic-gate if (!globbed) 190*7c478bd9Sstevel@tonic-gate Gcat(gpath, S_ /* "" */); 191*7c478bd9Sstevel@tonic-gate else if (lstat_(gpath, &stb) >= 0) { 192*7c478bd9Sstevel@tonic-gate Gcat(gpath, S_ /* "" */); 193*7c478bd9Sstevel@tonic-gate globcnt++; 194*7c478bd9Sstevel@tonic-gate } 195*7c478bd9Sstevel@tonic-gate goto endit; 196*7c478bd9Sstevel@tonic-gate } 197*7c478bd9Sstevel@tonic-gate addpath(*cs++); 198*7c478bd9Sstevel@tonic-gate } 199*7c478bd9Sstevel@tonic-gate oldcs = cs; 200*7c478bd9Sstevel@tonic-gate while (cs > as && *cs != '/') 201*7c478bd9Sstevel@tonic-gate cs--, gpathp--; 202*7c478bd9Sstevel@tonic-gate if (*cs == '/') 203*7c478bd9Sstevel@tonic-gate cs++, gpathp++; 204*7c478bd9Sstevel@tonic-gate *gpathp = 0; 205*7c478bd9Sstevel@tonic-gate if (*oldcs == '{') { 206*7c478bd9Sstevel@tonic-gate (void) execbrc(cs, NOSTR); 207*7c478bd9Sstevel@tonic-gate return; 208*7c478bd9Sstevel@tonic-gate } 209*7c478bd9Sstevel@tonic-gate matchdir_(cs); 210*7c478bd9Sstevel@tonic-gate endit: 211*7c478bd9Sstevel@tonic-gate gpathp = sgpathp; 212*7c478bd9Sstevel@tonic-gate *gpathp = 0; 213*7c478bd9Sstevel@tonic-gate } 214*7c478bd9Sstevel@tonic-gate 215*7c478bd9Sstevel@tonic-gate matchdir_(pattern) 216*7c478bd9Sstevel@tonic-gate tchar *pattern; 217*7c478bd9Sstevel@tonic-gate { 218*7c478bd9Sstevel@tonic-gate struct stat stb; 219*7c478bd9Sstevel@tonic-gate register struct dirent *dp; 220*7c478bd9Sstevel@tonic-gate register DIR *dirp; 221*7c478bd9Sstevel@tonic-gate tchar curdir_[MAXNAMLEN+1]; 222*7c478bd9Sstevel@tonic-gate int slproc = 0; 223*7c478bd9Sstevel@tonic-gate 224*7c478bd9Sstevel@tonic-gate #ifdef TRACE 225*7c478bd9Sstevel@tonic-gate tprintf("TRACE- matchdir()\n"); 226*7c478bd9Sstevel@tonic-gate #endif 227*7c478bd9Sstevel@tonic-gate /* 228*7c478bd9Sstevel@tonic-gate * BSD's opendir would open "." if argument is NULL, but not S5 229*7c478bd9Sstevel@tonic-gate */ 230*7c478bd9Sstevel@tonic-gate 231*7c478bd9Sstevel@tonic-gate if (*gpath == NULL) 232*7c478bd9Sstevel@tonic-gate dirp = opendir_(S_DOT /* "." */); 233*7c478bd9Sstevel@tonic-gate else 234*7c478bd9Sstevel@tonic-gate dirp = opendir_(gpath); 235*7c478bd9Sstevel@tonic-gate if (dirp == NULL) { 236*7c478bd9Sstevel@tonic-gate if (globbed) 237*7c478bd9Sstevel@tonic-gate return; 238*7c478bd9Sstevel@tonic-gate goto patherr2; 239*7c478bd9Sstevel@tonic-gate } 240*7c478bd9Sstevel@tonic-gate if (fstat(dirp->dd_fd, &stb) < 0) 241*7c478bd9Sstevel@tonic-gate goto patherr1; 242*7c478bd9Sstevel@tonic-gate if (!isdir(stb)) { 243*7c478bd9Sstevel@tonic-gate errno = ENOTDIR; 244*7c478bd9Sstevel@tonic-gate goto patherr1; 245*7c478bd9Sstevel@tonic-gate } 246*7c478bd9Sstevel@tonic-gate while ((dp = readdir(dirp)) != NULL) { 247*7c478bd9Sstevel@tonic-gate 248*7c478bd9Sstevel@tonic-gate if (dp->d_ino == 0) 249*7c478bd9Sstevel@tonic-gate continue; 250*7c478bd9Sstevel@tonic-gate strtots(curdir_, dp->d_name); 251*7c478bd9Sstevel@tonic-gate slproc = 0; 252*7c478bd9Sstevel@tonic-gate if (match(curdir_, pattern, &slproc)) { 253*7c478bd9Sstevel@tonic-gate Gcat(gpath, curdir_); 254*7c478bd9Sstevel@tonic-gate globcnt++; 255*7c478bd9Sstevel@tonic-gate } 256*7c478bd9Sstevel@tonic-gate } 257*7c478bd9Sstevel@tonic-gate unsetfd(dirp->dd_fd); 258*7c478bd9Sstevel@tonic-gate closedir_(dirp); 259*7c478bd9Sstevel@tonic-gate return; 260*7c478bd9Sstevel@tonic-gate 261*7c478bd9Sstevel@tonic-gate patherr1: 262*7c478bd9Sstevel@tonic-gate unsetfd(dirp->dd_fd); 263*7c478bd9Sstevel@tonic-gate closedir_(dirp); 264*7c478bd9Sstevel@tonic-gate patherr2: 265*7c478bd9Sstevel@tonic-gate Perror(gpath); 266*7c478bd9Sstevel@tonic-gate } 267*7c478bd9Sstevel@tonic-gate 268*7c478bd9Sstevel@tonic-gate execbrc(p, s) 269*7c478bd9Sstevel@tonic-gate tchar *p, *s; 270*7c478bd9Sstevel@tonic-gate { 271*7c478bd9Sstevel@tonic-gate tchar restbuf[BUFSIZ + 2]; 272*7c478bd9Sstevel@tonic-gate register tchar *pe, *pm, *pl; 273*7c478bd9Sstevel@tonic-gate int brclev = 0; 274*7c478bd9Sstevel@tonic-gate tchar *lm, savec, *sgpathp; 275*7c478bd9Sstevel@tonic-gate int slproc = 0; 276*7c478bd9Sstevel@tonic-gate 277*7c478bd9Sstevel@tonic-gate #ifdef TRACE 278*7c478bd9Sstevel@tonic-gate tprintf("TRACE- execbrc()\n"); 279*7c478bd9Sstevel@tonic-gate #endif 280*7c478bd9Sstevel@tonic-gate for (lm = restbuf; *p != '{'; *lm++ = *p++) 281*7c478bd9Sstevel@tonic-gate continue; 282*7c478bd9Sstevel@tonic-gate for (pe = ++p; *pe; pe++) 283*7c478bd9Sstevel@tonic-gate switch (*pe) { 284*7c478bd9Sstevel@tonic-gate 285*7c478bd9Sstevel@tonic-gate case '{': 286*7c478bd9Sstevel@tonic-gate brclev++; 287*7c478bd9Sstevel@tonic-gate continue; 288*7c478bd9Sstevel@tonic-gate 289*7c478bd9Sstevel@tonic-gate case '}': 290*7c478bd9Sstevel@tonic-gate if (brclev == 0) 291*7c478bd9Sstevel@tonic-gate goto pend; 292*7c478bd9Sstevel@tonic-gate brclev--; 293*7c478bd9Sstevel@tonic-gate continue; 294*7c478bd9Sstevel@tonic-gate 295*7c478bd9Sstevel@tonic-gate case '[': 296*7c478bd9Sstevel@tonic-gate for (pe++; *pe && *pe != ']'; pe++) 297*7c478bd9Sstevel@tonic-gate continue; 298*7c478bd9Sstevel@tonic-gate if (!*pe) 299*7c478bd9Sstevel@tonic-gate error("Missing ]"); 300*7c478bd9Sstevel@tonic-gate continue; 301*7c478bd9Sstevel@tonic-gate } 302*7c478bd9Sstevel@tonic-gate pend: 303*7c478bd9Sstevel@tonic-gate if (brclev || !*pe) 304*7c478bd9Sstevel@tonic-gate error("Missing }"); 305*7c478bd9Sstevel@tonic-gate for (pl = pm = p; pm <= pe; pm++) 306*7c478bd9Sstevel@tonic-gate switch (*pm & (QUOTE|TRIM)) { 307*7c478bd9Sstevel@tonic-gate 308*7c478bd9Sstevel@tonic-gate case '{': 309*7c478bd9Sstevel@tonic-gate brclev++; 310*7c478bd9Sstevel@tonic-gate continue; 311*7c478bd9Sstevel@tonic-gate 312*7c478bd9Sstevel@tonic-gate case '}': 313*7c478bd9Sstevel@tonic-gate if (brclev) { 314*7c478bd9Sstevel@tonic-gate brclev--; 315*7c478bd9Sstevel@tonic-gate continue; 316*7c478bd9Sstevel@tonic-gate } 317*7c478bd9Sstevel@tonic-gate goto doit; 318*7c478bd9Sstevel@tonic-gate 319*7c478bd9Sstevel@tonic-gate case ',': 320*7c478bd9Sstevel@tonic-gate if (brclev) 321*7c478bd9Sstevel@tonic-gate continue; 322*7c478bd9Sstevel@tonic-gate doit: 323*7c478bd9Sstevel@tonic-gate savec = *pm; 324*7c478bd9Sstevel@tonic-gate *pm = 0; 325*7c478bd9Sstevel@tonic-gate (void) strcpy_(lm, pl); 326*7c478bd9Sstevel@tonic-gate (void) strcat_(restbuf, pe + 1); 327*7c478bd9Sstevel@tonic-gate *pm = savec; 328*7c478bd9Sstevel@tonic-gate if (s == 0) { 329*7c478bd9Sstevel@tonic-gate sgpathp = gpathp; 330*7c478bd9Sstevel@tonic-gate expand(restbuf); 331*7c478bd9Sstevel@tonic-gate gpathp = sgpathp; 332*7c478bd9Sstevel@tonic-gate *gpathp = 0; 333*7c478bd9Sstevel@tonic-gate } else if (amatch(s, restbuf, &slproc)) 334*7c478bd9Sstevel@tonic-gate return (1); 335*7c478bd9Sstevel@tonic-gate sort(); 336*7c478bd9Sstevel@tonic-gate pl = pm + 1; 337*7c478bd9Sstevel@tonic-gate continue; 338*7c478bd9Sstevel@tonic-gate 339*7c478bd9Sstevel@tonic-gate case '[': 340*7c478bd9Sstevel@tonic-gate for (pm++; *pm && *pm != ']'; pm++) 341*7c478bd9Sstevel@tonic-gate continue; 342*7c478bd9Sstevel@tonic-gate if (!*pm) 343*7c478bd9Sstevel@tonic-gate error("Missing ]"); 344*7c478bd9Sstevel@tonic-gate continue; 345*7c478bd9Sstevel@tonic-gate } 346*7c478bd9Sstevel@tonic-gate return (0); 347*7c478bd9Sstevel@tonic-gate } 348*7c478bd9Sstevel@tonic-gate 349*7c478bd9Sstevel@tonic-gate match(s, p, slproc) 350*7c478bd9Sstevel@tonic-gate tchar *s, *p; 351*7c478bd9Sstevel@tonic-gate int *slproc; 352*7c478bd9Sstevel@tonic-gate { 353*7c478bd9Sstevel@tonic-gate register int c; 354*7c478bd9Sstevel@tonic-gate register tchar *sentp; 355*7c478bd9Sstevel@tonic-gate tchar sglobbed = globbed; 356*7c478bd9Sstevel@tonic-gate 357*7c478bd9Sstevel@tonic-gate #ifdef TRACE 358*7c478bd9Sstevel@tonic-gate tprintf("TRACE- match()\n"); 359*7c478bd9Sstevel@tonic-gate #endif 360*7c478bd9Sstevel@tonic-gate if (*s == '.' && *p != '.') 361*7c478bd9Sstevel@tonic-gate return (0); 362*7c478bd9Sstevel@tonic-gate sentp = entp; 363*7c478bd9Sstevel@tonic-gate entp = s; 364*7c478bd9Sstevel@tonic-gate c = amatch(s, p, slproc); 365*7c478bd9Sstevel@tonic-gate entp = sentp; 366*7c478bd9Sstevel@tonic-gate globbed = sglobbed; 367*7c478bd9Sstevel@tonic-gate return (c); 368*7c478bd9Sstevel@tonic-gate } 369*7c478bd9Sstevel@tonic-gate 370*7c478bd9Sstevel@tonic-gate amatch(s, p, slproc) 371*7c478bd9Sstevel@tonic-gate register tchar *s, *p; 372*7c478bd9Sstevel@tonic-gate int *slproc; 373*7c478bd9Sstevel@tonic-gate { 374*7c478bd9Sstevel@tonic-gate register int scc; 375*7c478bd9Sstevel@tonic-gate int ok, lc; 376*7c478bd9Sstevel@tonic-gate tchar *sgpathp; 377*7c478bd9Sstevel@tonic-gate struct stat stb; 378*7c478bd9Sstevel@tonic-gate int c, cc; 379*7c478bd9Sstevel@tonic-gate 380*7c478bd9Sstevel@tonic-gate #ifdef TRACE 381*7c478bd9Sstevel@tonic-gate tprintf("TRACE- amatch()\n"); 382*7c478bd9Sstevel@tonic-gate #endif 383*7c478bd9Sstevel@tonic-gate globbed = 1; 384*7c478bd9Sstevel@tonic-gate for (;;) { 385*7c478bd9Sstevel@tonic-gate scc = *s++ & TRIM; 386*7c478bd9Sstevel@tonic-gate switch (c = *p++) { 387*7c478bd9Sstevel@tonic-gate 388*7c478bd9Sstevel@tonic-gate case '{': 389*7c478bd9Sstevel@tonic-gate return (execbrc(p - 1, s - 1)); 390*7c478bd9Sstevel@tonic-gate 391*7c478bd9Sstevel@tonic-gate case '[': 392*7c478bd9Sstevel@tonic-gate ok = 0; 393*7c478bd9Sstevel@tonic-gate lc = TRIM; 394*7c478bd9Sstevel@tonic-gate while (cc = *p++) { 395*7c478bd9Sstevel@tonic-gate if (cc == ']') { 396*7c478bd9Sstevel@tonic-gate if (ok) 397*7c478bd9Sstevel@tonic-gate break; 398*7c478bd9Sstevel@tonic-gate return (0); 399*7c478bd9Sstevel@tonic-gate } 400*7c478bd9Sstevel@tonic-gate if (cc == '-') { 401*7c478bd9Sstevel@tonic-gate #ifdef MBCHAR 402*7c478bd9Sstevel@tonic-gate wchar_t rc = *p++; 403*7c478bd9Sstevel@tonic-gate if (rc == ']') { 404*7c478bd9Sstevel@tonic-gate p--; 405*7c478bd9Sstevel@tonic-gate continue; 406*7c478bd9Sstevel@tonic-gate } 407*7c478bd9Sstevel@tonic-gate /* 408*7c478bd9Sstevel@tonic-gate * Both ends of the char range 409*7c478bd9Sstevel@tonic-gate * must belong to the same codeset. 410*7c478bd9Sstevel@tonic-gate */ 411*7c478bd9Sstevel@tonic-gate if (sh_bracket_exp(scc, lc, rc)) 412*7c478bd9Sstevel@tonic-gate ok++; 413*7c478bd9Sstevel@tonic-gate #else /* !MBCHAR */ 414*7c478bd9Sstevel@tonic-gate if (lc <= scc && scc <= (int) *p++) 415*7c478bd9Sstevel@tonic-gate ok++; 416*7c478bd9Sstevel@tonic-gate #endif /* !MBCHAR */ 417*7c478bd9Sstevel@tonic-gate } else 418*7c478bd9Sstevel@tonic-gate if (scc == (lc = cc)) 419*7c478bd9Sstevel@tonic-gate ok++; 420*7c478bd9Sstevel@tonic-gate } 421*7c478bd9Sstevel@tonic-gate if (cc == 0) 422*7c478bd9Sstevel@tonic-gate error("Missing ]"); 423*7c478bd9Sstevel@tonic-gate continue; 424*7c478bd9Sstevel@tonic-gate 425*7c478bd9Sstevel@tonic-gate case '*': 426*7c478bd9Sstevel@tonic-gate if (!*p) 427*7c478bd9Sstevel@tonic-gate return (1); 428*7c478bd9Sstevel@tonic-gate if (*p == '/') { 429*7c478bd9Sstevel@tonic-gate p++; 430*7c478bd9Sstevel@tonic-gate goto slash; 431*7c478bd9Sstevel@tonic-gate } else if (*p == '*') { 432*7c478bd9Sstevel@tonic-gate s--; 433*7c478bd9Sstevel@tonic-gate continue; 434*7c478bd9Sstevel@tonic-gate } 435*7c478bd9Sstevel@tonic-gate 436*7c478bd9Sstevel@tonic-gate for (s--; *s; s++) 437*7c478bd9Sstevel@tonic-gate if (amatch(s, p, slproc)) 438*7c478bd9Sstevel@tonic-gate return (1); 439*7c478bd9Sstevel@tonic-gate 440*7c478bd9Sstevel@tonic-gate return (0); 441*7c478bd9Sstevel@tonic-gate 442*7c478bd9Sstevel@tonic-gate case 0: 443*7c478bd9Sstevel@tonic-gate return (scc == 0); 444*7c478bd9Sstevel@tonic-gate 445*7c478bd9Sstevel@tonic-gate default: 446*7c478bd9Sstevel@tonic-gate if ((c & TRIM) != scc) 447*7c478bd9Sstevel@tonic-gate return (0); 448*7c478bd9Sstevel@tonic-gate continue; 449*7c478bd9Sstevel@tonic-gate 450*7c478bd9Sstevel@tonic-gate case '?': 451*7c478bd9Sstevel@tonic-gate if (scc == 0) 452*7c478bd9Sstevel@tonic-gate return (0); 453*7c478bd9Sstevel@tonic-gate continue; 454*7c478bd9Sstevel@tonic-gate 455*7c478bd9Sstevel@tonic-gate case '/': 456*7c478bd9Sstevel@tonic-gate if (scc) 457*7c478bd9Sstevel@tonic-gate return (0); 458*7c478bd9Sstevel@tonic-gate slash: 459*7c478bd9Sstevel@tonic-gate if (*slproc) /* Need to expand "/" only once */ 460*7c478bd9Sstevel@tonic-gate return (0); 461*7c478bd9Sstevel@tonic-gate else 462*7c478bd9Sstevel@tonic-gate *slproc = 1; 463*7c478bd9Sstevel@tonic-gate 464*7c478bd9Sstevel@tonic-gate s = entp; 465*7c478bd9Sstevel@tonic-gate sgpathp = gpathp; 466*7c478bd9Sstevel@tonic-gate while (*s) 467*7c478bd9Sstevel@tonic-gate addpath(*s++); 468*7c478bd9Sstevel@tonic-gate addpath('/'); 469*7c478bd9Sstevel@tonic-gate if (stat_(gpath, &stb) == 0 && isdir(stb)) 470*7c478bd9Sstevel@tonic-gate if (*p == 0) { 471*7c478bd9Sstevel@tonic-gate Gcat(gpath, S_ /* "" */); 472*7c478bd9Sstevel@tonic-gate globcnt++; 473*7c478bd9Sstevel@tonic-gate } else 474*7c478bd9Sstevel@tonic-gate expand(p); 475*7c478bd9Sstevel@tonic-gate gpathp = sgpathp; 476*7c478bd9Sstevel@tonic-gate *gpathp = 0; 477*7c478bd9Sstevel@tonic-gate return (0); 478*7c478bd9Sstevel@tonic-gate } 479*7c478bd9Sstevel@tonic-gate } 480*7c478bd9Sstevel@tonic-gate } 481*7c478bd9Sstevel@tonic-gate 482*7c478bd9Sstevel@tonic-gate Gmatch(s, p) 483*7c478bd9Sstevel@tonic-gate register tchar *s, *p; 484*7c478bd9Sstevel@tonic-gate { 485*7c478bd9Sstevel@tonic-gate register int scc; 486*7c478bd9Sstevel@tonic-gate int ok, lc; 487*7c478bd9Sstevel@tonic-gate int c, cc; 488*7c478bd9Sstevel@tonic-gate 489*7c478bd9Sstevel@tonic-gate #ifdef TRACE 490*7c478bd9Sstevel@tonic-gate tprintf("TRACE- Gmatch()\n"); 491*7c478bd9Sstevel@tonic-gate #endif 492*7c478bd9Sstevel@tonic-gate for (;;) { 493*7c478bd9Sstevel@tonic-gate scc = *s++ & TRIM; 494*7c478bd9Sstevel@tonic-gate switch (c = *p++) { 495*7c478bd9Sstevel@tonic-gate 496*7c478bd9Sstevel@tonic-gate case '[': 497*7c478bd9Sstevel@tonic-gate ok = 0; 498*7c478bd9Sstevel@tonic-gate lc = TRIM; 499*7c478bd9Sstevel@tonic-gate while (cc = *p++) { 500*7c478bd9Sstevel@tonic-gate if (cc == ']') { 501*7c478bd9Sstevel@tonic-gate if (ok) 502*7c478bd9Sstevel@tonic-gate break; 503*7c478bd9Sstevel@tonic-gate return (0); 504*7c478bd9Sstevel@tonic-gate } 505*7c478bd9Sstevel@tonic-gate if (cc == '-') { 506*7c478bd9Sstevel@tonic-gate #ifdef MBCHAR 507*7c478bd9Sstevel@tonic-gate wchar_t rc = *p++; 508*7c478bd9Sstevel@tonic-gate /* 509*7c478bd9Sstevel@tonic-gate * Both ends of the char range 510*7c478bd9Sstevel@tonic-gate * must belong to the same codeset... 511*7c478bd9Sstevel@tonic-gate */ 512*7c478bd9Sstevel@tonic-gate if (sh_bracket_exp(scc, lc, rc)) 513*7c478bd9Sstevel@tonic-gate ok++; 514*7c478bd9Sstevel@tonic-gate #else /* !MBCHAR */ 515*7c478bd9Sstevel@tonic-gate if (lc <= scc && scc <= (int) *p++) 516*7c478bd9Sstevel@tonic-gate ok++; 517*7c478bd9Sstevel@tonic-gate #endif /* !MBCHAR */ 518*7c478bd9Sstevel@tonic-gate } else 519*7c478bd9Sstevel@tonic-gate if (scc == (lc = cc)) 520*7c478bd9Sstevel@tonic-gate ok++; 521*7c478bd9Sstevel@tonic-gate } 522*7c478bd9Sstevel@tonic-gate if (cc == 0) 523*7c478bd9Sstevel@tonic-gate bferr("Missing ]"); 524*7c478bd9Sstevel@tonic-gate continue; 525*7c478bd9Sstevel@tonic-gate 526*7c478bd9Sstevel@tonic-gate case '*': 527*7c478bd9Sstevel@tonic-gate if (!*p) 528*7c478bd9Sstevel@tonic-gate return (1); 529*7c478bd9Sstevel@tonic-gate for (s--; *s; s++) 530*7c478bd9Sstevel@tonic-gate if (Gmatch(s, p)) 531*7c478bd9Sstevel@tonic-gate return (1); 532*7c478bd9Sstevel@tonic-gate return (0); 533*7c478bd9Sstevel@tonic-gate 534*7c478bd9Sstevel@tonic-gate case 0: 535*7c478bd9Sstevel@tonic-gate return (scc == 0); 536*7c478bd9Sstevel@tonic-gate 537*7c478bd9Sstevel@tonic-gate default: 538*7c478bd9Sstevel@tonic-gate if ((c & TRIM) != scc) 539*7c478bd9Sstevel@tonic-gate return (0); 540*7c478bd9Sstevel@tonic-gate continue; 541*7c478bd9Sstevel@tonic-gate 542*7c478bd9Sstevel@tonic-gate case '?': 543*7c478bd9Sstevel@tonic-gate if (scc == 0) 544*7c478bd9Sstevel@tonic-gate return (0); 545*7c478bd9Sstevel@tonic-gate continue; 546*7c478bd9Sstevel@tonic-gate 547*7c478bd9Sstevel@tonic-gate } 548*7c478bd9Sstevel@tonic-gate } 549*7c478bd9Sstevel@tonic-gate } 550*7c478bd9Sstevel@tonic-gate 551*7c478bd9Sstevel@tonic-gate Gcat(s1, s2) 552*7c478bd9Sstevel@tonic-gate tchar *s1, *s2; 553*7c478bd9Sstevel@tonic-gate { 554*7c478bd9Sstevel@tonic-gate register tchar *p, *q; 555*7c478bd9Sstevel@tonic-gate int n; 556*7c478bd9Sstevel@tonic-gate 557*7c478bd9Sstevel@tonic-gate #ifdef TRACE 558*7c478bd9Sstevel@tonic-gate tprintf("TRACE- Gcat()\n"); 559*7c478bd9Sstevel@tonic-gate #endif 560*7c478bd9Sstevel@tonic-gate for (p = s1; *p++; ) 561*7c478bd9Sstevel@tonic-gate ; 562*7c478bd9Sstevel@tonic-gate for (q = s2; *q++; ) 563*7c478bd9Sstevel@tonic-gate ; 564*7c478bd9Sstevel@tonic-gate gnleft -= (n = (p - s1) + (q - s2) - 1); 565*7c478bd9Sstevel@tonic-gate if (gnleft <= 0 || ++gargc >= GAVSIZ) 566*7c478bd9Sstevel@tonic-gate error("Arguments too long"); 567*7c478bd9Sstevel@tonic-gate gargv[gargc] = 0; 568*7c478bd9Sstevel@tonic-gate p = gargv[gargc - 1] = (tchar *) xalloc((unsigned)n*sizeof (tchar)); 569*7c478bd9Sstevel@tonic-gate 570*7c478bd9Sstevel@tonic-gate for (q = s1; *p++ = *q++; ) 571*7c478bd9Sstevel@tonic-gate ; 572*7c478bd9Sstevel@tonic-gate for (p--, q = s2; *p++ = *q++; ) 573*7c478bd9Sstevel@tonic-gate ; 574*7c478bd9Sstevel@tonic-gate } 575*7c478bd9Sstevel@tonic-gate 576*7c478bd9Sstevel@tonic-gate addpath(c) 577*7c478bd9Sstevel@tonic-gate tchar c; 578*7c478bd9Sstevel@tonic-gate { 579*7c478bd9Sstevel@tonic-gate 580*7c478bd9Sstevel@tonic-gate #ifdef TRACE 581*7c478bd9Sstevel@tonic-gate tprintf("TRACE- addpath()\n"); 582*7c478bd9Sstevel@tonic-gate #endif 583*7c478bd9Sstevel@tonic-gate if (gpathp >= lastgpathp) 584*7c478bd9Sstevel@tonic-gate error("Pathname too long"); 585*7c478bd9Sstevel@tonic-gate *gpathp++ = c & TRIM; 586*7c478bd9Sstevel@tonic-gate *gpathp = 0; 587*7c478bd9Sstevel@tonic-gate } 588*7c478bd9Sstevel@tonic-gate 589*7c478bd9Sstevel@tonic-gate rscan(t, f) 590*7c478bd9Sstevel@tonic-gate register tchar **t; 591*7c478bd9Sstevel@tonic-gate int (*f)(); 592*7c478bd9Sstevel@tonic-gate { 593*7c478bd9Sstevel@tonic-gate register tchar *p; 594*7c478bd9Sstevel@tonic-gate 595*7c478bd9Sstevel@tonic-gate #ifdef TRACE 596*7c478bd9Sstevel@tonic-gate tprintf("TRACE- rscan()\n"); 597*7c478bd9Sstevel@tonic-gate #endif 598*7c478bd9Sstevel@tonic-gate while (p = *t++) 599*7c478bd9Sstevel@tonic-gate while (*p) 600*7c478bd9Sstevel@tonic-gate (*f)(*p++); 601*7c478bd9Sstevel@tonic-gate } 602*7c478bd9Sstevel@tonic-gate 603*7c478bd9Sstevel@tonic-gate trim(t) 604*7c478bd9Sstevel@tonic-gate register tchar **t; 605*7c478bd9Sstevel@tonic-gate { 606*7c478bd9Sstevel@tonic-gate register tchar *p; 607*7c478bd9Sstevel@tonic-gate 608*7c478bd9Sstevel@tonic-gate #ifdef TRACE 609*7c478bd9Sstevel@tonic-gate tprintf("TRACE- trim()\n"); 610*7c478bd9Sstevel@tonic-gate #endif 611*7c478bd9Sstevel@tonic-gate while (p = *t++) 612*7c478bd9Sstevel@tonic-gate while (*p) 613*7c478bd9Sstevel@tonic-gate *p++ &= TRIM; 614*7c478bd9Sstevel@tonic-gate } 615*7c478bd9Sstevel@tonic-gate 616*7c478bd9Sstevel@tonic-gate tglob(t) 617*7c478bd9Sstevel@tonic-gate register tchar **t; 618*7c478bd9Sstevel@tonic-gate { 619*7c478bd9Sstevel@tonic-gate register tchar *p, c; 620*7c478bd9Sstevel@tonic-gate 621*7c478bd9Sstevel@tonic-gate #ifdef TRACE 622*7c478bd9Sstevel@tonic-gate tprintf("TRACE- tglob()\n"); 623*7c478bd9Sstevel@tonic-gate #endif 624*7c478bd9Sstevel@tonic-gate while (p = *t++) { 625*7c478bd9Sstevel@tonic-gate if (*p == '~') 626*7c478bd9Sstevel@tonic-gate gflag |= 2; 627*7c478bd9Sstevel@tonic-gate else if (*p == '{' && (p[1] == '\0' || 628*7c478bd9Sstevel@tonic-gate p[1] == '}' && p[2] == '\0')) 629*7c478bd9Sstevel@tonic-gate continue; 630*7c478bd9Sstevel@tonic-gate while (c = *p++) 631*7c478bd9Sstevel@tonic-gate if (isglob(c)) 632*7c478bd9Sstevel@tonic-gate gflag |= c == '{' ? 2 : 1; 633*7c478bd9Sstevel@tonic-gate } 634*7c478bd9Sstevel@tonic-gate } 635*7c478bd9Sstevel@tonic-gate 636*7c478bd9Sstevel@tonic-gate tchar * 637*7c478bd9Sstevel@tonic-gate globone(str) 638*7c478bd9Sstevel@tonic-gate register tchar *str; 639*7c478bd9Sstevel@tonic-gate { 640*7c478bd9Sstevel@tonic-gate tchar *gv[2]; 641*7c478bd9Sstevel@tonic-gate register tchar **gvp; 642*7c478bd9Sstevel@tonic-gate register tchar *cp; 643*7c478bd9Sstevel@tonic-gate 644*7c478bd9Sstevel@tonic-gate #ifdef TRACE 645*7c478bd9Sstevel@tonic-gate tprintf("TRACE- globone()\n"); 646*7c478bd9Sstevel@tonic-gate #endif 647*7c478bd9Sstevel@tonic-gate gv[0] = str; 648*7c478bd9Sstevel@tonic-gate gv[1] = 0; 649*7c478bd9Sstevel@tonic-gate gflag = 0; 650*7c478bd9Sstevel@tonic-gate tglob(gv); 651*7c478bd9Sstevel@tonic-gate if (gflag) { 652*7c478bd9Sstevel@tonic-gate gvp = glob(gv); 653*7c478bd9Sstevel@tonic-gate if (gvp == 0) { 654*7c478bd9Sstevel@tonic-gate setname(str); 655*7c478bd9Sstevel@tonic-gate bferr("No match"); 656*7c478bd9Sstevel@tonic-gate } 657*7c478bd9Sstevel@tonic-gate cp = *gvp++; 658*7c478bd9Sstevel@tonic-gate if (cp == 0) 659*7c478bd9Sstevel@tonic-gate cp = S_ /* "" */; 660*7c478bd9Sstevel@tonic-gate else if (*gvp) { 661*7c478bd9Sstevel@tonic-gate setname(str); 662*7c478bd9Sstevel@tonic-gate bferr("Ambiguous"); 663*7c478bd9Sstevel@tonic-gate } else 664*7c478bd9Sstevel@tonic-gate cp = strip(cp); 665*7c478bd9Sstevel@tonic-gate /* 666*7c478bd9Sstevel@tonic-gate if (cp == 0 || *gvp) { 667*7c478bd9Sstevel@tonic-gate setname(str); 668*7c478bd9Sstevel@tonic-gate bferr(cp ? "Ambiguous" : "No output"); 669*7c478bd9Sstevel@tonic-gate } 670*7c478bd9Sstevel@tonic-gate */ 671*7c478bd9Sstevel@tonic-gate xfree((char *)gargv); gargv = 0; 672*7c478bd9Sstevel@tonic-gate } else { 673*7c478bd9Sstevel@tonic-gate trim(gv); 674*7c478bd9Sstevel@tonic-gate cp = savestr(gv[0]); 675*7c478bd9Sstevel@tonic-gate } 676*7c478bd9Sstevel@tonic-gate return (cp); 677*7c478bd9Sstevel@tonic-gate } 678*7c478bd9Sstevel@tonic-gate 679*7c478bd9Sstevel@tonic-gate /* 680*7c478bd9Sstevel@tonic-gate * Command substitute cp. If literal, then this is 681*7c478bd9Sstevel@tonic-gate * a substitution from a << redirection, and so we should 682*7c478bd9Sstevel@tonic-gate * not crunch blanks and tabs, separating words only at newlines. 683*7c478bd9Sstevel@tonic-gate */ 684*7c478bd9Sstevel@tonic-gate tchar ** 685*7c478bd9Sstevel@tonic-gate dobackp(cp, literal) 686*7c478bd9Sstevel@tonic-gate tchar *cp; 687*7c478bd9Sstevel@tonic-gate bool literal; 688*7c478bd9Sstevel@tonic-gate { 689*7c478bd9Sstevel@tonic-gate register tchar *lp, *rp; 690*7c478bd9Sstevel@tonic-gate tchar *ep; 691*7c478bd9Sstevel@tonic-gate tchar word[BUFSIZ]; 692*7c478bd9Sstevel@tonic-gate tchar *apargv[GAVSIZ + 2]; 693*7c478bd9Sstevel@tonic-gate 694*7c478bd9Sstevel@tonic-gate #ifdef TRACE 695*7c478bd9Sstevel@tonic-gate tprintf("TRACE- dobackp()\n"); 696*7c478bd9Sstevel@tonic-gate #endif 697*7c478bd9Sstevel@tonic-gate if (pargv) { 698*7c478bd9Sstevel@tonic-gate blkfree(pargv); 699*7c478bd9Sstevel@tonic-gate } 700*7c478bd9Sstevel@tonic-gate pargv = apargv; 701*7c478bd9Sstevel@tonic-gate pargv[0] = NOSTR; 702*7c478bd9Sstevel@tonic-gate pargcp = pargs = word; 703*7c478bd9Sstevel@tonic-gate pargc = 0; 704*7c478bd9Sstevel@tonic-gate pnleft = BUFSIZ - 4; 705*7c478bd9Sstevel@tonic-gate for (;;) { 706*7c478bd9Sstevel@tonic-gate for (lp = cp; *lp != '`'; lp++) { 707*7c478bd9Sstevel@tonic-gate if (*lp == 0) { 708*7c478bd9Sstevel@tonic-gate if (pargcp != pargs) 709*7c478bd9Sstevel@tonic-gate pword(); 710*7c478bd9Sstevel@tonic-gate #ifdef GDEBUG 711*7c478bd9Sstevel@tonic-gate printf("leaving dobackp\n"); 712*7c478bd9Sstevel@tonic-gate #endif 713*7c478bd9Sstevel@tonic-gate return (pargv = copyblk(pargv)); 714*7c478bd9Sstevel@tonic-gate } 715*7c478bd9Sstevel@tonic-gate psave(*lp); 716*7c478bd9Sstevel@tonic-gate } 717*7c478bd9Sstevel@tonic-gate lp++; 718*7c478bd9Sstevel@tonic-gate for (rp = lp; *rp && *rp != '`'; rp++) 719*7c478bd9Sstevel@tonic-gate if (*rp == '\\') { 720*7c478bd9Sstevel@tonic-gate rp++; 721*7c478bd9Sstevel@tonic-gate if (!*rp) 722*7c478bd9Sstevel@tonic-gate goto oops; 723*7c478bd9Sstevel@tonic-gate } 724*7c478bd9Sstevel@tonic-gate if (!*rp) 725*7c478bd9Sstevel@tonic-gate oops: 726*7c478bd9Sstevel@tonic-gate error("Unmatched `"); 727*7c478bd9Sstevel@tonic-gate ep = savestr(lp); 728*7c478bd9Sstevel@tonic-gate ep[rp - lp] = 0; 729*7c478bd9Sstevel@tonic-gate backeval(ep, literal); 730*7c478bd9Sstevel@tonic-gate #ifdef GDEBUG 731*7c478bd9Sstevel@tonic-gate printf("back from backeval\n"); 732*7c478bd9Sstevel@tonic-gate #endif 733*7c478bd9Sstevel@tonic-gate cp = rp + 1; 734*7c478bd9Sstevel@tonic-gate } 735*7c478bd9Sstevel@tonic-gate } 736*7c478bd9Sstevel@tonic-gate 737*7c478bd9Sstevel@tonic-gate backeval(cp, literal) 738*7c478bd9Sstevel@tonic-gate tchar *cp; 739*7c478bd9Sstevel@tonic-gate bool literal; 740*7c478bd9Sstevel@tonic-gate { 741*7c478bd9Sstevel@tonic-gate int pvec[2]; 742*7c478bd9Sstevel@tonic-gate int quoted = (literal || (cp[0] & QUOTE)) ? QUOTE : 0; 743*7c478bd9Sstevel@tonic-gate tchar ibuf[BUFSIZ]; 744*7c478bd9Sstevel@tonic-gate register int icnt = 0, c; 745*7c478bd9Sstevel@tonic-gate register tchar *ip; 746*7c478bd9Sstevel@tonic-gate bool hadnl = 0; 747*7c478bd9Sstevel@tonic-gate tchar *fakecom[2]; 748*7c478bd9Sstevel@tonic-gate struct command faket; 749*7c478bd9Sstevel@tonic-gate 750*7c478bd9Sstevel@tonic-gate #ifdef TRACE 751*7c478bd9Sstevel@tonic-gate tprintf("TRACE- backeval()\n"); 752*7c478bd9Sstevel@tonic-gate #endif 753*7c478bd9Sstevel@tonic-gate faket.t_dtyp = TCOM; 754*7c478bd9Sstevel@tonic-gate faket.t_dflg = 0; 755*7c478bd9Sstevel@tonic-gate faket.t_dlef = 0; 756*7c478bd9Sstevel@tonic-gate faket.t_drit = 0; 757*7c478bd9Sstevel@tonic-gate faket.t_dspr = 0; 758*7c478bd9Sstevel@tonic-gate faket.t_dcom = fakecom; 759*7c478bd9Sstevel@tonic-gate fakecom[0] = S_QPPPQ; /* "` ... `" */; 760*7c478bd9Sstevel@tonic-gate fakecom[1] = 0; 761*7c478bd9Sstevel@tonic-gate /* 762*7c478bd9Sstevel@tonic-gate * We do the psave job to temporarily change the current job 763*7c478bd9Sstevel@tonic-gate * so that the following fork is considered a separate job. 764*7c478bd9Sstevel@tonic-gate * This is so that when backquotes are used in a 765*7c478bd9Sstevel@tonic-gate * builtin function that calls glob the "current job" is not corrupted. 766*7c478bd9Sstevel@tonic-gate * We only need one level of pushed jobs as long as we are sure to 767*7c478bd9Sstevel@tonic-gate * fork here. 768*7c478bd9Sstevel@tonic-gate */ 769*7c478bd9Sstevel@tonic-gate psavejob(); 770*7c478bd9Sstevel@tonic-gate /* 771*7c478bd9Sstevel@tonic-gate * It would be nicer if we could integrate this redirection more 772*7c478bd9Sstevel@tonic-gate * with the routines in sh.sem.c by doing a fake execute on a builtin 773*7c478bd9Sstevel@tonic-gate * function that was piped out. 774*7c478bd9Sstevel@tonic-gate */ 775*7c478bd9Sstevel@tonic-gate mypipe(pvec); 776*7c478bd9Sstevel@tonic-gate if (pfork(&faket, -1) == 0) { 777*7c478bd9Sstevel@tonic-gate struct wordent paraml; 778*7c478bd9Sstevel@tonic-gate struct command *t; 779*7c478bd9Sstevel@tonic-gate tchar oHIST; 780*7c478bd9Sstevel@tonic-gate 781*7c478bd9Sstevel@tonic-gate new_process(); 782*7c478bd9Sstevel@tonic-gate (void) close(pvec[0]); 783*7c478bd9Sstevel@tonic-gate unsetfd(pvec[0]); 784*7c478bd9Sstevel@tonic-gate (void) dmove(pvec[1], 1); 785*7c478bd9Sstevel@tonic-gate (void) dmove(SHDIAG, 2); 786*7c478bd9Sstevel@tonic-gate reinitdesc(0, NULL); 787*7c478bd9Sstevel@tonic-gate arginp = cp; 788*7c478bd9Sstevel@tonic-gate while (*cp) 789*7c478bd9Sstevel@tonic-gate *cp++ &= TRIM; 790*7c478bd9Sstevel@tonic-gate /* 791*7c478bd9Sstevel@tonic-gate * disable history subsitution in sub-shell 792*7c478bd9Sstevel@tonic-gate * of `` evaluation prevents possible 793*7c478bd9Sstevel@tonic-gate * infinite recursion of `` evaluation 794*7c478bd9Sstevel@tonic-gate */ 795*7c478bd9Sstevel@tonic-gate oHIST = HIST; 796*7c478bd9Sstevel@tonic-gate HIST = 0; 797*7c478bd9Sstevel@tonic-gate (void) lex(¶ml); 798*7c478bd9Sstevel@tonic-gate HIST = oHIST; 799*7c478bd9Sstevel@tonic-gate if (err) 800*7c478bd9Sstevel@tonic-gate error("%s", gettext(err)); 801*7c478bd9Sstevel@tonic-gate alias(¶ml); 802*7c478bd9Sstevel@tonic-gate t = syntax(paraml.next, ¶ml, 0); 803*7c478bd9Sstevel@tonic-gate if (err) 804*7c478bd9Sstevel@tonic-gate error("%s", gettext(err)); 805*7c478bd9Sstevel@tonic-gate if (t) 806*7c478bd9Sstevel@tonic-gate t->t_dflg |= FPAR; 807*7c478bd9Sstevel@tonic-gate (void) signal(SIGTSTP, SIG_IGN); 808*7c478bd9Sstevel@tonic-gate (void) signal(SIGTTIN, SIG_IGN); 809*7c478bd9Sstevel@tonic-gate (void) signal(SIGTTOU, SIG_IGN); 810*7c478bd9Sstevel@tonic-gate execute(t, -1); 811*7c478bd9Sstevel@tonic-gate exitstat(); 812*7c478bd9Sstevel@tonic-gate } 813*7c478bd9Sstevel@tonic-gate xfree(cp); 814*7c478bd9Sstevel@tonic-gate (void) close(pvec[1]); 815*7c478bd9Sstevel@tonic-gate unsetfd(pvec[1]); 816*7c478bd9Sstevel@tonic-gate do { 817*7c478bd9Sstevel@tonic-gate int cnt = 0; 818*7c478bd9Sstevel@tonic-gate for (;;) { 819*7c478bd9Sstevel@tonic-gate if (icnt == 0) { 820*7c478bd9Sstevel@tonic-gate ip = ibuf; 821*7c478bd9Sstevel@tonic-gate icnt = read_(pvec[0], ip, BUFSIZ); 822*7c478bd9Sstevel@tonic-gate if (icnt <= 0) { 823*7c478bd9Sstevel@tonic-gate c = -1; 824*7c478bd9Sstevel@tonic-gate break; 825*7c478bd9Sstevel@tonic-gate } 826*7c478bd9Sstevel@tonic-gate } 827*7c478bd9Sstevel@tonic-gate if (hadnl) 828*7c478bd9Sstevel@tonic-gate break; 829*7c478bd9Sstevel@tonic-gate --icnt; 830*7c478bd9Sstevel@tonic-gate c = (*ip++ & TRIM); 831*7c478bd9Sstevel@tonic-gate if (c == 0) 832*7c478bd9Sstevel@tonic-gate break; 833*7c478bd9Sstevel@tonic-gate if (c == '\n') { 834*7c478bd9Sstevel@tonic-gate /* 835*7c478bd9Sstevel@tonic-gate * Continue around the loop one 836*7c478bd9Sstevel@tonic-gate * more time, so that we can eat 837*7c478bd9Sstevel@tonic-gate * the last newline without terminating 838*7c478bd9Sstevel@tonic-gate * this word. 839*7c478bd9Sstevel@tonic-gate */ 840*7c478bd9Sstevel@tonic-gate hadnl = 1; 841*7c478bd9Sstevel@tonic-gate continue; 842*7c478bd9Sstevel@tonic-gate } 843*7c478bd9Sstevel@tonic-gate if (!quoted && issp(c)) 844*7c478bd9Sstevel@tonic-gate break; 845*7c478bd9Sstevel@tonic-gate cnt++; 846*7c478bd9Sstevel@tonic-gate psave(c | quoted); 847*7c478bd9Sstevel@tonic-gate } 848*7c478bd9Sstevel@tonic-gate /* 849*7c478bd9Sstevel@tonic-gate * Unless at end-of-file, we will form a new word 850*7c478bd9Sstevel@tonic-gate * here if there were characters in the word, or in 851*7c478bd9Sstevel@tonic-gate * any case when we take text literally. If 852*7c478bd9Sstevel@tonic-gate * we didn't make empty words here when literal was 853*7c478bd9Sstevel@tonic-gate * set then we would lose blank lines. 854*7c478bd9Sstevel@tonic-gate */ 855*7c478bd9Sstevel@tonic-gate if (c != -1 && (cnt || literal)) { 856*7c478bd9Sstevel@tonic-gate if (pargc == GAVSIZ) 857*7c478bd9Sstevel@tonic-gate break; 858*7c478bd9Sstevel@tonic-gate pword(); 859*7c478bd9Sstevel@tonic-gate } 860*7c478bd9Sstevel@tonic-gate hadnl = 0; 861*7c478bd9Sstevel@tonic-gate } while (c >= 0); 862*7c478bd9Sstevel@tonic-gate #ifdef GDEBUG 863*7c478bd9Sstevel@tonic-gate printf("done in backeval, pvec: %d %d\n", pvec[0], pvec[1]); 864*7c478bd9Sstevel@tonic-gate printf("also c = %c <%o>\n", (tchar) c, (tchar) c); 865*7c478bd9Sstevel@tonic-gate #endif 866*7c478bd9Sstevel@tonic-gate (void) close(pvec[0]); 867*7c478bd9Sstevel@tonic-gate unsetfd(pvec[0]); 868*7c478bd9Sstevel@tonic-gate pwait(); 869*7c478bd9Sstevel@tonic-gate prestjob(); 870*7c478bd9Sstevel@tonic-gate } 871*7c478bd9Sstevel@tonic-gate 872*7c478bd9Sstevel@tonic-gate psave(c) 873*7c478bd9Sstevel@tonic-gate tchar c; 874*7c478bd9Sstevel@tonic-gate { 875*7c478bd9Sstevel@tonic-gate #ifdef TRACE 876*7c478bd9Sstevel@tonic-gate tprintf("TRACE- psave()\n"); 877*7c478bd9Sstevel@tonic-gate #endif 878*7c478bd9Sstevel@tonic-gate 879*7c478bd9Sstevel@tonic-gate if (--pnleft <= 0) 880*7c478bd9Sstevel@tonic-gate error("Word too long"); 881*7c478bd9Sstevel@tonic-gate *pargcp++ = c; 882*7c478bd9Sstevel@tonic-gate } 883*7c478bd9Sstevel@tonic-gate 884*7c478bd9Sstevel@tonic-gate pword() 885*7c478bd9Sstevel@tonic-gate { 886*7c478bd9Sstevel@tonic-gate #ifdef TRACE 887*7c478bd9Sstevel@tonic-gate tprintf("TRACE- pword()\n"); 888*7c478bd9Sstevel@tonic-gate #endif 889*7c478bd9Sstevel@tonic-gate 890*7c478bd9Sstevel@tonic-gate psave(0); 891*7c478bd9Sstevel@tonic-gate if (pargc == GAVSIZ) 892*7c478bd9Sstevel@tonic-gate error("Too many words from ``"); 893*7c478bd9Sstevel@tonic-gate pargv[pargc++] = savestr(pargs); 894*7c478bd9Sstevel@tonic-gate pargv[pargc] = NOSTR; 895*7c478bd9Sstevel@tonic-gate #ifdef GDEBUG 896*7c478bd9Sstevel@tonic-gate printf("got word %t\n", pargv[pargc-1]); 897*7c478bd9Sstevel@tonic-gate #endif 898*7c478bd9Sstevel@tonic-gate pargcp = pargs; 899*7c478bd9Sstevel@tonic-gate pnleft = BUFSIZ - 4; 900*7c478bd9Sstevel@tonic-gate } 901*7c478bd9Sstevel@tonic-gate 902*7c478bd9Sstevel@tonic-gate 903*7c478bd9Sstevel@tonic-gate 904*7c478bd9Sstevel@tonic-gate /* 905*7c478bd9Sstevel@tonic-gate * returns pathname of the form dir/file; 906*7c478bd9Sstevel@tonic-gate * dir is a null-terminated string; 907*7c478bd9Sstevel@tonic-gate */ 908*7c478bd9Sstevel@tonic-gate char * 909*7c478bd9Sstevel@tonic-gate makename(dir, file) 910*7c478bd9Sstevel@tonic-gate char *dir; 911*7c478bd9Sstevel@tonic-gate char *file; 912*7c478bd9Sstevel@tonic-gate { 913*7c478bd9Sstevel@tonic-gate /* 914*7c478bd9Sstevel@tonic-gate * Maximum length of a 915*7c478bd9Sstevel@tonic-gate * file/dir name in ls-command; 916*7c478bd9Sstevel@tonic-gate * dfile is static as this is returned 917*7c478bd9Sstevel@tonic-gate * by makename(); 918*7c478bd9Sstevel@tonic-gate */ 919*7c478bd9Sstevel@tonic-gate static char dfile[MAXNAMLEN]; 920*7c478bd9Sstevel@tonic-gate 921*7c478bd9Sstevel@tonic-gate register char *dp, *fp; 922*7c478bd9Sstevel@tonic-gate 923*7c478bd9Sstevel@tonic-gate dp = dfile; 924*7c478bd9Sstevel@tonic-gate fp = dir; 925*7c478bd9Sstevel@tonic-gate while (*fp) 926*7c478bd9Sstevel@tonic-gate *dp++ = *fp++; 927*7c478bd9Sstevel@tonic-gate if (dp > dfile && *(dp - 1) != '/') 928*7c478bd9Sstevel@tonic-gate *dp++ = '/'; 929*7c478bd9Sstevel@tonic-gate fp = file; 930*7c478bd9Sstevel@tonic-gate while (*fp) 931*7c478bd9Sstevel@tonic-gate *dp++ = *fp++; 932*7c478bd9Sstevel@tonic-gate *dp = '\0'; 933*7c478bd9Sstevel@tonic-gate /* 934*7c478bd9Sstevel@tonic-gate * dfile points to the absolute pathname. We are 935*7c478bd9Sstevel@tonic-gate * only interested in the last component. 936*7c478bd9Sstevel@tonic-gate */ 937*7c478bd9Sstevel@tonic-gate return (rindex(dfile, '/') + 1); 938*7c478bd9Sstevel@tonic-gate } 939*7c478bd9Sstevel@tonic-gate 940*7c478bd9Sstevel@tonic-gate sh_bracket_exp(t_ch, t_fch, t_lch) 941*7c478bd9Sstevel@tonic-gate tchar t_ch; 942*7c478bd9Sstevel@tonic-gate tchar t_fch; 943*7c478bd9Sstevel@tonic-gate tchar t_lch; 944*7c478bd9Sstevel@tonic-gate { 945*7c478bd9Sstevel@tonic-gate char t_char[MB_LEN_MAX + 1]; 946*7c478bd9Sstevel@tonic-gate char t_patan[MB_LEN_MAX * 2 + 8]; 947*7c478bd9Sstevel@tonic-gate char *p; 948*7c478bd9Sstevel@tonic-gate int i; 949*7c478bd9Sstevel@tonic-gate 950*7c478bd9Sstevel@tonic-gate if ((t_ch == t_fch) || (t_ch == t_lch)) 951*7c478bd9Sstevel@tonic-gate return(1); 952*7c478bd9Sstevel@tonic-gate 953*7c478bd9Sstevel@tonic-gate p = t_patan; 954*7c478bd9Sstevel@tonic-gate if ((i = wctomb(t_char, (wchar_t)t_ch)) <= 0) 955*7c478bd9Sstevel@tonic-gate return(0); 956*7c478bd9Sstevel@tonic-gate t_char[i] = 0; 957*7c478bd9Sstevel@tonic-gate 958*7c478bd9Sstevel@tonic-gate *p++ = '['; 959*7c478bd9Sstevel@tonic-gate if ((i = wctomb(p, (wchar_t)t_fch)) <= 0) 960*7c478bd9Sstevel@tonic-gate return(0); 961*7c478bd9Sstevel@tonic-gate p += i; 962*7c478bd9Sstevel@tonic-gate *p++ = '-'; 963*7c478bd9Sstevel@tonic-gate if ((i = wctomb(p, (wchar_t)t_lch)) <= 0) 964*7c478bd9Sstevel@tonic-gate return(0); 965*7c478bd9Sstevel@tonic-gate p += i; 966*7c478bd9Sstevel@tonic-gate *p++ = ']'; 967*7c478bd9Sstevel@tonic-gate *p = 0; 968*7c478bd9Sstevel@tonic-gate 969*7c478bd9Sstevel@tonic-gate if (fnmatch(t_patan, t_char, FNM_NOESCAPE)) 970*7c478bd9Sstevel@tonic-gate return(0); 971*7c478bd9Sstevel@tonic-gate return(1); 972*7c478bd9Sstevel@tonic-gate } 973