2 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
6 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
7 /* All Rights Reserved */
10 * Copyright (c) 1980 Regents of the University of California.
11 * All rights reserved. The Berkeley Software License Agreement
12 * specifies the terms and conditions for redistribution.
16 #include "sh.tconst.h"
20 #include <widec.h> /* wcsetno() */
21 #include <fnmatch.h> /* fnmatch() */
30 tchar
*gpath
, *gpathp
, *lastgpathp
;
36 int sortscmp(tchar
**, tchar
**);
38 void collect(tchar
*);
39 void acollect(tchar
*);
41 void matchdir_(tchar
*);
42 void Gcat(tchar
*, tchar
*);
45 tchar
**dobackp(tchar
*, bool);
46 void backeval(tchar
*, bool);
50 extern DIR *opendir_(tchar
*);
52 #define sort() qsort((char *)sortbas, &gargv[gargc] - sortbas, \
53 sizeof (*sortbas), (int (*)(const void *, \
54 const void *)) sortscmp), sortbas = &gargv[gargc]
61 tchar
*agargv
[GAVSIZ
];
63 gpath
= agpath
; gpathp
= gpath
; *gpathp
= 0;
64 lastgpathp
= &gpath
[BUFSIZ
- 2];
65 ginit(agargv
); globcnt
= 0;
67 tprintf("TRACE- glob()\n");
70 printf("glob entered: "); blkpr(v
); printf("\n");
72 noglob
= adrof(S_noglob
/* "noglob" */) != 0;
73 nonomatch
= adrof(S_nonomatch
/* "nonomatch" */) != 0;
74 globcnt
= noglob
| nonomatch
;
78 printf("glob done, globcnt=%d, gflag=%d: ", globcnt
, gflag
);
79 blkpr(gargv
); printf("\n");
81 if (globcnt
== 0 && (gflag
&1)) {
82 blkfree(gargv
), gargv
= 0;
85 return (gargv
= copyblk(gargv
));
92 agargv
[0] = 0; gargv
= agargv
; sortbas
= agargv
; gargc
= 0;
102 tprintf("TRACE- collect()\n");
106 printf("doing backp of %t\n", as
);
108 (void) dobackp(as
, 0);
110 printf("backp done, acollect'ing\n");
113 * dobackp has the side effect of messing with
114 * gflag, since it does more globbing, so check
115 * if the results is still globbable
119 for (i
= 0; i
< pargc
; i
++)
121 Gcat(pargv
[i
], S_
/* "" */);
122 sortbas
= &gargv
[gargc
];
126 blkfree(pargv
), pargv
= 0;
128 printf("acollect done\n");
130 } else if (noglob
|| eq(as
, S_LBRA
/* "{" */) ||
131 eq(as
, S_BRABRA
/* "{}" */)) {
132 Gcat(as
, S_
/* "" */);
144 tprintf("TRACE- acollect()\n");
146 gpathp
= gpath
; *gpathp
= 0; globbed
= 0;
148 if (gargc
== ogargc
) {
150 Gcat(as
, S_
/* "" */);
158 * String compare for qsort. Also used by filec code in sh.file.c.
161 sortscmp(tchar
**a1
, tchar
**a2
)
164 return (strcoll_(*a1
, *a2
));
171 tchar
*sgpathp
, *oldcs
;
175 tprintf("TRACE- expand()\n");
179 if (*cs
== '~' && gpathp
== gpath
) {
181 for (cs
++; alnum(*cs
) || *cs
== '-'; )
183 if (!*cs
|| *cs
== '/') {
184 if (gpathp
!= gpath
+ 1) {
186 if (gethdir(gpath
+ 1))
188 * modified from %s to %t
190 error("Unknown user: %t", gpath
+ 1);
191 (void) strcpy_(gpath
, gpath
+ 1);
193 (void) strcpy_(gpath
,
194 value(S_home
/* "home" */));
195 gpathp
= strend(gpath
);
198 while (!isglob(*cs
)) {
201 Gcat(gpath
, S_
/* "" */);
202 else if (lstat_(gpath
, &stb
) >= 0) {
203 Gcat(gpath
, S_
/* "" */);
211 while (cs
> as
&& *cs
!= '/')
217 (void) execbrc(cs
, NOSTR
);
227 matchdir_(tchar
*pattern
)
232 tchar curdir_
[MAXNAMLEN
+1];
236 tprintf("TRACE- matchdir()\n");
239 * BSD's opendir would open "." if argument is NULL, but not S5
243 dirp
= opendir_(S_DOT
/* "." */);
245 dirp
= opendir_(gpath
);
251 if (fstat(dirp
->dd_fd
, &stb
) < 0)
257 while ((dp
= readdir(dirp
)) != NULL
) {
261 strtots(curdir_
, dp
->d_name
);
263 if (match(curdir_
, pattern
, &slproc
)) {
264 Gcat(gpath
, curdir_
);
268 unsetfd(dirp
->dd_fd
);
273 unsetfd(dirp
->dd_fd
);
280 execbrc(tchar
*p
, tchar
*s
)
282 tchar restbuf
[BUFSIZ
+ 2];
285 tchar
*lm
, savec
, *sgpathp
;
289 tprintf("TRACE- execbrc()\n");
291 for (lm
= restbuf
; *p
!= '{'; *lm
++ = *p
++)
293 for (pe
= ++p
; *pe
; pe
++)
307 for (pe
++; *pe
&& *pe
!= ']'; pe
++)
316 for (pl
= pm
= p
; pm
<= pe
; pm
++)
317 switch (*pm
& (QUOTE
|TRIM
)) {
336 (void) strcpy_(lm
, pl
);
337 (void) strcat_(restbuf
, pe
+ 1);
344 } else if (amatch(s
, restbuf
, &slproc
))
351 for (pm
++; *pm
&& *pm
!= ']'; pm
++)
361 match(tchar
*s
, tchar
*p
, int *slproc
)
365 tchar sglobbed
= globbed
;
368 tprintf("TRACE- match()\n");
370 if (*s
== '.' && *p
!= '.')
374 c
= amatch(s
, p
, slproc
);
381 amatch(tchar
*s
, tchar
*p
, int *slproc
)
390 tprintf("TRACE- amatch()\n");
398 return (execbrc(p
- 1, s
- 1));
417 * Both ends of the char range
418 * must belong to the same codeset.
420 if (sh_bracket_exp(scc
, lc
, rc
))
423 if (lc
<= scc
&& scc
<= (int)*p
++)
427 if (scc
== (lc
= cc
))
440 } else if (*p
== '*') {
446 if (amatch(s
, p
, slproc
))
455 if ((c
& TRIM
) != scc
)
468 if (*slproc
) /* Need to expand "/" only once */
478 if (stat_(gpath
, &stb
) == 0 && isdir(stb
))
480 Gcat(gpath
, S_
/* "" */);
492 Gmatch(tchar
*s
, tchar
*p
)
499 tprintf("TRACE- Gmatch()\n");
518 * Both ends of the char range
519 * must belong to the same codeset...
521 if (sh_bracket_exp(scc
, lc
, rc
))
524 if (lc
<= scc
&& scc
<= (int)*p
++)
528 if (scc
== (lc
= cc
))
547 if ((c
& TRIM
) != scc
)
561 Gcat(tchar
*s1
, tchar
*s2
)
567 tprintf("TRACE- Gcat()\n");
573 gnleft
-= (n
= (p
- s1
) + (q
- s2
) - 1);
574 if (gnleft
<= 0 || ++gargc
>= GAVSIZ
)
575 error("Arguments too long");
577 p
= gargv
[gargc
- 1] = (tchar
*) xalloc((unsigned)n
*sizeof (tchar
));
579 for (q
= s1
; *p
++ = *q
++; )
581 for (p
--, q
= s2
; *p
++ = *q
++; )
590 tprintf("TRACE- addpath()\n");
592 if (gpathp
>= lastgpathp
)
593 error("Pathname too long");
594 *gpathp
++ = c
& TRIM
;
599 rscan(tchar
**t
, int (*f
)(int))
604 tprintf("TRACE- rscan()\n");
617 tprintf("TRACE- trim()\n");
630 tprintf("TRACE- tglob()\n");
635 else if (*p
== '{' && (p
[1] == '\0' ||
636 p
[1] == '}' && p
[2] == '\0'))
640 gflag
|= c
== '{' ? 2 : 1;
652 tprintf("TRACE- globone()\n");
673 if (cp
== 0 || *gvp
) {
675 bferr(cp
? "Ambiguous" : "No output");
678 xfree((char *)gargv
); gargv
= 0;
687 * Command substitute cp. If literal, then this is
688 * a substitution from a << redirection, and so we should
689 * not crunch blanks and tabs, separating words only at newlines.
692 dobackp(tchar
*cp
, bool literal
)
697 tchar
*apargv
[GAVSIZ
+ 2];
700 tprintf("TRACE- dobackp()\n");
707 pargcp
= pargs
= word
;
711 for (lp
= cp
; *lp
!= '`'; lp
++) {
716 printf("leaving dobackp\n");
718 return (pargv
= copyblk(pargv
));
723 for (rp
= lp
; *rp
&& *rp
!= '`'; rp
++)
731 error("Unmatched `");
734 backeval(ep
, literal
);
736 printf("back from backeval\n");
743 backeval(tchar
*cp
, bool literal
)
746 int quoted
= (literal
|| (cp
[0] & QUOTE
)) ? QUOTE
: 0;
747 tchar ibuf
[BUFSIZ
+ MB_LEN_MAX
]; /* read_ can return extra bytes */
752 struct command faket
;
755 tprintf("TRACE- backeval()\n");
762 faket
.t_dcom
= fakecom
;
763 fakecom
[0] = S_QPPPQ
; /* "` ... `" */;
766 * We do the psave job to temporarily change the current job
767 * so that the following fork is considered a separate job.
768 * This is so that when backquotes are used in a
769 * builtin function that calls glob the "current job" is not corrupted.
770 * We only need one level of pushed jobs as long as we are sure to
775 * It would be nicer if we could integrate this redirection more
776 * with the routines in sh.sem.c by doing a fake execute on a builtin
777 * function that was piped out.
780 if (pfork(&faket
, -1) == 0) {
781 struct wordent paraml
;
786 (void) close(pvec
[0]);
788 (void) dmove(pvec
[1], 1);
789 (void) dmove(SHDIAG
, 2);
795 * disable history subsitution in sub-shell
796 * of `` evaluation prevents possible
797 * infinite recursion of `` evaluation
804 error("%s", gettext(err
));
806 t
= syntax(paraml
.next
, ¶ml
, 0);
808 error("%s", gettext(err
));
811 (void) signal(SIGTSTP
, SIG_IGN
);
812 (void) signal(SIGTTIN
, SIG_IGN
);
813 (void) signal(SIGTTOU
, SIG_IGN
);
818 (void) close(pvec
[1]);
825 icnt
= read_(pvec
[0], ip
, BUFSIZ
);
839 * Continue around the loop one
840 * more time, so that we can eat
841 * the last newline without terminating
847 if (!quoted
&& issp(c
))
853 * Unless at end-of-file, we will form a new word
854 * here if there were characters in the word, or in
855 * any case when we take text literally. If
856 * we didn't make empty words here when literal was
857 * set then we would lose blank lines.
859 if (c
!= -1 && (cnt
|| literal
)) {
867 printf("done in backeval, pvec: %d %d\n", pvec
[0], pvec
[1]);
868 printf("also c = %c <%o>\n", (tchar
) c
, (tchar
) c
);
870 (void) close(pvec
[0]);
880 tprintf("TRACE- psave()\n");
884 error("Word too long");
892 tprintf("TRACE- pword()\n");
897 error("Too many words from ``");
898 pargv
[pargc
++] = savestr(pargs
);
899 pargv
[pargc
] = NOSTR
;
901 printf("got word %t\n", pargv
[pargc
-1]);
910 * returns pathname of the form dir/file;
911 * dir is a null-terminated string;
914 makename(char *dir
, char *file
)
917 * Maximum length of a
918 * file/dir name in ls-command;
919 * dfile is static as this is returned
922 static char dfile
[MAXNAMLEN
];
930 if (dp
> dfile
&& *(dp
- 1) != '/')
937 * dfile points to the absolute pathname. We are
938 * only interested in the last component.
940 return (rindex(dfile
, '/') + 1);
944 sh_bracket_exp(tchar t_ch
, tchar t_fch
, tchar t_lch
)
946 char t_char
[MB_LEN_MAX
+ 1];
947 char t_patan
[MB_LEN_MAX
* 2 + 8];
951 if ((t_ch
== t_fch
) || (t_ch
== t_lch
))
955 if ((i
= wctomb(t_char
, (wchar_t)t_ch
)) <= 0)
960 if ((i
= wctomb(p
, (wchar_t)t_fch
)) <= 0)
964 if ((i
= wctomb(p
, (wchar_t)t_lch
)) <= 0)
970 if (fnmatch(t_patan
, t_char
, FNM_NOESCAPE
))