Ultrix-3.1/src/cmd/sh5/expand.c
/**********************************************************************
* Copyright (c) Digital Equipment Corporation 1984, 1985, 1986. *
* All Rights Reserved. *
* Reference "/usr/src/COPYRIGHT" for applicable restrictions. *
**********************************************************************/
/*
* SCCSID: @(#)expand.c 3.0 4/22/86
* (System V) expand.c 1.4
*/
/*
* UNIX shell
*
* Bell Telephone Laboratories
*
*/
#include "defs.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/dir.h>
#define MAXDIR 64
struct direct *getdir();
static struct direct dirbuf[MAXDIR];
static int nxtdir = -1;
static int maxdir = 0;
static char entry[DIRSIZ+1];
/*
* 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.
*
*/
extern int addg();
expand(as, rcnt)
char *as;
{
int count, dirf;
BOOL dir = 0;
char *rescan = 0;
register char *s, *cs;
struct argnod *schain = gchain;
struct stat statb;
BOOL slash;
if (trapnote & SIGSET)
return(0);
s = cs = as;
/*
* check for meta chars
*/
{
register BOOL open;
slash = 0;
open = 0;
do
{
switch (*cs++)
{
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;
default:
continue;
}
break;
} while (TRUE);
}
for (;;)
{
if (cs == s)
{
s = nullstr;
break;
}
else if (*--cs == '/')
{
*cs = 0;
if (s == cs)
s = "/";
break;
}
}
if ((dirf = open(*s ? s : ".", 0)) > 0)
{
if (fstat(dirf, &statb) != -1 &&
(statb.st_mode & S_IFMT) == S_IFDIR)
dir++;
else
close(dirf);
}
count = 0;
if (*cs == 0)
*cs++ = 0200;
if (dir) /* check for rescan */
{
register char *rs;
struct direct *e;
rs = cs;
do
{
if (*rs == '/')
{
rescan = rs;
*rs = 0;
gchain = 0;
}
} while (*rs++);
while ((e = getdir(dirf)) && (trapnote & SIGSET) == 0)
{
*(movstrn(e->d_name, entry, DIRSIZ)) = 0;
if (entry[0] == '.' && *cs != '.')
#ifndef BOURNE
continue;
#else
{
if (entry[1] == 0)
continue;
if (entry[1] == '.' && entry[2] == 0)
continue;
}
#endif
if (gmatch(entry, cs))
{
addg(s, entry, rescan);
count++;
}
}
close(dirf);
if (rescan)
{
register struct argnod *rchain;
rchain = gchain;
gchain = schain;
if (count)
{
count = 0;
while (rchain)
{
count += expand(rchain->argval, slash + 1);
rchain = rchain->argnxt;
}
}
*rescan = '/';
}
}
{
register char c;
s = as;
while (c = *s)
*s++ = (c & STRIP ? c : '/');
}
return(count);
}
reset_dir()
{
nxtdir = -1;
maxdir = 0;
}
/*
* read next directory entry
* and ignore inode == 0
*
*/
struct direct *
getdir(dirf)
{
for (;;)
{
if (++nxtdir == maxdir)
{
int r;
r = read(dirf, dirbuf, sizeof(dirbuf)) / sizeof(struct direct);
if (maxdir = r)
nxtdir = 0;
else
{
nxtdir = -1;
return(0);
}
}
/* nxtdir is next available entry */
if (dirbuf[nxtdir].d_ino == 0)
continue;
return(&dirbuf[nxtdir]);
}
}
gmatch(s, p)
register char *s, *p;
{
register int scc;
char c;
if (scc = *s++)
{
if ((scc &= STRIP) == 0)
scc=0200;
}
switch (c = *p++)
{
case '[':
{
BOOL ok;
int lc;
int notflag = 0;
ok = 0;
lc = 077777;
if (*p == '!')
{
notflag = 1;
p++;
}
while (c = *p++)
{
if (c == ']')
return(ok ? gmatch(s, p) : 0);
else if (c == MINUS)
{
if (notflag)
{
if (scc < lc || scc > *(p++))
ok++;
else
return(0);
}
else
{
if (lc <= scc && scc <= (*p++))
ok++;
}
}
else
{
lc = c & STRIP;
if (notflag)
{
if (scc && scc != lc)
ok++;
else
return(0);
}
else
{
if (scc == lc)
ok++;
}
}
}
return(0);
}
default:
if ((c & STRIP) != scc)
return(0);
case '?':
return(scc ? gmatch(s, p) : 0);
case '*':
while (*p == '*')
p++;
if (*p == 0)
return(1);
--s;
while (*s)
{
if (gmatch(s++, p))
return(1);
}
return(0);
case 0:
return(scc == 0);
}
}
static int
addg(as1, as2, as3)
char *as1, *as2, *as3;
{
register char *s1, *s2;
register int c;
s2 = locstak() + BYTESPERWORD;
s1 = as1;
while (c = *s1++)
{
if ((c &= STRIP) == 0)
{
*s2++ = '/';
break;
}
*s2++ = c;
}
s1 = as2;
while (*s2 = *s1++)
s2++;
if (s1 = as3)
{
*s2++ = '/';
while (*s2++ = *++s1);
}
makearg(endstak(s2));
}
makearg(args)
register struct argnod *args;
{
args->argnxt = gchain;
gchain = args;
}