257 lines
3.6 KiB
C
257 lines
3.6 KiB
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);
|
|
}
|