MiniUnix/usr/source/s1/glob.c
#
/* global command --
glob params
"*" in params matches r.e ".*"
"?" in params matches r.e. "."
"[...]" in params matches character class
"[...a-z...]" in params matches a through z.
perform command with argument list
constructed as follows:
if param does not contain "*", "[", or "?", use it as is
if it does, find all files in current directory
which match the param, sort them, and use them
prepend the command name with "/bin" or "/usr/bin"
as required.
*/
#define E2BIG 7
#define ENOEXEC 8
#define ENOENT 2
#define STRSIZ 522
char ab[STRSIZ]; /* generated characters */
char *ava[200]; /* generated arguments */
char **av &ava[1];
char *string ab;
int errno;
int ncoll;
main(argc, argv)
char *argv[];
{
register char *cp;
if (argc < 3) {
write(2, "Arg count\n", 10);
return;
}
argv++;
*av++ = *argv;
while (--argc >= 2)
expand(*++argv);
if (ncoll==0) {
write(2, "No match\n", 9);
return;
}
execute(ava[1], &ava[1]);
cp = cat("/usr/bin/", ava[1]);
execute(cp+4, &ava[1]);
execute(cp, &ava[1]);
write(2, "Command not found.\n", 19);
}
expand(as)
char *as;
{
register char *s, *cs;
register int dirf;
char **oav;
static struct {
int ino;
char name[16];
} entry;
s = cs = as;
while (*cs!='*' && *cs!='?' && *cs!='[') {
if (*cs++ == 0) {
*av++ = cat(s, "");
return;
}
}
for (;;) {
if (cs==s) {
dirf = open(".", 0);
s = "";
break;
}
if (*--cs == '/') {
*cs = 0;
dirf = open(s==cs? "/": s, 0);
*cs++ = 0200;
break;
}
}
if (dirf<0) {
write(2, "No directory\n", 13);
exit();
}
oav = av;
while (read(dirf, &entry, 16) == 16) {
if (entry.ino==0)
continue;
if (match(entry.name, cs)) {
*av++ = cat(s, entry.name);
ncoll++;
}
}
close(dirf);
sort(oav);
}
sort(oav)
char **oav;
{
register char **p1, **p2, **c;
p1 = oav;
while (p1 < av-1) {
p2 = p1;
while(++p2 < av) {
if (compar(*p1, *p2) > 0) {
c = *p1;
*p1 = *p2;
*p2 = c;
}
}
p1++;
}
}
execute(afile, aarg)
char *afile;
char **aarg;
{
register char *file, **arg;
arg = aarg;
file = afile;
execv(file, arg);
if (errno==ENOEXEC) {
arg[0] = file;
*--arg = "/bin/sh";
execv(*arg, arg);
}
if (errno==E2BIG)
toolong();
}
toolong()
{
write(2, "Arg list too long\n", 18);
exit();
}
match(s, p)
char *s, *p;
{
if (*s=='.' && *p!='.')
return(0);
return(amatch(s, p));
}
amatch(as, ap)
char *as, *ap;
{
register char *s, *p;
register scc;
int c, cc, ok, lc;
s = as;
p = ap;
if (scc = *s++)
if ((scc =& 0177) == 0)
scc = 0200;
switch (c = *p++) {
case '[':
ok = 0;
lc = 077777;
while (cc = *p++) {
if (cc==']') {
if (ok)
return(amatch(s, p));
else
return(0);
} else if (cc=='-') {
if (lc<=scc && scc<=(c = *p++))
ok++;
} else
if (scc == (lc=cc))
ok++;
}
return(0);
default:
if (c!=scc)
return(0);
case '?':
if (scc)
return(amatch(s, p));
return(0);
case '*':
return(umatch(--s, p));
case '\0':
return(!scc);
}
}
umatch(s, p)
char *s, *p;
{
if(*p==0)
return(1);
while(*s)
if (amatch(s++,p))
return(1);
return(0);
}
compar(as1, as2)
char *as1, *as2;
{
register char *s1, *s2;
s1 = as1;
s2 = as2;
while (*s1++ == *s2)
if (*s2++ == 0)
return(0);
return (*--s1 - *s2);
}
cat(as1, as2)
char *as1, *as2;
{
register char *s1, *s2;
register int c;
s2 = string;
s1 = as1;
while (c = *s1++) {
if (s2 > &ab[STRSIZ])
toolong();
c =& 0177;
if (c==0) {
*s2++ = '/';
break;
}
*s2++ = c;
}
s1 = as2;
do {
if (s2 > &ab[STRSIZ])
toolong();
*s2++ = c = *s1++;
} while (c);
s1 = string;
string = s2;
return(s1);
}