/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 1995 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ /* * UNIX shell * */ #include "defs.h" #include #include #include /* * globals (file name generation) * * "*" in params matches r.e ".*" * "?" in params matches r.e. "." * "[...]" in params matches character class * "[...a-z...]" in params matches a through z. * */ static void addg(unsigned char *, unsigned char *, unsigned char *, unsigned char *); void makearg(struct argnod *); int expand(unsigned char *as, int rcnt) { int count; DIR *dirf; BOOL dir = 0; unsigned char *rescan = 0; unsigned char *slashsav = 0; unsigned char *s, *cs; unsigned char *s2 = 0; struct argnod *schain = gchain; BOOL slash; int len; wchar_t wc; if (trapnote & SIGSET) return (0); s = cs = as; /* * check for meta chars */ { BOOL open; slash = 0; open = 0; do { if ((len = mbtowc(&wc, (char *)cs, MB_LEN_MAX)) <= 0) { len = 1; wc = (unsigned char)*cs; } cs += len; switch (wc) { case 0: if (rcnt && slash) break; else return (0); case '/': slash++; open = 0; continue; case '[': open++; continue; case ']': if (open == 0) continue; case '?': case '*': if (rcnt > slash) continue; else cs--; break; case '\\': cs++; default: continue; } break; } while (TRUE); } for (;;) { if (cs == s) { s = (unsigned char *)nullstr; break; } else if (*--cs == '/') { *cs = 0; if (s == cs) s = (unsigned char *)"/"; else { /* * push trimmed copy of directory prefix * onto stack */ s2 = cpystak(s); trim(s2); s = s2; } break; } } if ((dirf = opendir(*s ? (char *)s : (char *)".")) != 0) dir++; /* Let s point to original string because it will be trimmed later */ if (s2) s = as; count = 0; if (*cs == 0) slashsav = cs++; /* remember where first slash in as is */ /* check for rescan */ if (dir) { unsigned char *rs; struct dirent *e; rs = cs; do /* find next / in as */ { if (*rs == '/') { rescan = rs; *rs = 0; gchain = 0; } } while (*rs++); while ((e = readdir(dirf)) && (trapnote & SIGSET) == 0) { if (e->d_name[0] == '.' && *cs != '.') continue; if (gmatch(e->d_name, cs)) { addg(s, (unsigned char *)e->d_name, rescan, slashsav); count++; } } (void) closedir(dirf); if (rescan) { struct argnod *rchain; rchain = gchain; gchain = schain; if (count) { count = 0; while (rchain) { count += expand(rchain->argval, slash + 1); rchain = rchain->argnxt; } } *rescan = '/'; } } if (slashsav) *slashsav = '/'; return (count); } static void addg(unsigned char *as1, unsigned char *as2, unsigned char *as3, unsigned char *as4) { unsigned char *s1, *s2; int c; int len; wchar_t wc; s2 = locstak() + BYTESPERWORD; s1 = as1; if (as4) { while (c = *s1++) { if (s2 >= brkend) growstak(s2); *s2++ = c; } /* * Restore first slash before the first metacharacter * if as1 is not "/" */ if (as4 + 1 == s1) { if (s2 >= brkend) growstak(s2); *s2++ = '/'; } } /* add matched entries, plus extra \\ to escape \\'s */ s1 = as2; for (;;) { if ((len = mbtowc(&wc, (char *)s1, MB_LEN_MAX)) <= 0) { len = 1; wc = (unsigned char)*s1; } if (s2 >= brkend) growstak(s2); if (wc == 0) { *s2 = *s1++; break; } if (wc == '\\') { *s2++ = '\\'; if (s2 >= brkend) growstak(s2); *s2++ = '\\'; s1++; continue; } if ((s2 + len) >= brkend) growstak(s2 + len); memcpy(s2, s1, len); s2 += len; s1 += len; } if (s1 = as3) { if (s2 >= brkend) growstak(s2); *s2++ = '/'; do { if (s2 >= brkend) growstak(s2); } while (*s2++ = *++s1); } makearg((struct argnod *)endstak(s2)); } void makearg(struct argnod *args) { args->argnxt = gchain; gchain = args; }