1 /* 2 * CDDL HEADER START 3 * 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 7 * with the License. 8 * 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. 13 * 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] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 1995 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 #pragma ident "%Z%%M% %I% %E% SMI" 31 /* 32 * UNIX shell 33 * 34 */ 35 36 #include "defs.h" 37 #include <sys/types.h> 38 #include <sys/stat.h> 39 #include <dirent.h> 40 41 42 43 /* 44 * globals (file name generation) 45 * 46 * "*" in params matches r.e ".*" 47 * "?" in params matches r.e. "." 48 * "[...]" in params matches character class 49 * "[...a-z...]" in params matches a through z. 50 * 51 */ 52 static int addg(); 53 54 expand(as, rcnt) 55 unsigned char *as; 56 { 57 int count; 58 DIR *dirf; 59 BOOL dir = 0; 60 unsigned char *rescan = 0; 61 unsigned char *slashsav = 0; 62 register unsigned char *s, *cs; 63 unsigned char *s2 = 0; 64 struct argnod *schain = gchain; 65 BOOL slash; 66 int len; 67 wchar_t wc; 68 69 if (trapnote & SIGSET) 70 return (0); 71 s = cs = as; 72 /* 73 * check for meta chars 74 */ 75 { 76 register BOOL open; 77 78 slash = 0; 79 open = 0; 80 do 81 { 82 if ((len = mbtowc(&wc, (char *)cs, MB_LEN_MAX)) <= 0) { 83 len = 1; 84 wc = (unsigned char)*cs; 85 } 86 87 cs += len; 88 switch (wc) { 89 case 0: 90 if (rcnt && slash) 91 break; 92 else 93 return (0); 94 95 case '/': 96 slash++; 97 open = 0; 98 continue; 99 100 case '[': 101 open++; 102 continue; 103 104 case ']': 105 if (open == 0) 106 continue; 107 108 case '?': 109 case '*': 110 if (rcnt > slash) 111 continue; 112 else 113 cs--; 114 break; 115 116 case '\\': 117 cs++; 118 default: 119 continue; 120 } 121 break; 122 } while (TRUE); 123 } 124 125 for (;;) 126 { 127 if (cs == s) 128 { 129 s = (unsigned char *)nullstr; 130 break; 131 } else if (*--cs == '/') 132 { 133 *cs = 0; 134 if (s == cs) 135 s = (unsigned char *)"/"; 136 else { 137 /* 138 * push trimmed copy of directory prefix 139 * onto stack 140 */ 141 s2 = cpystak(s); 142 trim(s2); 143 s = s2; 144 } 145 break; 146 } 147 } 148 149 if ((dirf = opendir(*s ? (char *)s : (char *)".")) != 0) 150 dir++; 151 152 /* Let s point to original string because it will be trimmed later */ 153 if (s2) 154 s = as; 155 count = 0; 156 if (*cs == 0) 157 slashsav = cs++; /* remember where first slash in as is */ 158 159 /* check for rescan */ 160 if (dir) 161 { 162 register unsigned char *rs; 163 struct dirent *e; 164 165 rs = cs; 166 do /* find next / in as */ 167 { 168 if (*rs == '/') 169 { 170 rescan = rs; 171 *rs = 0; 172 gchain = 0; 173 } 174 } while (*rs++); 175 176 while ((e = readdir(dirf)) && (trapnote & SIGSET) == 0) 177 { 178 if (e->d_name[0] == '.' && *cs != '.') 179 continue; 180 181 if (gmatch(e->d_name, cs)) 182 { 183 addg(s, e->d_name, rescan, slashsav); 184 count++; 185 } 186 } 187 (void) closedir(dirf); 188 189 if (rescan) 190 { 191 register struct argnod *rchain; 192 193 rchain = gchain; 194 gchain = schain; 195 if (count) 196 { 197 count = 0; 198 while (rchain) 199 { 200 count += expand(rchain->argval, 201 slash + 1); 202 rchain = rchain->argnxt; 203 } 204 } 205 *rescan = '/'; 206 } 207 } 208 209 if (slashsav) 210 *slashsav = '/'; 211 return (count); 212 } 213 214 static int 215 addg(as1, as2, as3, as4) 216 unsigned char *as1, *as2, *as3, *as4; 217 { 218 register unsigned char *s1, *s2; 219 register int c; 220 int len; 221 wchar_t wc; 222 223 s2 = locstak() + BYTESPERWORD; 224 s1 = as1; 225 if (as4) { 226 while (c = *s1++) 227 { 228 if (s2 >= brkend) 229 growstak(s2); 230 *s2++ = c; 231 } 232 /* 233 * Restore first slash before the first metacharacter 234 * if as1 is not "/" 235 */ 236 if (as4 + 1 == s1) { 237 if (s2 >= brkend) 238 growstak(s2); 239 *s2++ = '/'; 240 } 241 } 242 /* add matched entries, plus extra \\ to escape \\'s */ 243 s1 = as2; 244 for (;;) 245 { 246 if ((len = mbtowc(&wc, (char *)s1, MB_LEN_MAX)) <= 0) { 247 len = 1; 248 wc = (unsigned char)*s1; 249 } 250 if (s2 >= brkend) 251 growstak(s2); 252 253 if (wc == 0) { 254 *s2 = *s1++; 255 break; 256 } 257 258 if (wc == '\\') { 259 *s2++ = '\\'; 260 if (s2 >= brkend) 261 growstak(s2); 262 *s2++ = '\\'; 263 s1++; 264 continue; 265 } 266 if ((s2 + len) >= brkend) 267 growstak(s2 + len); 268 memcpy(s2, s1, len); 269 s2 += len; 270 s1 += len; 271 } 272 if (s1 = as3) 273 { 274 if (s2 >= brkend) 275 growstak(s2); 276 *s2++ = '/'; 277 do 278 { 279 if (s2 >= brkend) 280 growstak(s2); 281 } 282 while (*s2++ = *++s1); 283 } 284 makearg(endstak(s2)); 285 } 286 287 makearg(args) 288 register struct argnod *args; 289 { 290 args->argnxt = gchain; 291 gchain = args; 292 } 293