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 **
glob(tchar ** v)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
ginit(tchar ** agargv)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
collect(tchar * as)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
acollect(tchar * as)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
sortscmp(tchar ** a1,tchar ** a2)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
expand(tchar * as)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
matchdir_(tchar * pattern)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
execbrc(tchar * p,tchar * s)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
match(tchar * s,tchar * p,int * slproc)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
amatch(tchar * s,tchar * p,int * slproc)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
Gmatch(tchar * s,tchar * p)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
Gcat(tchar * s1,tchar * s2)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
addpath(tchar c)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
rscan(tchar ** t,int (* f)(int))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
trim(tchar ** t)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
tglob(tchar ** t)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 *
globone(tchar * str)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 **
dobackp(tchar * cp,bool literal)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
backeval(tchar * cp,bool literal)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
psave(tchar c)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
pword(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 *
makename(char * dir,char * file)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
sh_bracket_exp(tchar t_ch,tchar t_fch,tchar t_lch)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