BSD 1 development
[unix-history] / ashell / sh_glob.c
#include "sh.h"
#define STRSIZ 522
#define PTHSIZ 100
static char ab[STRSIZ];
static char *ava[200];
static char **av;
static char *string;
static int ncoll;
static char gpath[100], *gpathp;
static int globbed;
static char *entp;
static int stbuff[18];
char **
glob(v)
register char *v[];
{
if (adrof("noglob"))
return (v);
ginit();
while (*v)
collect(*v++);
*av++ = 0;
return (ncoll == 0 ? 0 : &ava[2]);
}
ginit()
{
av = &ava[2];
string = ab;
ncoll = 0;
globbed = 0;
gpathp = gpath;
}
collect(as)
{
char **oav;
oav = av;
globbed = 0;
expand(as);
sort(oav);
}
sort(oav)
char **oav;
{
register char **p1, **p2, **c;
p1 = oav;
while (p1 < av-1) {
p2 = p1;
while(++p2 < av) {
if (strcmp(*p1, *p2) > 0) {
c = *p1;
*p1 = *p2;
*p2 = c;
}
}
p1++;
}
}
expand(as)
char *as;
{
register char *cs;
char *sgpathp;
register int dirf;
static struct {
int ino;
char name[16];
} entry;
sgpathp = gpathp;
cs = as;
while (*cs != '*' && *cs != '?' && *cs != '[') {
if (gpathp >= &gpath[PTHSIZ])
gpatherr();
else if ((*gpathp++ = *cs++) == 0) {
if (!globbed)
*av++ = cat(as, "");
else if (stat(gpath, &stbuff) >= 0) {
*av++ = cat(gpath, "");
ncoll++;
}
goto endit;
}
}
gpathp = sgpathp;
cs--;
while (cs >= as && *cs != '/')
cs--;
while (as <= cs)
if (gpathp >= &gpath[PTHSIZ])
gpatherr();
else
*gpathp++ = *as++;
*gpathp = 0;
dirf = open(gpath, 0);
if (dirf<0)
if (globbed)
goto endit;
else {
prs(gpath);
panic(": cannot open");
}
globbed++;
cs++;
while (read(dirf, &entry, 16) == 16) {
if (entry.ino==0)
continue;
if (match(entry.name, cs)) {
*av++ = cat(gpath, entry.name);
ncoll++;
}
}
close(dirf);
endit:
gpathp = sgpathp;
*gpathp = 0;
}
toolong()
{
panic("Arg list too long");
}
gpatherr()
{
prs("Path too long: ");
panic(gpath);
}
match(s, p)
char *s, *p;
{
register c, sentp;
if (*s == '.' && *p != '.')
return(0);
sentp = entp;
entp = s;
c = amatch(s, p);
entp = sentp;
return(c);
}
amatch(as, ap)
char *as, *ap;
{
register char *s, *p;
register scc;
int c, cc, ok, lc;
char *sgpathp;
s = as;
p = ap;
nextc:
if(scc = *s++ & 0177)
if ((scc =& 0177) == 0)
scc = 0200;
switch (c = *p++) {
case '[':
ok = 0;
lc = 077777;
while (cc = *p++) {
if (cc == ']') {
if (ok)
goto nextc;
else
return(0);
} else if (cc == '-') {
if (lc <= scc && scc <= *p++)
ok++;
} else
if (scc == (lc = cc))
ok++;
}
panic("missing ]");
case '*':
if(*p == '\0')
return(1);
else if (*p == '/') {
p++;
goto slash;
}
s--;
while(*s)
if (amatch(s, p))
return(1);
else
s++;
return(0);
case '\0':
return(scc == '\0');
default:
if (c == scc)
goto nextc;
else
return(0);
case '?':
if (scc != '\0')
goto nextc;
else
return(0);
case '/':
if (scc == '\0') {
slash:
s = entp;
sgpathp = gpathp;
while (*gpathp = *s++)
gpathp++;
*gpathp++ = '/';
*gpathp = 0;
if (stat(gpath, &stbuff) == 0)
if ((stbuff[2] & 060000) == 040000)
if (*p == 0) {
*av++ = cat(gpath, "");
ncoll++;
} else
expand(p);
gpathp = sgpathp;
*gpathp = 0;
}
return(0);
}
}
cat(as1, as2)
char *as1, *as2;
{
register char *s1, *s2;
s2 = string;
s1 = as1;
while (*s2++ = (*s1++ & 0177))
if (s2 >= &ab[STRSIZ])
toolong();
s1 = as2;
s2--;
while (*s2++ = *s1++)
if (s2 > &ab[STRSIZ])
toolong();
s1 = string;
string = s2;
return(s1);
}
panic(str)
{
err(str);
reset();
}