17c478bd9Sstevel@tonic-gate /* 26c02b4a4Smuffin * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 37c478bd9Sstevel@tonic-gate * Use is subject to license terms. 47c478bd9Sstevel@tonic-gate */ 57c478bd9Sstevel@tonic-gate 67c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 77c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 87c478bd9Sstevel@tonic-gate 97c478bd9Sstevel@tonic-gate /* 107c478bd9Sstevel@tonic-gate * Copyright (c) 1980 Regents of the University of California. 117c478bd9Sstevel@tonic-gate * All rights reserved. The Berkeley Software License Agreement 127c478bd9Sstevel@tonic-gate * specifies the terms and conditions for redistribution. 137c478bd9Sstevel@tonic-gate */ 147c478bd9Sstevel@tonic-gate 157c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 167c478bd9Sstevel@tonic-gate 177c478bd9Sstevel@tonic-gate #include "sh.h" 187c478bd9Sstevel@tonic-gate #include "sh.tconst.h" 197c478bd9Sstevel@tonic-gate #include <dirent.h> 206c02b4a4Smuffin #include <strings.h> 217c478bd9Sstevel@tonic-gate #ifdef MBCHAR 227c478bd9Sstevel@tonic-gate #include <widec.h> /* wcsetno() */ 237c478bd9Sstevel@tonic-gate #include <fnmatch.h> /* fnmatch() */ 247c478bd9Sstevel@tonic-gate #endif /* MBCHAR */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate /* 277c478bd9Sstevel@tonic-gate * C Shell 287c478bd9Sstevel@tonic-gate */ 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate int globcnt; 317c478bd9Sstevel@tonic-gate 327c478bd9Sstevel@tonic-gate tchar *gpath, *gpathp, *lastgpathp; 337c478bd9Sstevel@tonic-gate int globbed; 347c478bd9Sstevel@tonic-gate bool noglob; 357c478bd9Sstevel@tonic-gate bool nonomatch; 367c478bd9Sstevel@tonic-gate tchar *entp; 377c478bd9Sstevel@tonic-gate tchar **sortbas; 386c02b4a4Smuffin int sortscmp(tchar **, tchar **); 396c02b4a4Smuffin void ginit(tchar **); 406c02b4a4Smuffin void collect(tchar *); 416c02b4a4Smuffin void acollect(tchar *); 426c02b4a4Smuffin void expand(tchar *); 436c02b4a4Smuffin void matchdir_(tchar *); 446c02b4a4Smuffin void Gcat(tchar *, tchar *); 456c02b4a4Smuffin void addpath(tchar); 466c02b4a4Smuffin void tglob(tchar **); 476c02b4a4Smuffin tchar **dobackp(tchar *, bool); 486c02b4a4Smuffin void backeval(tchar *, bool); 496c02b4a4Smuffin void psave(tchar); 506c02b4a4Smuffin void pword(void); 516c02b4a4Smuffin 526c02b4a4Smuffin extern DIR *opendir_(tchar *); 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate #define sort() qsort((char *)sortbas, &gargv[gargc] - sortbas, \ 557c478bd9Sstevel@tonic-gate sizeof (*sortbas), (int (*)(const void *, \ 567c478bd9Sstevel@tonic-gate const void *)) sortscmp), sortbas = &gargv[gargc] 577c478bd9Sstevel@tonic-gate 587c478bd9Sstevel@tonic-gate 597c478bd9Sstevel@tonic-gate tchar ** 606c02b4a4Smuffin glob(tchar **v) 617c478bd9Sstevel@tonic-gate { 627c478bd9Sstevel@tonic-gate tchar agpath[BUFSIZ]; 637c478bd9Sstevel@tonic-gate tchar *agargv[GAVSIZ]; 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate gpath = agpath; gpathp = gpath; *gpathp = 0; 667c478bd9Sstevel@tonic-gate lastgpathp = &gpath[BUFSIZ - 2]; 677c478bd9Sstevel@tonic-gate ginit(agargv); globcnt = 0; 687c478bd9Sstevel@tonic-gate #ifdef TRACE 697c478bd9Sstevel@tonic-gate tprintf("TRACE- glob()\n"); 707c478bd9Sstevel@tonic-gate #endif 717c478bd9Sstevel@tonic-gate #ifdef GDEBUG 727c478bd9Sstevel@tonic-gate printf("glob entered: "); blkpr(v); printf("\n"); 737c478bd9Sstevel@tonic-gate #endif 747c478bd9Sstevel@tonic-gate noglob = adrof(S_noglob /* "noglob" */) != 0; 757c478bd9Sstevel@tonic-gate nonomatch = adrof(S_nonomatch /* "nonomatch" */) != 0; 767c478bd9Sstevel@tonic-gate globcnt = noglob | nonomatch; 777c478bd9Sstevel@tonic-gate while (*v) 787c478bd9Sstevel@tonic-gate collect(*v++); 797c478bd9Sstevel@tonic-gate #ifdef GDEBUG 807c478bd9Sstevel@tonic-gate printf("glob done, globcnt=%d, gflag=%d: ", globcnt, gflag); 817c478bd9Sstevel@tonic-gate blkpr(gargv); printf("\n"); 827c478bd9Sstevel@tonic-gate #endif 837c478bd9Sstevel@tonic-gate if (globcnt == 0 && (gflag&1)) { 847c478bd9Sstevel@tonic-gate blkfree(gargv), gargv = 0; 857c478bd9Sstevel@tonic-gate return (0); 867c478bd9Sstevel@tonic-gate } else 877c478bd9Sstevel@tonic-gate return (gargv = copyblk(gargv)); 887c478bd9Sstevel@tonic-gate } 897c478bd9Sstevel@tonic-gate 906c02b4a4Smuffin void 916c02b4a4Smuffin ginit(tchar **agargv) 927c478bd9Sstevel@tonic-gate { 937c478bd9Sstevel@tonic-gate 947c478bd9Sstevel@tonic-gate agargv[0] = 0; gargv = agargv; sortbas = agargv; gargc = 0; 957c478bd9Sstevel@tonic-gate gnleft = NCARGS - 4; 967c478bd9Sstevel@tonic-gate } 977c478bd9Sstevel@tonic-gate 986c02b4a4Smuffin void 996c02b4a4Smuffin collect(tchar *as) 1007c478bd9Sstevel@tonic-gate { 1016c02b4a4Smuffin int i; 1027c478bd9Sstevel@tonic-gate 1037c478bd9Sstevel@tonic-gate #ifdef TRACE 1047c478bd9Sstevel@tonic-gate tprintf("TRACE- collect()\n"); 1057c478bd9Sstevel@tonic-gate #endif 1067c478bd9Sstevel@tonic-gate if (any('`', as)) { 1077c478bd9Sstevel@tonic-gate #ifdef GDEBUG 1087c478bd9Sstevel@tonic-gate printf("doing backp of %t\n", as); 1097c478bd9Sstevel@tonic-gate #endif 1107c478bd9Sstevel@tonic-gate (void) dobackp(as, 0); 1117c478bd9Sstevel@tonic-gate #ifdef GDEBUG 1127c478bd9Sstevel@tonic-gate printf("backp done, acollect'ing\n"); 1137c478bd9Sstevel@tonic-gate #endif 1147c478bd9Sstevel@tonic-gate /* 1157c478bd9Sstevel@tonic-gate * dobackp has the side effect of messing with 1167c478bd9Sstevel@tonic-gate * gflag, since it does more globbing, so check 1177c478bd9Sstevel@tonic-gate * if the results is still globbable 1187c478bd9Sstevel@tonic-gate */ 1197c478bd9Sstevel@tonic-gate tglob(pargv); 1207c478bd9Sstevel@tonic-gate 1217c478bd9Sstevel@tonic-gate for (i = 0; i < pargc; i++) 1227c478bd9Sstevel@tonic-gate if (noglob) { 1237c478bd9Sstevel@tonic-gate Gcat(pargv[i], S_ /* "" */); 1247c478bd9Sstevel@tonic-gate sortbas = &gargv[gargc]; 1257c478bd9Sstevel@tonic-gate } else 1267c478bd9Sstevel@tonic-gate acollect(pargv[i]); 1277c478bd9Sstevel@tonic-gate if (pargv) 1287c478bd9Sstevel@tonic-gate blkfree(pargv), pargv = 0; 1297c478bd9Sstevel@tonic-gate #ifdef GDEBUG 1307c478bd9Sstevel@tonic-gate printf("acollect done\n"); 1317c478bd9Sstevel@tonic-gate #endif 1327c478bd9Sstevel@tonic-gate } else if (noglob || eq(as, S_LBRA /* "{" */) || 1337c478bd9Sstevel@tonic-gate eq(as, S_BRABRA /* "{}" */)) { 1347c478bd9Sstevel@tonic-gate Gcat(as, S_ /* "" */); 1357c478bd9Sstevel@tonic-gate sort(); 1367c478bd9Sstevel@tonic-gate } else 1377c478bd9Sstevel@tonic-gate acollect(as); 1387c478bd9Sstevel@tonic-gate } 1397c478bd9Sstevel@tonic-gate 1406c02b4a4Smuffin void 1416c02b4a4Smuffin acollect(tchar *as) 1427c478bd9Sstevel@tonic-gate { 1436c02b4a4Smuffin long ogargc = gargc; 1447c478bd9Sstevel@tonic-gate 1457c478bd9Sstevel@tonic-gate #ifdef TRACE 1467c478bd9Sstevel@tonic-gate tprintf("TRACE- acollect()\n"); 1477c478bd9Sstevel@tonic-gate #endif 1487c478bd9Sstevel@tonic-gate gpathp = gpath; *gpathp = 0; globbed = 0; 1497c478bd9Sstevel@tonic-gate expand(as); 1507c478bd9Sstevel@tonic-gate if (gargc == ogargc) { 1517c478bd9Sstevel@tonic-gate if (nonomatch) { 1527c478bd9Sstevel@tonic-gate Gcat(as, S_ /* "" */); 1537c478bd9Sstevel@tonic-gate sort(); 1547c478bd9Sstevel@tonic-gate } 1557c478bd9Sstevel@tonic-gate } else 1567c478bd9Sstevel@tonic-gate sort(); 1577c478bd9Sstevel@tonic-gate } 1587c478bd9Sstevel@tonic-gate 1597c478bd9Sstevel@tonic-gate /* 1607c478bd9Sstevel@tonic-gate * String compare for qsort. Also used by filec code in sh.file.c. 1617c478bd9Sstevel@tonic-gate */ 1626c02b4a4Smuffin int 1636c02b4a4Smuffin sortscmp(tchar **a1, tchar **a2) 1647c478bd9Sstevel@tonic-gate { 1657c478bd9Sstevel@tonic-gate 1667c478bd9Sstevel@tonic-gate return (strcoll_(*a1, *a2)); 1677c478bd9Sstevel@tonic-gate } 1687c478bd9Sstevel@tonic-gate 1696c02b4a4Smuffin void 1706c02b4a4Smuffin expand(tchar *as) 1717c478bd9Sstevel@tonic-gate { 1726c02b4a4Smuffin tchar *cs; 1736c02b4a4Smuffin tchar *sgpathp, *oldcs; 1747c478bd9Sstevel@tonic-gate struct stat stb; 1757c478bd9Sstevel@tonic-gate 1767c478bd9Sstevel@tonic-gate #ifdef TRACE 1777c478bd9Sstevel@tonic-gate tprintf("TRACE- expand()\n"); 1787c478bd9Sstevel@tonic-gate #endif 1797c478bd9Sstevel@tonic-gate sgpathp = gpathp; 1807c478bd9Sstevel@tonic-gate cs = as; 1817c478bd9Sstevel@tonic-gate if (*cs == '~' && gpathp == gpath) { 1827c478bd9Sstevel@tonic-gate addpath('~'); 1837c478bd9Sstevel@tonic-gate for (cs++; alnum(*cs) || *cs == '-'; ) 1847c478bd9Sstevel@tonic-gate addpath(*cs++); 1857c478bd9Sstevel@tonic-gate if (!*cs || *cs == '/') { 1867c478bd9Sstevel@tonic-gate if (gpathp != gpath + 1) { 1877c478bd9Sstevel@tonic-gate *gpathp = 0; 1887c478bd9Sstevel@tonic-gate if (gethdir(gpath + 1)) 1897c478bd9Sstevel@tonic-gate /* 1907c478bd9Sstevel@tonic-gate * modified from %s to %t 1917c478bd9Sstevel@tonic-gate */ 1927c478bd9Sstevel@tonic-gate error("Unknown user: %t", gpath + 1); 1937c478bd9Sstevel@tonic-gate (void) strcpy_(gpath, gpath + 1); 1947c478bd9Sstevel@tonic-gate } else 1957c478bd9Sstevel@tonic-gate (void) strcpy_(gpath, 1967c478bd9Sstevel@tonic-gate value(S_home /* "home" */)); 1977c478bd9Sstevel@tonic-gate gpathp = strend(gpath); 1987c478bd9Sstevel@tonic-gate } 1997c478bd9Sstevel@tonic-gate } 2007c478bd9Sstevel@tonic-gate while (!isglob(*cs)) { 2017c478bd9Sstevel@tonic-gate if (*cs == 0) { 2027c478bd9Sstevel@tonic-gate if (!globbed) 2037c478bd9Sstevel@tonic-gate Gcat(gpath, S_ /* "" */); 2047c478bd9Sstevel@tonic-gate else if (lstat_(gpath, &stb) >= 0) { 2057c478bd9Sstevel@tonic-gate Gcat(gpath, S_ /* "" */); 2067c478bd9Sstevel@tonic-gate globcnt++; 2077c478bd9Sstevel@tonic-gate } 2087c478bd9Sstevel@tonic-gate goto endit; 2097c478bd9Sstevel@tonic-gate } 2107c478bd9Sstevel@tonic-gate addpath(*cs++); 2117c478bd9Sstevel@tonic-gate } 2127c478bd9Sstevel@tonic-gate oldcs = cs; 2137c478bd9Sstevel@tonic-gate while (cs > as && *cs != '/') 2147c478bd9Sstevel@tonic-gate cs--, gpathp--; 2157c478bd9Sstevel@tonic-gate if (*cs == '/') 2167c478bd9Sstevel@tonic-gate cs++, gpathp++; 2177c478bd9Sstevel@tonic-gate *gpathp = 0; 2187c478bd9Sstevel@tonic-gate if (*oldcs == '{') { 2197c478bd9Sstevel@tonic-gate (void) execbrc(cs, NOSTR); 2207c478bd9Sstevel@tonic-gate return; 2217c478bd9Sstevel@tonic-gate } 2227c478bd9Sstevel@tonic-gate matchdir_(cs); 2237c478bd9Sstevel@tonic-gate endit: 2247c478bd9Sstevel@tonic-gate gpathp = sgpathp; 2257c478bd9Sstevel@tonic-gate *gpathp = 0; 2267c478bd9Sstevel@tonic-gate } 2277c478bd9Sstevel@tonic-gate 2286c02b4a4Smuffin void 2296c02b4a4Smuffin matchdir_(tchar *pattern) 2307c478bd9Sstevel@tonic-gate { 2317c478bd9Sstevel@tonic-gate struct stat stb; 2326c02b4a4Smuffin struct dirent *dp; 2336c02b4a4Smuffin DIR *dirp; 2347c478bd9Sstevel@tonic-gate tchar curdir_[MAXNAMLEN+1]; 2357c478bd9Sstevel@tonic-gate int slproc = 0; 2367c478bd9Sstevel@tonic-gate 2377c478bd9Sstevel@tonic-gate #ifdef TRACE 2387c478bd9Sstevel@tonic-gate tprintf("TRACE- matchdir()\n"); 2397c478bd9Sstevel@tonic-gate #endif 2407c478bd9Sstevel@tonic-gate /* 2417c478bd9Sstevel@tonic-gate * BSD's opendir would open "." if argument is NULL, but not S5 2427c478bd9Sstevel@tonic-gate */ 2437c478bd9Sstevel@tonic-gate 2447c478bd9Sstevel@tonic-gate if (*gpath == NULL) 2457c478bd9Sstevel@tonic-gate dirp = opendir_(S_DOT /* "." */); 2467c478bd9Sstevel@tonic-gate else 2477c478bd9Sstevel@tonic-gate dirp = opendir_(gpath); 2487c478bd9Sstevel@tonic-gate if (dirp == NULL) { 2497c478bd9Sstevel@tonic-gate if (globbed) 2507c478bd9Sstevel@tonic-gate return; 2517c478bd9Sstevel@tonic-gate goto patherr2; 2527c478bd9Sstevel@tonic-gate } 2537c478bd9Sstevel@tonic-gate if (fstat(dirp->dd_fd, &stb) < 0) 2547c478bd9Sstevel@tonic-gate goto patherr1; 2557c478bd9Sstevel@tonic-gate if (!isdir(stb)) { 2567c478bd9Sstevel@tonic-gate errno = ENOTDIR; 2577c478bd9Sstevel@tonic-gate goto patherr1; 2587c478bd9Sstevel@tonic-gate } 2597c478bd9Sstevel@tonic-gate while ((dp = readdir(dirp)) != NULL) { 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gate if (dp->d_ino == 0) 2627c478bd9Sstevel@tonic-gate continue; 2637c478bd9Sstevel@tonic-gate strtots(curdir_, dp->d_name); 2647c478bd9Sstevel@tonic-gate slproc = 0; 2657c478bd9Sstevel@tonic-gate if (match(curdir_, pattern, &slproc)) { 2667c478bd9Sstevel@tonic-gate Gcat(gpath, curdir_); 2677c478bd9Sstevel@tonic-gate globcnt++; 2687c478bd9Sstevel@tonic-gate } 2697c478bd9Sstevel@tonic-gate } 2707c478bd9Sstevel@tonic-gate unsetfd(dirp->dd_fd); 2717c478bd9Sstevel@tonic-gate closedir_(dirp); 2727c478bd9Sstevel@tonic-gate return; 2737c478bd9Sstevel@tonic-gate 2747c478bd9Sstevel@tonic-gate patherr1: 2757c478bd9Sstevel@tonic-gate unsetfd(dirp->dd_fd); 2767c478bd9Sstevel@tonic-gate closedir_(dirp); 2777c478bd9Sstevel@tonic-gate patherr2: 2787c478bd9Sstevel@tonic-gate Perror(gpath); 2797c478bd9Sstevel@tonic-gate } 2807c478bd9Sstevel@tonic-gate 2816c02b4a4Smuffin int 2826c02b4a4Smuffin execbrc(tchar *p, tchar *s) 2837c478bd9Sstevel@tonic-gate { 2847c478bd9Sstevel@tonic-gate tchar restbuf[BUFSIZ + 2]; 2856c02b4a4Smuffin tchar *pe, *pm, *pl; 2867c478bd9Sstevel@tonic-gate int brclev = 0; 2877c478bd9Sstevel@tonic-gate tchar *lm, savec, *sgpathp; 2887c478bd9Sstevel@tonic-gate int slproc = 0; 2897c478bd9Sstevel@tonic-gate 2907c478bd9Sstevel@tonic-gate #ifdef TRACE 2917c478bd9Sstevel@tonic-gate tprintf("TRACE- execbrc()\n"); 2927c478bd9Sstevel@tonic-gate #endif 2937c478bd9Sstevel@tonic-gate for (lm = restbuf; *p != '{'; *lm++ = *p++) 2947c478bd9Sstevel@tonic-gate continue; 2957c478bd9Sstevel@tonic-gate for (pe = ++p; *pe; pe++) 2967c478bd9Sstevel@tonic-gate switch (*pe) { 2977c478bd9Sstevel@tonic-gate 2987c478bd9Sstevel@tonic-gate case '{': 2997c478bd9Sstevel@tonic-gate brclev++; 3007c478bd9Sstevel@tonic-gate continue; 3017c478bd9Sstevel@tonic-gate 3027c478bd9Sstevel@tonic-gate case '}': 3037c478bd9Sstevel@tonic-gate if (brclev == 0) 3047c478bd9Sstevel@tonic-gate goto pend; 3057c478bd9Sstevel@tonic-gate brclev--; 3067c478bd9Sstevel@tonic-gate continue; 3077c478bd9Sstevel@tonic-gate 3087c478bd9Sstevel@tonic-gate case '[': 3097c478bd9Sstevel@tonic-gate for (pe++; *pe && *pe != ']'; pe++) 3107c478bd9Sstevel@tonic-gate continue; 3117c478bd9Sstevel@tonic-gate if (!*pe) 3127c478bd9Sstevel@tonic-gate error("Missing ]"); 3137c478bd9Sstevel@tonic-gate continue; 3147c478bd9Sstevel@tonic-gate } 3157c478bd9Sstevel@tonic-gate pend: 3167c478bd9Sstevel@tonic-gate if (brclev || !*pe) 3177c478bd9Sstevel@tonic-gate error("Missing }"); 3187c478bd9Sstevel@tonic-gate for (pl = pm = p; pm <= pe; pm++) 3197c478bd9Sstevel@tonic-gate switch (*pm & (QUOTE|TRIM)) { 3207c478bd9Sstevel@tonic-gate 3217c478bd9Sstevel@tonic-gate case '{': 3227c478bd9Sstevel@tonic-gate brclev++; 3237c478bd9Sstevel@tonic-gate continue; 3247c478bd9Sstevel@tonic-gate 3257c478bd9Sstevel@tonic-gate case '}': 3267c478bd9Sstevel@tonic-gate if (brclev) { 3277c478bd9Sstevel@tonic-gate brclev--; 3287c478bd9Sstevel@tonic-gate continue; 3297c478bd9Sstevel@tonic-gate } 3307c478bd9Sstevel@tonic-gate goto doit; 3317c478bd9Sstevel@tonic-gate 3327c478bd9Sstevel@tonic-gate case ',': 3337c478bd9Sstevel@tonic-gate if (brclev) 3347c478bd9Sstevel@tonic-gate continue; 3357c478bd9Sstevel@tonic-gate doit: 3367c478bd9Sstevel@tonic-gate savec = *pm; 3377c478bd9Sstevel@tonic-gate *pm = 0; 3387c478bd9Sstevel@tonic-gate (void) strcpy_(lm, pl); 3397c478bd9Sstevel@tonic-gate (void) strcat_(restbuf, pe + 1); 3407c478bd9Sstevel@tonic-gate *pm = savec; 3417c478bd9Sstevel@tonic-gate if (s == 0) { 3427c478bd9Sstevel@tonic-gate sgpathp = gpathp; 3437c478bd9Sstevel@tonic-gate expand(restbuf); 3447c478bd9Sstevel@tonic-gate gpathp = sgpathp; 3457c478bd9Sstevel@tonic-gate *gpathp = 0; 3467c478bd9Sstevel@tonic-gate } else if (amatch(s, restbuf, &slproc)) 3477c478bd9Sstevel@tonic-gate return (1); 3487c478bd9Sstevel@tonic-gate sort(); 3497c478bd9Sstevel@tonic-gate pl = pm + 1; 3507c478bd9Sstevel@tonic-gate continue; 3517c478bd9Sstevel@tonic-gate 3527c478bd9Sstevel@tonic-gate case '[': 3537c478bd9Sstevel@tonic-gate for (pm++; *pm && *pm != ']'; pm++) 3547c478bd9Sstevel@tonic-gate continue; 3557c478bd9Sstevel@tonic-gate if (!*pm) 3567c478bd9Sstevel@tonic-gate error("Missing ]"); 3577c478bd9Sstevel@tonic-gate continue; 3587c478bd9Sstevel@tonic-gate } 3597c478bd9Sstevel@tonic-gate return (0); 3607c478bd9Sstevel@tonic-gate } 3617c478bd9Sstevel@tonic-gate 3626c02b4a4Smuffin int 3636c02b4a4Smuffin match(tchar *s, tchar *p, int *slproc) 3647c478bd9Sstevel@tonic-gate { 3656c02b4a4Smuffin int c; 3666c02b4a4Smuffin tchar *sentp; 3677c478bd9Sstevel@tonic-gate tchar sglobbed = globbed; 3687c478bd9Sstevel@tonic-gate 3697c478bd9Sstevel@tonic-gate #ifdef TRACE 3707c478bd9Sstevel@tonic-gate tprintf("TRACE- match()\n"); 3717c478bd9Sstevel@tonic-gate #endif 3727c478bd9Sstevel@tonic-gate if (*s == '.' && *p != '.') 3737c478bd9Sstevel@tonic-gate return (0); 3747c478bd9Sstevel@tonic-gate sentp = entp; 3757c478bd9Sstevel@tonic-gate entp = s; 3767c478bd9Sstevel@tonic-gate c = amatch(s, p, slproc); 3777c478bd9Sstevel@tonic-gate entp = sentp; 3787c478bd9Sstevel@tonic-gate globbed = sglobbed; 3797c478bd9Sstevel@tonic-gate return (c); 3807c478bd9Sstevel@tonic-gate } 3817c478bd9Sstevel@tonic-gate 3826c02b4a4Smuffin int 3836c02b4a4Smuffin amatch(tchar *s, tchar *p, int *slproc) 3847c478bd9Sstevel@tonic-gate { 3856c02b4a4Smuffin int scc; 3867c478bd9Sstevel@tonic-gate int ok, lc; 3877c478bd9Sstevel@tonic-gate tchar *sgpathp; 3887c478bd9Sstevel@tonic-gate struct stat stb; 3897c478bd9Sstevel@tonic-gate int c, cc; 3907c478bd9Sstevel@tonic-gate 3917c478bd9Sstevel@tonic-gate #ifdef TRACE 3927c478bd9Sstevel@tonic-gate tprintf("TRACE- amatch()\n"); 3937c478bd9Sstevel@tonic-gate #endif 3947c478bd9Sstevel@tonic-gate globbed = 1; 3957c478bd9Sstevel@tonic-gate for (;;) { 3967c478bd9Sstevel@tonic-gate scc = *s++ & TRIM; 3977c478bd9Sstevel@tonic-gate switch (c = *p++) { 3987c478bd9Sstevel@tonic-gate 3997c478bd9Sstevel@tonic-gate case '{': 4007c478bd9Sstevel@tonic-gate return (execbrc(p - 1, s - 1)); 4017c478bd9Sstevel@tonic-gate 4027c478bd9Sstevel@tonic-gate case '[': 4037c478bd9Sstevel@tonic-gate ok = 0; 4047c478bd9Sstevel@tonic-gate lc = TRIM; 4057c478bd9Sstevel@tonic-gate while (cc = *p++) { 4067c478bd9Sstevel@tonic-gate if (cc == ']') { 4077c478bd9Sstevel@tonic-gate if (ok) 4087c478bd9Sstevel@tonic-gate break; 4097c478bd9Sstevel@tonic-gate return (0); 4107c478bd9Sstevel@tonic-gate } 4117c478bd9Sstevel@tonic-gate if (cc == '-') { 4127c478bd9Sstevel@tonic-gate #ifdef MBCHAR 4137c478bd9Sstevel@tonic-gate wchar_t rc = *p++; 4147c478bd9Sstevel@tonic-gate if (rc == ']') { 4157c478bd9Sstevel@tonic-gate p--; 4167c478bd9Sstevel@tonic-gate continue; 4177c478bd9Sstevel@tonic-gate } 4187c478bd9Sstevel@tonic-gate /* 4197c478bd9Sstevel@tonic-gate * Both ends of the char range 4207c478bd9Sstevel@tonic-gate * must belong to the same codeset. 4217c478bd9Sstevel@tonic-gate */ 4227c478bd9Sstevel@tonic-gate if (sh_bracket_exp(scc, lc, rc)) 4237c478bd9Sstevel@tonic-gate ok++; 4247c478bd9Sstevel@tonic-gate #else /* !MBCHAR */ 4257c478bd9Sstevel@tonic-gate if (lc <= scc && scc <= (int)*p++) 4267c478bd9Sstevel@tonic-gate ok++; 4277c478bd9Sstevel@tonic-gate #endif /* !MBCHAR */ 4287c478bd9Sstevel@tonic-gate } else 4297c478bd9Sstevel@tonic-gate if (scc == (lc = cc)) 4307c478bd9Sstevel@tonic-gate ok++; 4317c478bd9Sstevel@tonic-gate } 4327c478bd9Sstevel@tonic-gate if (cc == 0) 4337c478bd9Sstevel@tonic-gate error("Missing ]"); 4347c478bd9Sstevel@tonic-gate continue; 4357c478bd9Sstevel@tonic-gate 4367c478bd9Sstevel@tonic-gate case '*': 4377c478bd9Sstevel@tonic-gate if (!*p) 4387c478bd9Sstevel@tonic-gate return (1); 4397c478bd9Sstevel@tonic-gate if (*p == '/') { 4407c478bd9Sstevel@tonic-gate p++; 4417c478bd9Sstevel@tonic-gate goto slash; 4427c478bd9Sstevel@tonic-gate } else if (*p == '*') { 4437c478bd9Sstevel@tonic-gate s--; 4447c478bd9Sstevel@tonic-gate continue; 4457c478bd9Sstevel@tonic-gate } 4467c478bd9Sstevel@tonic-gate 4477c478bd9Sstevel@tonic-gate for (s--; *s; s++) 4487c478bd9Sstevel@tonic-gate if (amatch(s, p, slproc)) 4497c478bd9Sstevel@tonic-gate return (1); 4507c478bd9Sstevel@tonic-gate 4517c478bd9Sstevel@tonic-gate return (0); 4527c478bd9Sstevel@tonic-gate 4537c478bd9Sstevel@tonic-gate case 0: 4547c478bd9Sstevel@tonic-gate return (scc == 0); 4557c478bd9Sstevel@tonic-gate 4567c478bd9Sstevel@tonic-gate default: 4577c478bd9Sstevel@tonic-gate if ((c & TRIM) != scc) 4587c478bd9Sstevel@tonic-gate return (0); 4597c478bd9Sstevel@tonic-gate continue; 4607c478bd9Sstevel@tonic-gate 4617c478bd9Sstevel@tonic-gate case '?': 4627c478bd9Sstevel@tonic-gate if (scc == 0) 4637c478bd9Sstevel@tonic-gate return (0); 4647c478bd9Sstevel@tonic-gate continue; 4657c478bd9Sstevel@tonic-gate 4667c478bd9Sstevel@tonic-gate case '/': 4677c478bd9Sstevel@tonic-gate if (scc) 4687c478bd9Sstevel@tonic-gate return (0); 4697c478bd9Sstevel@tonic-gate slash: 4707c478bd9Sstevel@tonic-gate if (*slproc) /* Need to expand "/" only once */ 4717c478bd9Sstevel@tonic-gate return (0); 4727c478bd9Sstevel@tonic-gate else 4737c478bd9Sstevel@tonic-gate *slproc = 1; 4747c478bd9Sstevel@tonic-gate 4757c478bd9Sstevel@tonic-gate s = entp; 4767c478bd9Sstevel@tonic-gate sgpathp = gpathp; 4777c478bd9Sstevel@tonic-gate while (*s) 4787c478bd9Sstevel@tonic-gate addpath(*s++); 4797c478bd9Sstevel@tonic-gate addpath('/'); 4807c478bd9Sstevel@tonic-gate if (stat_(gpath, &stb) == 0 && isdir(stb)) 4817c478bd9Sstevel@tonic-gate if (*p == 0) { 4827c478bd9Sstevel@tonic-gate Gcat(gpath, S_ /* "" */); 4837c478bd9Sstevel@tonic-gate globcnt++; 4847c478bd9Sstevel@tonic-gate } else 4857c478bd9Sstevel@tonic-gate expand(p); 4867c478bd9Sstevel@tonic-gate gpathp = sgpathp; 4877c478bd9Sstevel@tonic-gate *gpathp = 0; 4887c478bd9Sstevel@tonic-gate return (0); 4897c478bd9Sstevel@tonic-gate } 4907c478bd9Sstevel@tonic-gate } 4917c478bd9Sstevel@tonic-gate } 4927c478bd9Sstevel@tonic-gate 4936c02b4a4Smuffin int 4946c02b4a4Smuffin Gmatch(tchar *s, tchar *p) 4957c478bd9Sstevel@tonic-gate { 4966c02b4a4Smuffin int scc; 4977c478bd9Sstevel@tonic-gate int ok, lc; 4987c478bd9Sstevel@tonic-gate int c, cc; 4997c478bd9Sstevel@tonic-gate 5007c478bd9Sstevel@tonic-gate #ifdef TRACE 5017c478bd9Sstevel@tonic-gate tprintf("TRACE- Gmatch()\n"); 5027c478bd9Sstevel@tonic-gate #endif 5037c478bd9Sstevel@tonic-gate for (;;) { 5047c478bd9Sstevel@tonic-gate scc = *s++ & TRIM; 5057c478bd9Sstevel@tonic-gate switch (c = *p++) { 5067c478bd9Sstevel@tonic-gate 5077c478bd9Sstevel@tonic-gate case '[': 5087c478bd9Sstevel@tonic-gate ok = 0; 5097c478bd9Sstevel@tonic-gate lc = TRIM; 5107c478bd9Sstevel@tonic-gate while (cc = *p++) { 5117c478bd9Sstevel@tonic-gate if (cc == ']') { 5127c478bd9Sstevel@tonic-gate if (ok) 5137c478bd9Sstevel@tonic-gate break; 5147c478bd9Sstevel@tonic-gate return (0); 5157c478bd9Sstevel@tonic-gate } 5167c478bd9Sstevel@tonic-gate if (cc == '-') { 5177c478bd9Sstevel@tonic-gate #ifdef MBCHAR 5187c478bd9Sstevel@tonic-gate wchar_t rc = *p++; 5197c478bd9Sstevel@tonic-gate /* 5207c478bd9Sstevel@tonic-gate * Both ends of the char range 5217c478bd9Sstevel@tonic-gate * must belong to the same codeset... 5227c478bd9Sstevel@tonic-gate */ 5237c478bd9Sstevel@tonic-gate if (sh_bracket_exp(scc, lc, rc)) 5247c478bd9Sstevel@tonic-gate ok++; 5257c478bd9Sstevel@tonic-gate #else /* !MBCHAR */ 5267c478bd9Sstevel@tonic-gate if (lc <= scc && scc <= (int)*p++) 5277c478bd9Sstevel@tonic-gate ok++; 5287c478bd9Sstevel@tonic-gate #endif /* !MBCHAR */ 5297c478bd9Sstevel@tonic-gate } else 5307c478bd9Sstevel@tonic-gate if (scc == (lc = cc)) 5317c478bd9Sstevel@tonic-gate ok++; 5327c478bd9Sstevel@tonic-gate } 5337c478bd9Sstevel@tonic-gate if (cc == 0) 5347c478bd9Sstevel@tonic-gate bferr("Missing ]"); 5357c478bd9Sstevel@tonic-gate continue; 5367c478bd9Sstevel@tonic-gate 5377c478bd9Sstevel@tonic-gate case '*': 5387c478bd9Sstevel@tonic-gate if (!*p) 5397c478bd9Sstevel@tonic-gate return (1); 5407c478bd9Sstevel@tonic-gate for (s--; *s; s++) 5417c478bd9Sstevel@tonic-gate if (Gmatch(s, p)) 5427c478bd9Sstevel@tonic-gate return (1); 5437c478bd9Sstevel@tonic-gate return (0); 5447c478bd9Sstevel@tonic-gate 5457c478bd9Sstevel@tonic-gate case 0: 5467c478bd9Sstevel@tonic-gate return (scc == 0); 5477c478bd9Sstevel@tonic-gate 5487c478bd9Sstevel@tonic-gate default: 5497c478bd9Sstevel@tonic-gate if ((c & TRIM) != scc) 5507c478bd9Sstevel@tonic-gate return (0); 5517c478bd9Sstevel@tonic-gate continue; 5527c478bd9Sstevel@tonic-gate 5537c478bd9Sstevel@tonic-gate case '?': 5547c478bd9Sstevel@tonic-gate if (scc == 0) 5557c478bd9Sstevel@tonic-gate return (0); 5567c478bd9Sstevel@tonic-gate continue; 5577c478bd9Sstevel@tonic-gate 5587c478bd9Sstevel@tonic-gate } 5597c478bd9Sstevel@tonic-gate } 5607c478bd9Sstevel@tonic-gate } 5617c478bd9Sstevel@tonic-gate 5626c02b4a4Smuffin void 5636c02b4a4Smuffin Gcat(tchar *s1, tchar *s2) 5647c478bd9Sstevel@tonic-gate { 5656c02b4a4Smuffin tchar *p, *q; 5667c478bd9Sstevel@tonic-gate int n; 5677c478bd9Sstevel@tonic-gate 5687c478bd9Sstevel@tonic-gate #ifdef TRACE 5697c478bd9Sstevel@tonic-gate tprintf("TRACE- Gcat()\n"); 5707c478bd9Sstevel@tonic-gate #endif 5717c478bd9Sstevel@tonic-gate for (p = s1; *p++; ) 5727c478bd9Sstevel@tonic-gate ; 5737c478bd9Sstevel@tonic-gate for (q = s2; *q++; ) 5747c478bd9Sstevel@tonic-gate ; 5757c478bd9Sstevel@tonic-gate gnleft -= (n = (p - s1) + (q - s2) - 1); 5767c478bd9Sstevel@tonic-gate if (gnleft <= 0 || ++gargc >= GAVSIZ) 5777c478bd9Sstevel@tonic-gate error("Arguments too long"); 5787c478bd9Sstevel@tonic-gate gargv[gargc] = 0; 5797c478bd9Sstevel@tonic-gate p = gargv[gargc - 1] = (tchar *) xalloc((unsigned)n*sizeof (tchar)); 5807c478bd9Sstevel@tonic-gate 5817c478bd9Sstevel@tonic-gate for (q = s1; *p++ = *q++; ) 5827c478bd9Sstevel@tonic-gate ; 5837c478bd9Sstevel@tonic-gate for (p--, q = s2; *p++ = *q++; ) 5847c478bd9Sstevel@tonic-gate ; 5857c478bd9Sstevel@tonic-gate } 5867c478bd9Sstevel@tonic-gate 5876c02b4a4Smuffin void 5886c02b4a4Smuffin addpath(tchar c) 5897c478bd9Sstevel@tonic-gate { 5907c478bd9Sstevel@tonic-gate 5917c478bd9Sstevel@tonic-gate #ifdef TRACE 5927c478bd9Sstevel@tonic-gate tprintf("TRACE- addpath()\n"); 5937c478bd9Sstevel@tonic-gate #endif 5947c478bd9Sstevel@tonic-gate if (gpathp >= lastgpathp) 5957c478bd9Sstevel@tonic-gate error("Pathname too long"); 5967c478bd9Sstevel@tonic-gate *gpathp++ = c & TRIM; 5977c478bd9Sstevel@tonic-gate *gpathp = 0; 5987c478bd9Sstevel@tonic-gate } 5997c478bd9Sstevel@tonic-gate 6006c02b4a4Smuffin void 6016c02b4a4Smuffin rscan(tchar **t, int (*f)(int)) 6027c478bd9Sstevel@tonic-gate { 6036c02b4a4Smuffin tchar *p; 6047c478bd9Sstevel@tonic-gate 6057c478bd9Sstevel@tonic-gate #ifdef TRACE 6067c478bd9Sstevel@tonic-gate tprintf("TRACE- rscan()\n"); 6077c478bd9Sstevel@tonic-gate #endif 6087c478bd9Sstevel@tonic-gate while (p = *t++) 6097c478bd9Sstevel@tonic-gate while (*p) 6107c478bd9Sstevel@tonic-gate (*f)(*p++); 6117c478bd9Sstevel@tonic-gate } 6127c478bd9Sstevel@tonic-gate 6136c02b4a4Smuffin void 6146c02b4a4Smuffin trim(tchar **t) 6157c478bd9Sstevel@tonic-gate { 6166c02b4a4Smuffin tchar *p; 6177c478bd9Sstevel@tonic-gate 6187c478bd9Sstevel@tonic-gate #ifdef TRACE 6197c478bd9Sstevel@tonic-gate tprintf("TRACE- trim()\n"); 6207c478bd9Sstevel@tonic-gate #endif 6217c478bd9Sstevel@tonic-gate while (p = *t++) 6227c478bd9Sstevel@tonic-gate while (*p) 6237c478bd9Sstevel@tonic-gate *p++ &= TRIM; 6247c478bd9Sstevel@tonic-gate } 6257c478bd9Sstevel@tonic-gate 6266c02b4a4Smuffin void 6276c02b4a4Smuffin tglob(tchar **t) 6287c478bd9Sstevel@tonic-gate { 6296c02b4a4Smuffin tchar *p, c; 6307c478bd9Sstevel@tonic-gate 6317c478bd9Sstevel@tonic-gate #ifdef TRACE 6327c478bd9Sstevel@tonic-gate tprintf("TRACE- tglob()\n"); 6337c478bd9Sstevel@tonic-gate #endif 6347c478bd9Sstevel@tonic-gate while (p = *t++) { 6357c478bd9Sstevel@tonic-gate if (*p == '~') 6367c478bd9Sstevel@tonic-gate gflag |= 2; 6377c478bd9Sstevel@tonic-gate else if (*p == '{' && (p[1] == '\0' || 6387c478bd9Sstevel@tonic-gate p[1] == '}' && p[2] == '\0')) 6397c478bd9Sstevel@tonic-gate continue; 6407c478bd9Sstevel@tonic-gate while (c = *p++) 6417c478bd9Sstevel@tonic-gate if (isglob(c)) 6427c478bd9Sstevel@tonic-gate gflag |= c == '{' ? 2 : 1; 6437c478bd9Sstevel@tonic-gate } 6447c478bd9Sstevel@tonic-gate } 6457c478bd9Sstevel@tonic-gate 6467c478bd9Sstevel@tonic-gate tchar * 6476c02b4a4Smuffin globone(tchar *str) 6487c478bd9Sstevel@tonic-gate { 6497c478bd9Sstevel@tonic-gate tchar *gv[2]; 6506c02b4a4Smuffin tchar **gvp; 6516c02b4a4Smuffin tchar *cp; 6527c478bd9Sstevel@tonic-gate 6537c478bd9Sstevel@tonic-gate #ifdef TRACE 6547c478bd9Sstevel@tonic-gate tprintf("TRACE- globone()\n"); 6557c478bd9Sstevel@tonic-gate #endif 6567c478bd9Sstevel@tonic-gate gv[0] = str; 6577c478bd9Sstevel@tonic-gate gv[1] = 0; 6587c478bd9Sstevel@tonic-gate gflag = 0; 6597c478bd9Sstevel@tonic-gate tglob(gv); 6607c478bd9Sstevel@tonic-gate if (gflag) { 6617c478bd9Sstevel@tonic-gate gvp = glob(gv); 6627c478bd9Sstevel@tonic-gate if (gvp == 0) { 6637c478bd9Sstevel@tonic-gate setname(str); 6647c478bd9Sstevel@tonic-gate bferr("No match"); 6657c478bd9Sstevel@tonic-gate } 6667c478bd9Sstevel@tonic-gate cp = *gvp++; 6677c478bd9Sstevel@tonic-gate if (cp == 0) 6687c478bd9Sstevel@tonic-gate cp = S_ /* "" */; 6697c478bd9Sstevel@tonic-gate else if (*gvp) { 6707c478bd9Sstevel@tonic-gate setname(str); 6717c478bd9Sstevel@tonic-gate bferr("Ambiguous"); 6727c478bd9Sstevel@tonic-gate } else 6737c478bd9Sstevel@tonic-gate cp = strip(cp); 674*65b0c20eSnakanon #if 0 6757c478bd9Sstevel@tonic-gate if (cp == 0 || *gvp) { 6767c478bd9Sstevel@tonic-gate setname(str); 6777c478bd9Sstevel@tonic-gate bferr(cp ? "Ambiguous" : "No output"); 6787c478bd9Sstevel@tonic-gate } 679*65b0c20eSnakanon #endif 6807c478bd9Sstevel@tonic-gate xfree((char *)gargv); gargv = 0; 6817c478bd9Sstevel@tonic-gate } else { 6827c478bd9Sstevel@tonic-gate trim(gv); 6837c478bd9Sstevel@tonic-gate cp = savestr(gv[0]); 6847c478bd9Sstevel@tonic-gate } 6857c478bd9Sstevel@tonic-gate return (cp); 6867c478bd9Sstevel@tonic-gate } 6877c478bd9Sstevel@tonic-gate 6887c478bd9Sstevel@tonic-gate /* 6897c478bd9Sstevel@tonic-gate * Command substitute cp. If literal, then this is 6907c478bd9Sstevel@tonic-gate * a substitution from a << redirection, and so we should 6917c478bd9Sstevel@tonic-gate * not crunch blanks and tabs, separating words only at newlines. 6927c478bd9Sstevel@tonic-gate */ 6937c478bd9Sstevel@tonic-gate tchar ** 6946c02b4a4Smuffin dobackp(tchar *cp, bool literal) 6957c478bd9Sstevel@tonic-gate { 6966c02b4a4Smuffin tchar *lp, *rp; 6977c478bd9Sstevel@tonic-gate tchar *ep; 6987c478bd9Sstevel@tonic-gate tchar word[BUFSIZ]; 6997c478bd9Sstevel@tonic-gate tchar *apargv[GAVSIZ + 2]; 7007c478bd9Sstevel@tonic-gate 7017c478bd9Sstevel@tonic-gate #ifdef TRACE 7027c478bd9Sstevel@tonic-gate tprintf("TRACE- dobackp()\n"); 7037c478bd9Sstevel@tonic-gate #endif 7047c478bd9Sstevel@tonic-gate if (pargv) { 7057c478bd9Sstevel@tonic-gate blkfree(pargv); 7067c478bd9Sstevel@tonic-gate } 7077c478bd9Sstevel@tonic-gate pargv = apargv; 7087c478bd9Sstevel@tonic-gate pargv[0] = NOSTR; 7097c478bd9Sstevel@tonic-gate pargcp = pargs = word; 7107c478bd9Sstevel@tonic-gate pargc = 0; 7117c478bd9Sstevel@tonic-gate pnleft = BUFSIZ - 4; 7127c478bd9Sstevel@tonic-gate for (;;) { 7137c478bd9Sstevel@tonic-gate for (lp = cp; *lp != '`'; lp++) { 7147c478bd9Sstevel@tonic-gate if (*lp == 0) { 7157c478bd9Sstevel@tonic-gate if (pargcp != pargs) 7167c478bd9Sstevel@tonic-gate pword(); 7177c478bd9Sstevel@tonic-gate #ifdef GDEBUG 7187c478bd9Sstevel@tonic-gate printf("leaving dobackp\n"); 7197c478bd9Sstevel@tonic-gate #endif 7207c478bd9Sstevel@tonic-gate return (pargv = copyblk(pargv)); 7217c478bd9Sstevel@tonic-gate } 7227c478bd9Sstevel@tonic-gate psave(*lp); 7237c478bd9Sstevel@tonic-gate } 7247c478bd9Sstevel@tonic-gate lp++; 7257c478bd9Sstevel@tonic-gate for (rp = lp; *rp && *rp != '`'; rp++) 7267c478bd9Sstevel@tonic-gate if (*rp == '\\') { 7277c478bd9Sstevel@tonic-gate rp++; 7287c478bd9Sstevel@tonic-gate if (!*rp) 7297c478bd9Sstevel@tonic-gate goto oops; 7307c478bd9Sstevel@tonic-gate } 7317c478bd9Sstevel@tonic-gate if (!*rp) 7327c478bd9Sstevel@tonic-gate oops: 7337c478bd9Sstevel@tonic-gate error("Unmatched `"); 7347c478bd9Sstevel@tonic-gate ep = savestr(lp); 7357c478bd9Sstevel@tonic-gate ep[rp - lp] = 0; 7367c478bd9Sstevel@tonic-gate backeval(ep, literal); 7377c478bd9Sstevel@tonic-gate #ifdef GDEBUG 7387c478bd9Sstevel@tonic-gate printf("back from backeval\n"); 7397c478bd9Sstevel@tonic-gate #endif 7407c478bd9Sstevel@tonic-gate cp = rp + 1; 7417c478bd9Sstevel@tonic-gate } 7427c478bd9Sstevel@tonic-gate } 7437c478bd9Sstevel@tonic-gate 7446c02b4a4Smuffin void 7456c02b4a4Smuffin backeval(tchar *cp, bool literal) 7467c478bd9Sstevel@tonic-gate { 7477c478bd9Sstevel@tonic-gate int pvec[2]; 7487c478bd9Sstevel@tonic-gate int quoted = (literal || (cp[0] & QUOTE)) ? QUOTE : 0; 749*65b0c20eSnakanon tchar ibuf[BUFSIZ + MB_LEN_MAX]; /* read_ can return extra bytes */ 7506c02b4a4Smuffin int icnt = 0, c; 7516c02b4a4Smuffin tchar *ip; 7527c478bd9Sstevel@tonic-gate bool hadnl = 0; 7537c478bd9Sstevel@tonic-gate tchar *fakecom[2]; 7547c478bd9Sstevel@tonic-gate struct command faket; 7557c478bd9Sstevel@tonic-gate 7567c478bd9Sstevel@tonic-gate #ifdef TRACE 7577c478bd9Sstevel@tonic-gate tprintf("TRACE- backeval()\n"); 7587c478bd9Sstevel@tonic-gate #endif 7597c478bd9Sstevel@tonic-gate faket.t_dtyp = TCOM; 7607c478bd9Sstevel@tonic-gate faket.t_dflg = 0; 7617c478bd9Sstevel@tonic-gate faket.t_dlef = 0; 7627c478bd9Sstevel@tonic-gate faket.t_drit = 0; 7637c478bd9Sstevel@tonic-gate faket.t_dspr = 0; 7647c478bd9Sstevel@tonic-gate faket.t_dcom = fakecom; 7657c478bd9Sstevel@tonic-gate fakecom[0] = S_QPPPQ; /* "` ... `" */; 7667c478bd9Sstevel@tonic-gate fakecom[1] = 0; 7677c478bd9Sstevel@tonic-gate /* 7687c478bd9Sstevel@tonic-gate * We do the psave job to temporarily change the current job 7697c478bd9Sstevel@tonic-gate * so that the following fork is considered a separate job. 7707c478bd9Sstevel@tonic-gate * This is so that when backquotes are used in a 7717c478bd9Sstevel@tonic-gate * builtin function that calls glob the "current job" is not corrupted. 7727c478bd9Sstevel@tonic-gate * We only need one level of pushed jobs as long as we are sure to 7737c478bd9Sstevel@tonic-gate * fork here. 7747c478bd9Sstevel@tonic-gate */ 7757c478bd9Sstevel@tonic-gate psavejob(); 7767c478bd9Sstevel@tonic-gate /* 7777c478bd9Sstevel@tonic-gate * It would be nicer if we could integrate this redirection more 7787c478bd9Sstevel@tonic-gate * with the routines in sh.sem.c by doing a fake execute on a builtin 7797c478bd9Sstevel@tonic-gate * function that was piped out. 7807c478bd9Sstevel@tonic-gate */ 7817c478bd9Sstevel@tonic-gate mypipe(pvec); 7827c478bd9Sstevel@tonic-gate if (pfork(&faket, -1) == 0) { 7837c478bd9Sstevel@tonic-gate struct wordent paraml; 7847c478bd9Sstevel@tonic-gate struct command *t; 7857c478bd9Sstevel@tonic-gate tchar oHIST; 7867c478bd9Sstevel@tonic-gate 7877c478bd9Sstevel@tonic-gate new_process(); 7887c478bd9Sstevel@tonic-gate (void) close(pvec[0]); 7897c478bd9Sstevel@tonic-gate unsetfd(pvec[0]); 7907c478bd9Sstevel@tonic-gate (void) dmove(pvec[1], 1); 7917c478bd9Sstevel@tonic-gate (void) dmove(SHDIAG, 2); 7927c478bd9Sstevel@tonic-gate reinitdesc(0, NULL); 7937c478bd9Sstevel@tonic-gate arginp = cp; 7947c478bd9Sstevel@tonic-gate while (*cp) 7957c478bd9Sstevel@tonic-gate *cp++ &= TRIM; 7967c478bd9Sstevel@tonic-gate /* 7977c478bd9Sstevel@tonic-gate * disable history subsitution in sub-shell 7987c478bd9Sstevel@tonic-gate * of `` evaluation prevents possible 7997c478bd9Sstevel@tonic-gate * infinite recursion of `` evaluation 8007c478bd9Sstevel@tonic-gate */ 8017c478bd9Sstevel@tonic-gate oHIST = HIST; 8027c478bd9Sstevel@tonic-gate HIST = 0; 8037c478bd9Sstevel@tonic-gate (void) lex(¶ml); 8047c478bd9Sstevel@tonic-gate HIST = oHIST; 8057c478bd9Sstevel@tonic-gate if (err) 8067c478bd9Sstevel@tonic-gate error("%s", gettext(err)); 8077c478bd9Sstevel@tonic-gate alias(¶ml); 8087c478bd9Sstevel@tonic-gate t = syntax(paraml.next, ¶ml, 0); 8097c478bd9Sstevel@tonic-gate if (err) 8107c478bd9Sstevel@tonic-gate error("%s", gettext(err)); 8117c478bd9Sstevel@tonic-gate if (t) 8127c478bd9Sstevel@tonic-gate t->t_dflg |= FPAR; 8137c478bd9Sstevel@tonic-gate (void) signal(SIGTSTP, SIG_IGN); 8147c478bd9Sstevel@tonic-gate (void) signal(SIGTTIN, SIG_IGN); 8157c478bd9Sstevel@tonic-gate (void) signal(SIGTTOU, SIG_IGN); 8167c478bd9Sstevel@tonic-gate execute(t, -1); 8177c478bd9Sstevel@tonic-gate exitstat(); 8187c478bd9Sstevel@tonic-gate } 8197c478bd9Sstevel@tonic-gate xfree(cp); 8207c478bd9Sstevel@tonic-gate (void) close(pvec[1]); 8217c478bd9Sstevel@tonic-gate unsetfd(pvec[1]); 8227c478bd9Sstevel@tonic-gate do { 8237c478bd9Sstevel@tonic-gate int cnt = 0; 8247c478bd9Sstevel@tonic-gate for (;;) { 8257c478bd9Sstevel@tonic-gate if (icnt == 0) { 8267c478bd9Sstevel@tonic-gate ip = ibuf; 8277c478bd9Sstevel@tonic-gate icnt = read_(pvec[0], ip, BUFSIZ); 8287c478bd9Sstevel@tonic-gate if (icnt <= 0) { 8297c478bd9Sstevel@tonic-gate c = -1; 8307c478bd9Sstevel@tonic-gate break; 8317c478bd9Sstevel@tonic-gate } 8327c478bd9Sstevel@tonic-gate } 8337c478bd9Sstevel@tonic-gate if (hadnl) 8347c478bd9Sstevel@tonic-gate break; 8357c478bd9Sstevel@tonic-gate --icnt; 8367c478bd9Sstevel@tonic-gate c = (*ip++ & TRIM); 8377c478bd9Sstevel@tonic-gate if (c == 0) 8387c478bd9Sstevel@tonic-gate break; 8397c478bd9Sstevel@tonic-gate if (c == '\n') { 8407c478bd9Sstevel@tonic-gate /* 8417c478bd9Sstevel@tonic-gate * Continue around the loop one 8427c478bd9Sstevel@tonic-gate * more time, so that we can eat 8437c478bd9Sstevel@tonic-gate * the last newline without terminating 8447c478bd9Sstevel@tonic-gate * this word. 8457c478bd9Sstevel@tonic-gate */ 8467c478bd9Sstevel@tonic-gate hadnl = 1; 8477c478bd9Sstevel@tonic-gate continue; 8487c478bd9Sstevel@tonic-gate } 8497c478bd9Sstevel@tonic-gate if (!quoted && issp(c)) 8507c478bd9Sstevel@tonic-gate break; 8517c478bd9Sstevel@tonic-gate cnt++; 8527c478bd9Sstevel@tonic-gate psave(c | quoted); 8537c478bd9Sstevel@tonic-gate } 8547c478bd9Sstevel@tonic-gate /* 8557c478bd9Sstevel@tonic-gate * Unless at end-of-file, we will form a new word 8567c478bd9Sstevel@tonic-gate * here if there were characters in the word, or in 8577c478bd9Sstevel@tonic-gate * any case when we take text literally. If 8587c478bd9Sstevel@tonic-gate * we didn't make empty words here when literal was 8597c478bd9Sstevel@tonic-gate * set then we would lose blank lines. 8607c478bd9Sstevel@tonic-gate */ 8617c478bd9Sstevel@tonic-gate if (c != -1 && (cnt || literal)) { 8627c478bd9Sstevel@tonic-gate if (pargc == GAVSIZ) 8637c478bd9Sstevel@tonic-gate break; 8647c478bd9Sstevel@tonic-gate pword(); 8657c478bd9Sstevel@tonic-gate } 8667c478bd9Sstevel@tonic-gate hadnl = 0; 8677c478bd9Sstevel@tonic-gate } while (c >= 0); 8687c478bd9Sstevel@tonic-gate #ifdef GDEBUG 8697c478bd9Sstevel@tonic-gate printf("done in backeval, pvec: %d %d\n", pvec[0], pvec[1]); 8707c478bd9Sstevel@tonic-gate printf("also c = %c <%o>\n", (tchar) c, (tchar) c); 8717c478bd9Sstevel@tonic-gate #endif 8727c478bd9Sstevel@tonic-gate (void) close(pvec[0]); 8737c478bd9Sstevel@tonic-gate unsetfd(pvec[0]); 8747c478bd9Sstevel@tonic-gate pwait(); 8757c478bd9Sstevel@tonic-gate prestjob(); 8767c478bd9Sstevel@tonic-gate } 8777c478bd9Sstevel@tonic-gate 8786c02b4a4Smuffin void 8796c02b4a4Smuffin psave(tchar c) 8807c478bd9Sstevel@tonic-gate { 8817c478bd9Sstevel@tonic-gate #ifdef TRACE 8827c478bd9Sstevel@tonic-gate tprintf("TRACE- psave()\n"); 8837c478bd9Sstevel@tonic-gate #endif 8847c478bd9Sstevel@tonic-gate 8857c478bd9Sstevel@tonic-gate if (--pnleft <= 0) 8867c478bd9Sstevel@tonic-gate error("Word too long"); 8877c478bd9Sstevel@tonic-gate *pargcp++ = c; 8887c478bd9Sstevel@tonic-gate } 8897c478bd9Sstevel@tonic-gate 8906c02b4a4Smuffin void 8916c02b4a4Smuffin pword(void) 8927c478bd9Sstevel@tonic-gate { 8937c478bd9Sstevel@tonic-gate #ifdef TRACE 8947c478bd9Sstevel@tonic-gate tprintf("TRACE- pword()\n"); 8957c478bd9Sstevel@tonic-gate #endif 8967c478bd9Sstevel@tonic-gate 8977c478bd9Sstevel@tonic-gate psave(0); 8987c478bd9Sstevel@tonic-gate if (pargc == GAVSIZ) 8997c478bd9Sstevel@tonic-gate error("Too many words from ``"); 9007c478bd9Sstevel@tonic-gate pargv[pargc++] = savestr(pargs); 9017c478bd9Sstevel@tonic-gate pargv[pargc] = NOSTR; 9027c478bd9Sstevel@tonic-gate #ifdef GDEBUG 9037c478bd9Sstevel@tonic-gate printf("got word %t\n", pargv[pargc-1]); 9047c478bd9Sstevel@tonic-gate #endif 9057c478bd9Sstevel@tonic-gate pargcp = pargs; 9067c478bd9Sstevel@tonic-gate pnleft = BUFSIZ - 4; 9077c478bd9Sstevel@tonic-gate } 9087c478bd9Sstevel@tonic-gate 9097c478bd9Sstevel@tonic-gate 9107c478bd9Sstevel@tonic-gate 9117c478bd9Sstevel@tonic-gate /* 9127c478bd9Sstevel@tonic-gate * returns pathname of the form dir/file; 9137c478bd9Sstevel@tonic-gate * dir is a null-terminated string; 9147c478bd9Sstevel@tonic-gate */ 9157c478bd9Sstevel@tonic-gate char * 9166c02b4a4Smuffin makename(char *dir, char *file) 9177c478bd9Sstevel@tonic-gate { 9187c478bd9Sstevel@tonic-gate /* 9197c478bd9Sstevel@tonic-gate * Maximum length of a 9207c478bd9Sstevel@tonic-gate * file/dir name in ls-command; 9217c478bd9Sstevel@tonic-gate * dfile is static as this is returned 9227c478bd9Sstevel@tonic-gate * by makename(); 9237c478bd9Sstevel@tonic-gate */ 9247c478bd9Sstevel@tonic-gate static char dfile[MAXNAMLEN]; 9257c478bd9Sstevel@tonic-gate 9266c02b4a4Smuffin char *dp, *fp; 9277c478bd9Sstevel@tonic-gate 9287c478bd9Sstevel@tonic-gate dp = dfile; 9297c478bd9Sstevel@tonic-gate fp = dir; 9307c478bd9Sstevel@tonic-gate while (*fp) 9317c478bd9Sstevel@tonic-gate *dp++ = *fp++; 9327c478bd9Sstevel@tonic-gate if (dp > dfile && *(dp - 1) != '/') 9337c478bd9Sstevel@tonic-gate *dp++ = '/'; 9347c478bd9Sstevel@tonic-gate fp = file; 9357c478bd9Sstevel@tonic-gate while (*fp) 9367c478bd9Sstevel@tonic-gate *dp++ = *fp++; 9377c478bd9Sstevel@tonic-gate *dp = '\0'; 9387c478bd9Sstevel@tonic-gate /* 9397c478bd9Sstevel@tonic-gate * dfile points to the absolute pathname. We are 9407c478bd9Sstevel@tonic-gate * only interested in the last component. 9417c478bd9Sstevel@tonic-gate */ 9427c478bd9Sstevel@tonic-gate return (rindex(dfile, '/') + 1); 9437c478bd9Sstevel@tonic-gate } 9447c478bd9Sstevel@tonic-gate 9456c02b4a4Smuffin int 9466c02b4a4Smuffin sh_bracket_exp(tchar t_ch, tchar t_fch, tchar t_lch) 9477c478bd9Sstevel@tonic-gate { 9487c478bd9Sstevel@tonic-gate char t_char[MB_LEN_MAX + 1]; 9497c478bd9Sstevel@tonic-gate char t_patan[MB_LEN_MAX * 2 + 8]; 9507c478bd9Sstevel@tonic-gate char *p; 9517c478bd9Sstevel@tonic-gate int i; 9527c478bd9Sstevel@tonic-gate 9537c478bd9Sstevel@tonic-gate if ((t_ch == t_fch) || (t_ch == t_lch)) 9547c478bd9Sstevel@tonic-gate return (1); 9557c478bd9Sstevel@tonic-gate 9567c478bd9Sstevel@tonic-gate p = t_patan; 9577c478bd9Sstevel@tonic-gate if ((i = wctomb(t_char, (wchar_t)t_ch)) <= 0) 9587c478bd9Sstevel@tonic-gate return (0); 9597c478bd9Sstevel@tonic-gate t_char[i] = 0; 9607c478bd9Sstevel@tonic-gate 9617c478bd9Sstevel@tonic-gate *p++ = '['; 9627c478bd9Sstevel@tonic-gate if ((i = wctomb(p, (wchar_t)t_fch)) <= 0) 9637c478bd9Sstevel@tonic-gate return (0); 9647c478bd9Sstevel@tonic-gate p += i; 9657c478bd9Sstevel@tonic-gate *p++ = '-'; 9667c478bd9Sstevel@tonic-gate if ((i = wctomb(p, (wchar_t)t_lch)) <= 0) 9677c478bd9Sstevel@tonic-gate return (0); 9687c478bd9Sstevel@tonic-gate p += i; 9697c478bd9Sstevel@tonic-gate *p++ = ']'; 9707c478bd9Sstevel@tonic-gate *p = 0; 9717c478bd9Sstevel@tonic-gate 9727c478bd9Sstevel@tonic-gate if (fnmatch(t_patan, t_char, FNM_NOESCAPE)) 9737c478bd9Sstevel@tonic-gate return (0); 9747c478bd9Sstevel@tonic-gate return (1); 9757c478bd9Sstevel@tonic-gate } 976