4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
31 * University Copyright- Copyright (c) 1982, 1986, 1988
32 * The Regents of the University of California
35 * University Acknowledgment- Portions of this document are derived from
36 * software developed by the University of California, Berkeley, and its
40 #pragma ident "%Z%%M% %I% %E% SMI"
43 * C-shell glob for random programs.
54 #define eq(a, b) (strcmp(a, b) == 0)
57 * According to the person who wrote the C shell "glob" code, a reasonable
58 * limit on number of arguments would seem to be the maximum number of
59 * characters in an arg list / 6.
61 * XXX: With the new VM system, NCARGS has become enormous, making
62 * it impractical to allocate arrays with NCARGS / 6 entries on
63 * the stack. The proper fix is to revamp code elsewhere (in
64 * sh.dol.c and sh.glob.c) to use a different technique for handling
65 * command line arguments. In the meantime, we simply fall back
66 * on using the old value of NCARGS.
69 #define GAVSIZ (NCARGS / 6)
71 #define GAVSIZ (10240 / 6)
74 static char **gargv
; /* Pointer to the (stack) arglist */
76 static int agargv_size
;
77 static long gargc
; /* Number args in gargv */
79 static char *strspl();
80 static char *strend(char *cp
);
81 static char *strspl(char *cp
, char *dp
);
82 static int tglob(char c
);
83 static char **copyblk(char **v
);
84 static void ginit(char **agargv
);
85 static void addpath(char c
);
86 static int any(int c
, char *s
);
87 static void Gcat(char *s1
, char *s2
);
88 static void collect(char *as
);
89 static void acollect(char *as
);
90 static void sort(void);
91 static void expand(char *as
);
92 static void matchdir(char *pattern
);
93 static int execbrc(char *p
, char *s
);
94 static int ftp_fnmatch(wchar_t t_ch
, wchar_t t_fch
, wchar_t t_lch
);
95 static int gethdir(char *home
);
96 static void xfree(char *cp
);
97 static void rscan(char **t
, int (*f
)(char));
98 static int letter(char c
);
99 static int digit(char c
);
100 static int match(char *s
, char *p
);
101 static int amatch(char *s
, char *p
);
102 static int blklen(char **av
);
103 static char **blkcpy(char **oav
, char **bv
);
107 static char *globchars
= "`{[*?";
109 static char *gpath
, *gpathp
, *lastgpathp
;
112 static char **sortbas
;
117 char agpath
[FTPBUFSIZ
];
120 if (agargv
== NULL
) {
121 agargv
= (char **)malloc(GAVSIZ
* sizeof (char *));
122 agargv_size
= GAVSIZ
;
123 if (agargv
== NULL
) {
124 globerr
= "Arguments too long.";
134 return (copyblk(vv
));
139 lastgpathp
= &gpath
[sizeof (agpath
) - 2];
143 if (globcnt
== 0 && (gflag
&1)) {
150 return (gargv
= copyblk(gargv
));
166 if (eq(as
, "{") || eq(as
, "{}")) {
176 register long ogargc
= gargc
;
178 gpathp
= gpath
; *gpathp
= 0; globbed
= 0;
187 register char **p1
, **p2
, *c
;
188 char **Gvp
= &gargv
[gargc
];
194 if (strcmp(*p1
, *p2
) > 0)
195 c
= *p1
, *p1
= *p2
, *p2
= c
;
205 register char *sgpathp
, *oldcs
;
210 if (*cs
== '~' && gpathp
== gpath
) {
213 while (letter(*cs
) || digit(*cs
) || *cs
== '-')
215 if (!*cs
|| *cs
== '/') {
216 if (gpathp
!= gpath
+ 1) {
218 if (gethdir(gpath
+ 1))
219 globerr
= "Unknown user name after ~";
220 (void) strcpy(gpath
, gpath
+ 1);
222 (void) strcpy(gpath
, home
);
223 gpathp
= strend(gpath
);
226 while (!any(*cs
, globchars
)) {
230 else if (stat(gpath
, &stb
) >= 0) {
239 while (cs
> as
&& *cs
!= '/')
245 (void) execbrc(cs
, ((char *)0));
255 matchdir(char *pattern
)
258 register struct dirent
*dp
;
262 * BSD/SunOS open() system call maps a null pathname into
263 * "." while System V does not.
265 if (*gpath
== '\0') {
268 dirp
= opendir(gpath
);
274 if (fstat(dirp
->dd_fd
, &stb
) < 0)
276 if (!S_ISDIR(stb
.st_mode
)) {
280 while ((dp
= readdir(dirp
)) != NULL
) {
283 if (match(dp
->d_name
, pattern
)) {
284 Gcat(gpath
, dp
->d_name
);
294 globerr
= "Bad directory components";
298 execbrc(char *p
, char *s
)
300 char restbuf
[FTPBUFSIZ
+ 2];
301 register char *pe
, *pm
, *pl
;
303 char *lm
, savec
, *sgpathp
;
306 for (lm
= restbuf
; *p
!= '{'; *lm
+= len
, p
+= len
) {
307 if ((len
= mblen(p
, MB_CUR_MAX
)) <= 0)
312 for (pe
= ++p
; *pe
; pe
+= len
) {
313 if ((len
= mblen(pe
, MB_CUR_MAX
)) <= 0)
329 for (pe
++; *pe
&& *pe
!= ']'; pe
+= len
) {
330 if ((len
= mblen(pe
, MB_CUR_MAX
)) <= 0)
339 for (pl
= pm
= p
; pm
<= pe
; pm
+= len
) {
340 if ((len
= mblen(pm
, MB_CUR_MAX
)) <= 0)
343 switch (*pm
& (QUOTE
|TRIM
)) {
363 (void) strcpy(lm
, pl
);
364 (void) strcat(restbuf
, pe
+ 1);
371 } else if (amatch(s
, restbuf
))
380 for (pm
++; *pm
&& *pm
!= ']'; pm
+= len
) {
381 if ((len
= mblen(pm
, MB_CUR_MAX
)) <= 0)
396 match(char *s
, char *p
)
399 register char *sentp
;
400 char sglobbed
= globbed
;
402 if (*s
== '.' && *p
!= '.')
413 amatch(char *s
, char *p
)
425 if ((len_s
= mbtowc(&scc
, s
, MB_CUR_MAX
)) <= 0) {
426 scc
= (unsigned char)*s
;
429 /* scc = *s++ & TRIM; */
432 if ((len_p
= mbtowc(&c
, p
, MB_CUR_MAX
)) <= 0) {
433 c
= (unsigned char)*p
;
440 return (execbrc(p
- len_p
, s
- len_s
));
445 while ((cc
= *p
) != '\0') {
446 if ((len_p
= mbtowc(&cc
, p
, MB_CUR_MAX
)) <= 0) {
447 cc
= (unsigned char)*p
;
457 if ((len_p
= mbtowc(&lc2
, p
,
459 lc2
= (unsigned char)*p
;
463 if (ftp_fnmatch(scc
, lc1
, lc2
))
466 if (scc
== (lc1
= cc
))
510 if (stat(gpath
, &stb
) == 0 && S_ISDIR(stb
.st_mode
))
526 register char *s
, *p
;
546 if (lc
<= scc
&& scc
<= *p
++)
549 if (scc
== (lc
= cc
))
571 if ((c
& TRIM
) != scc
)
586 Gcat(char *s1
, char *s2
)
588 if (gargc
>= agargv_size
- 1) {
594 tmp
= reallocarray(agargv
, agargv_size
+ GAVSIZ
,
597 globerr
= "Arguments too long";
601 agargv_size
+= GAVSIZ
;
608 gargv
[gargc
- 1] = strspl(s1
, s2
);
615 if (gpathp
>= lastgpathp
)
616 globerr
= "Pathname too long";
624 rscan(char **t
, int (*f
)(char))
633 else if (eq(p
, "{") || eq(p
, "{}"))
635 while ((c
= *p
) != '\0') {
637 if ((len
= mblen(p
, MB_CUR_MAX
)) <= 0)
647 if (any(c
, globchars
))
648 gflag
|= c
== '{' ? 2 : 1;
655 return (c
>= 'a' && c
<= 'z' || c
>= 'A' && c
<= 'Z' || c
== '_');
661 return (c
>= '0' && c
<= '9');
672 if ((len
= mblen(s
, MB_CUR_MAX
)) <= 0)
690 blkcpy(char **oav
, char **bv
)
692 register char **av
= oav
;
694 while (*av
++ = *bv
++)
702 register char **av
= av0
;
714 if (cp
>= end
&& cp
< (char *)&cp
)
719 strspl(char *cp
, char *dp
)
721 register char *ep
= malloc((unsigned)(strlen(cp
) + strlen(dp
) + 1));
724 fatal("Out of memory");
725 (void) strcpy(ep
, cp
);
726 (void) strcat(ep
, dp
);
733 register char **nv
= (char **)malloc((unsigned)((blklen(v
) + 1) *
736 if (nv
== (char **)0)
737 fatal("Out of memory");
739 return (blkcpy(nv
, v
));
751 * Extract a home directory from the password file
752 * The argument points to a buffer where the name of the
753 * user whose home directory is sought is currently.
754 * We write the home directory of the user back there.
759 register struct passwd
*pp
= getpwnam(home
);
761 if (!pp
|| home
+ strlen(pp
->pw_dir
) >= lastgpathp
)
763 (void) strcpy(home
, pp
->pw_dir
);
768 ftp_fnmatch(wchar_t t_ch
, wchar_t t_fch
, wchar_t t_lch
)
770 char t_char
[MB_LEN_MAX
+ 1];
771 char t_patan
[MB_LEN_MAX
* 2 + 8];
775 if ((t_ch
== t_fch
) || (t_ch
== t_lch
))
779 if ((i
= wctomb(t_char
, (wchar_t)t_ch
)) <= 0)
784 if ((i
= wctomb(p
, (wchar_t)t_fch
)) <= 0)
788 if ((i
= wctomb(p
, (wchar_t)t_lch
)) <= 0)
794 if (fnmatch(t_patan
, t_char
, FNM_NOESCAPE
))