version 1.1, 1995/10/18 08:45:59 |
version 1.2, 1996/02/03 12:12:23 |
|
|
/* |
/* |
* Copyright (c) 1983, 1993 |
* Copyright (c) 1983 Regents of the University of California. |
* The Regents of the University of California. All rights reserved. |
* All rights reserved. |
* |
* |
* Redistribution and use in source and binary forms, with or without |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* modification, are permitted provided that the following conditions |
|
|
*/ |
*/ |
|
|
#ifndef lint |
#ifndef lint |
/* from: static char sccsid[] = "@(#)expand.c 8.1 (Berkeley) 6/9/93"; */ |
static char RCSid[] = |
static char *rcsid = "$Id$"; |
"$Id$"; |
|
|
|
static char sccsid[] = "@(#)expand.c 5.2 (Berkeley) 3/28/86"; |
|
|
|
char copyright[] = |
|
"@(#) Copyright (c) 1983 Regents of the University of California.\n\ |
|
All rights reserved.\n"; |
#endif /* not lint */ |
#endif /* not lint */ |
|
|
#include "defs.h" |
#include "defs.h" |
|
|
#define GAVSIZ NCARGS / 6 |
#define MAXEARGS 2048 |
#define LC '{' |
#define LC '{' |
#define RC '}' |
#define RC '}' |
|
|
static char shchars[] = "${[*?"; |
static char shchars[] = "${[*?"; |
|
|
int which; /* bit mask of types to expand */ |
int which; /* bit mask of types to expand */ |
int eargc; /* expanded arg count */ |
int eargc; /* expanded arg count */ |
char **eargv; /* expanded arg vectors */ |
char **eargv; /* expanded arg vectors */ |
char *path; |
char *path; |
char *pathp; |
char *pathp; |
char *lastpathp; |
char *lastpathp; |
char *tilde; /* "~user" if not expanding tilde, else "" */ |
char *tilde; /* "~user" if not expanding tilde, else "" */ |
char *tpathp; |
char *tpathp; |
int nleft; |
|
|
|
int expany; /* any expansions done? */ |
int expany; /* any expansions done? */ |
char *entp; |
char *entp; |
char **sortbase; |
char **sortbase; |
|
char *argvbuf[MAXEARGS]; |
|
|
|
static int argcmp(); |
|
void expstr(); |
|
void expsh(); |
|
void matchdir(); |
|
|
#define sort() qsort((char *)sortbase, &eargv[eargc] - sortbase, \ |
#define sort() qsort((char *)sortbase, &eargv[eargc] - sortbase, \ |
sizeof(*sortbase), argcmp), sortbase = &eargv[eargc] |
sizeof(*sortbase), argcmp), sortbase = &eargv[eargc] |
|
|
static void Cat __P((char *, char *)); |
static void Cat(s1, s2) /* quote in s1 and s2 */ |
static void addpath __P((int)); |
register u_char *s1, *s2; |
static int amatch __P((char *, char *)); |
{ |
static int argcmp __P((const void *, const void *)); |
register char *cp; |
static int execbrc __P((char *, char *)); |
int len = strlen((char *)s1) + strlen((char *)s2) + 2; |
static void expsh __P((char *)); |
|
static void expstr __P((char *)); |
|
static int match __P((char *, char *)); |
|
static void matchdir __P((char *)); |
|
static int smatch __P((char *, char *)); |
|
|
|
|
if ((eargc + 1) >= MAXEARGS) { |
|
yyerror("Too many names"); |
|
return; |
|
} |
|
|
|
eargv[++eargc] = (char *) NULL; |
|
eargv[eargc - 1] = cp = xmalloc(len); |
|
|
|
do { |
|
if (*s1 == QUOTECHAR) |
|
s1++; |
|
} while (*cp++ = *s1++); |
|
cp--; |
|
do { |
|
if (*s2 == QUOTECHAR) |
|
s2++; |
|
} while (*cp++ = *s2++); |
|
} |
|
|
|
static void addpath(c) |
|
char c; |
|
{ |
|
if (pathp >= lastpathp) { |
|
yyerror("Pathname too long"); |
|
return; |
|
} else { |
|
*pathp++ = c; |
|
*pathp = CNULL; |
|
} |
|
} |
|
|
/* |
/* |
* Take a list of names and expand any macros, etc. |
* Take a list of names and expand any macros, etc. |
* wh = E_VARS if expanding variables. |
* wh = E_VARS if expanding variables. |
|
|
* Major portions of this were snarfed from csh/sh.glob.c. |
* Major portions of this were snarfed from csh/sh.glob.c. |
*/ |
*/ |
struct namelist * |
struct namelist * |
expand(list, wh) |
expand(list, wh) /* quote in list->n_name */ |
struct namelist *list; |
struct namelist *list; |
int wh; |
int wh; |
{ |
{ |
register struct namelist *nl, *prev; |
register struct namelist *nl, *prev; |
register int n; |
register int n; |
char pathbuf[BUFSIZ]; |
char pathbuf[BUFSIZ]; |
char *argvbuf[GAVSIZ]; |
|
|
|
if (debug) { |
if (debug) |
printf("expand(%x, %d)\nlist = ", list, wh); |
debugmsg(DM_CALL, "expand(%x, %d) start, list = %s", |
prnames(list); |
list, wh, getnlstr(list)); |
} |
|
|
|
if (wh == 0) { |
if (wh == 0) |
register char *cp; |
fatalerr("expand() contains invalid 'wh' argument."); |
|
|
for (nl = list; nl != NULL; nl = nl->n_next) |
|
for (cp = nl->n_name; *cp; cp++) |
|
*cp = *cp & TRIM; |
|
return(list); |
|
} |
|
|
|
which = wh; |
which = wh; |
path = tpathp = pathp = pathbuf; |
path = tpathp = pathp = pathbuf; |
*pathp = '\0'; |
*pathp = CNULL; |
lastpathp = &path[sizeof pathbuf - 2]; |
lastpathp = &path[sizeof pathbuf - 2]; |
tilde = ""; |
tilde = ""; |
eargc = 0; |
eargc = 0; |
eargv = sortbase = argvbuf; |
eargv = sortbase = argvbuf; |
*eargv = 0; |
*eargv = (char *) NULL; |
nleft = NCARGS - 4; |
|
/* |
/* |
* Walk the name list and expand names into eargv[]; |
* Walk the name list and expand names into eargv[]; |
*/ |
*/ |
for (nl = list; nl != NULL; nl = nl->n_next) |
for (nl = list; nl != NULL; nl = nl->n_next) |
expstr(nl->n_name); |
expstr((u_char *)nl->n_name); |
/* |
/* |
* Take expanded list of names from eargv[] and build a new list. |
* Take expanded list of names from eargv[] and build a new list. |
*/ |
*/ |
list = prev = NULL; |
list = prev = NULL; |
for (n = 0; n < eargc; n++) { |
for (n = 0; n < eargc; n++) { |
nl = makenl(NULL); |
nl = makenl((char *)NULL); |
nl->n_name = eargv[n]; |
nl->n_name = eargv[n]; |
if (prev == NULL) |
if (prev == NULL) |
list = prev = nl; |
list = prev = nl; |
|
|
prev = nl; |
prev = nl; |
} |
} |
} |
} |
if (debug) { |
|
printf("expanded list = "); |
|
prnames(list); |
|
} |
|
return(list); |
return(list); |
} |
} |
|
|
static void |
/* |
expstr(s) |
* xstrchr() is a version of strchr() that |
char *s; |
* handles u_char buffers. |
|
*/ |
|
u_char *xstrchr(str, ch) |
|
u_char *str; |
|
int ch; |
{ |
{ |
register char *cp, *cp1; |
register u_char *cp; |
|
|
|
for (cp = str; cp && *cp != CNULL; ++cp) |
|
if (ch == *cp) |
|
return(cp); |
|
|
|
return((u_char *)NULL); |
|
} |
|
|
|
void expstr(s) |
|
u_char *s; |
|
{ |
|
register u_char *cp, *cp1; |
register struct namelist *tp; |
register struct namelist *tp; |
char *tail; |
u_char *tail; |
char buf[BUFSIZ]; |
u_char ebuf[BUFSIZ]; |
|
u_char varbuff[BUFSIZ]; |
int savec, oeargc; |
int savec, oeargc; |
extern char homedir[]; |
extern char *homedir; |
|
|
if (s == NULL || *s == '\0') |
if (s == NULL || *s == CNULL) |
return; |
return; |
|
|
if ((which & E_VARS) && (cp = index(s, '$')) != NULL) { |
/* |
*cp++ = '\0'; |
* Remove quoted characters |
if (*cp == '\0') { |
*/ |
|
if (IS_ON(which, E_VARS)) { |
|
if ((int)strlen((char *)s) > sizeof(varbuff)) { |
|
yyerror("Variable is too large."); |
|
return; |
|
} |
|
for (cp = s, cp1 = varbuff; cp && *cp; ++cp) { |
|
/* |
|
* remove quoted character if the next |
|
* character is not $ |
|
*/ |
|
if (*cp == QUOTECHAR && *(cp+1) != '$') |
|
++cp; |
|
else |
|
*cp1++ = *cp; |
|
} |
|
*cp1 = CNULL; |
|
s = varbuff; |
|
} |
|
|
|
/* |
|
* Consider string 's' a variable that should be expanded if |
|
* there is a '$' in 's' that is not quoted. |
|
*/ |
|
if (IS_ON(which, E_VARS) && |
|
((cp = xstrchr(s, '$')) && !(cp > s && *(cp-1) == QUOTECHAR))) { |
|
*cp++ = CNULL; |
|
if (*cp == CNULL) { |
yyerror("no variable name after '$'"); |
yyerror("no variable name after '$'"); |
return; |
return; |
} |
} |
if (*cp == LC) { |
if (*cp == LC) { |
cp++; |
cp++; |
if ((tail = index(cp, RC)) == NULL) { |
for (cp1 = cp; ; cp1 = tail + 1) { |
yyerror("unmatched '{'"); |
if ((tail = xstrchr(cp1, RC)) == NULL) { |
return; |
yyerror("unmatched '{'"); |
|
return; |
|
} |
|
if (tail[-1] != QUOTECHAR) break; |
} |
} |
*tail++ = savec = '\0'; |
*tail++ = savec = CNULL; |
if (*cp == '\0') { |
if (*cp == CNULL) { |
yyerror("no variable name after '$'"); |
yyerror("no variable name after '$'"); |
return; |
return; |
} |
} |
} else { |
} else { |
tail = cp + 1; |
tail = cp + 1; |
savec = *tail; |
savec = *tail; |
*tail = '\0'; |
*tail = CNULL; |
} |
} |
tp = lookup(cp, NULL, 0); |
tp = lookup((char *)cp, LOOKUP, (struct namelist *)NULL); |
if (savec != '\0') |
if (savec != CNULL) |
*tail = savec; |
*tail = savec; |
if (tp != NULL) { |
if (tp != NULL) { |
for (; tp != NULL; tp = tp->n_next) { |
for (; tp != NULL; tp = tp->n_next) { |
sprintf(buf, "%s%s%s", s, tp->n_name, tail); |
(void) sprintf((char *)ebuf, |
expstr(buf); |
"%s%s%s", s, tp->n_name, tail); |
|
expstr(ebuf); |
} |
} |
return; |
return; |
} |
} |
sprintf(buf, "%s%s", s, tail); |
(void) sprintf((char *)ebuf, "%s%s", s, tail); |
expstr(buf); |
expstr(ebuf); |
return; |
return; |
} |
} |
if ((which & ~E_VARS) == 0 || !strcmp(s, "{") || !strcmp(s, "{}")) { |
if ((which & ~E_VARS) == 0 || !strcmp((char *)s, "{") || |
Cat(s, ""); |
!strcmp((char *)s, "{}")) { |
|
Cat(s, (u_char *)""); |
sort(); |
sort(); |
return; |
return; |
} |
} |
if (*s == '~') { |
if (*s == '~') { |
cp = ++s; |
cp = ++s; |
if (*cp == '\0' || *cp == '/') { |
if (*cp == CNULL || *cp == '/') { |
tilde = "~"; |
tilde = "~"; |
cp1 = homedir; |
cp1 = (u_char *)homedir; |
} else { |
} else { |
tilde = cp1 = buf; |
tilde = (char *)(cp1 = ebuf); |
*cp1++ = '~'; |
*cp1++ = '~'; |
do |
do |
*cp1++ = *cp++; |
*cp1++ = *cp++; |
while (*cp && *cp != '/'); |
while (*cp && *cp != '/'); |
*cp1 = '\0'; |
*cp1 = CNULL; |
if (pw == NULL || strcmp(pw->pw_name, buf+1) != 0) { |
if (pw == NULL || strcmp(pw->pw_name, |
if ((pw = getpwnam(buf+1)) == NULL) { |
(char *)ebuf+1) != 0) { |
strcat(buf, ": unknown user name"); |
if ((pw = getpwnam((char *)ebuf+1)) == NULL) { |
yyerror(buf+1); |
strcat((char *)ebuf, |
|
": unknown user name"); |
|
yyerror((char *)ebuf+1); |
return; |
return; |
} |
} |
} |
} |
cp1 = pw->pw_dir; |
cp1 = (u_char *)pw->pw_dir; |
s = cp; |
s = cp; |
} |
} |
for (cp = path; *cp++ = *cp1++; ) |
for (cp = (u_char *)path; *cp++ = *cp1++; ) |
; |
; |
tpathp = pathp = cp - 1; |
tpathp = pathp = (char *)cp - 1; |
} else { |
} else { |
tpathp = pathp = path; |
tpathp = pathp = path; |
tilde = ""; |
tilde = ""; |
} |
} |
*pathp = '\0'; |
*pathp = CNULL; |
if (!(which & E_SHELL)) { |
if (!(which & E_SHELL)) { |
if (which & E_TILDE) |
if (which & E_TILDE) |
Cat(path, s); |
Cat((u_char *)path, s); |
else |
else |
Cat(tilde, s); |
Cat((u_char *)tilde, s); |
sort(); |
sort(); |
return; |
return; |
} |
} |
|
|
expany = 0; |
expany = 0; |
expsh(s); |
expsh(s); |
if (eargc == oeargc) |
if (eargc == oeargc) |
Cat(s, ""); /* "nonomatch" is set */ |
Cat(s, (u_char *)""); /* "nonomatch" is set */ |
sort(); |
sort(); |
} |
} |
|
|
static int |
static |
argcmp(a1, a2) |
argcmp(a1, a2) |
const void *a1, *a2; |
char **a1, **a2; |
{ |
{ |
|
|
return (strcmp(*(char **)a1, *(char **)a2)); |
return (strcmp(*a1, *a2)); |
} |
} |
|
|
/* |
/* |
* If there are any Shell meta characters in the name, |
* If there are any Shell meta characters in the name, |
* expand into a list, after searching directory |
* expand into a list, after searching directory |
*/ |
*/ |
static void |
void expsh(s) /* quote in s */ |
expsh(s) |
u_char *s; |
char *s; |
|
{ |
{ |
register char *cp; |
register u_char *cp, *oldcp; |
register char *spathp, *oldcp; |
register char *spathp; |
struct stat stb; |
struct stat stb; |
|
|
spathp = pathp; |
spathp = pathp; |
cp = s; |
cp = s; |
while (!any(*cp, shchars)) { |
while (!any(*cp, shchars)) { |
if (*cp == '\0') { |
if (*cp == CNULL) { |
if (!expany || stat(path, &stb) >= 0) { |
if (!expany || stat(path, &stb) >= 0) { |
if (which & E_TILDE) |
if (which & E_TILDE) |
Cat(path, ""); |
Cat((u_char *)path, (u_char *)""); |
else |
else |
Cat(tilde, tpathp); |
Cat((u_char *)tilde, (u_char *)tpathp); |
} |
} |
goto endit; |
goto endit; |
} |
} |
|
if (*cp == QUOTECHAR) cp++; |
addpath(*cp++); |
addpath(*cp++); |
} |
} |
oldcp = cp; |
oldcp = cp; |
|
|
cp--, pathp--; |
cp--, pathp--; |
if (*cp == '/') |
if (*cp == '/') |
cp++, pathp++; |
cp++, pathp++; |
*pathp = '\0'; |
*pathp = CNULL; |
if (*oldcp == '{') { |
if (*oldcp == '{') { |
execbrc(cp, NULL); |
(void) execbrc(cp, (u_char *)NULL); |
return; |
return; |
} |
} |
matchdir(cp); |
matchdir((char *)cp); |
endit: |
endit: |
pathp = spathp; |
pathp = spathp; |
*pathp = '\0'; |
*pathp = CNULL; |
} |
} |
|
|
static void |
void matchdir(pattern) /* quote in pattern */ |
matchdir(pattern) |
|
char *pattern; |
char *pattern; |
{ |
{ |
struct stat stb; |
struct stat stb; |
register struct direct *dp; |
register DIRENTRY *dp; |
DIR *dirp; |
DIR *dirp; |
|
|
dirp = opendir(path); |
dirp = opendir(path); |
|
|
} |
} |
if (fstat(dirp->dd_fd, &stb) < 0) |
if (fstat(dirp->dd_fd, &stb) < 0) |
goto patherr1; |
goto patherr1; |
if (!ISDIR(stb.st_mode)) { |
if (!S_ISDIR(stb.st_mode)) { |
errno = ENOTDIR; |
errno = ENOTDIR; |
goto patherr1; |
goto patherr1; |
} |
} |
while ((dp = readdir(dirp)) != NULL) |
while ((dp = readdir(dirp)) != NULL) |
if (match(dp->d_name, pattern)) { |
if (match(dp->d_name, pattern)) { |
if (which & E_TILDE) |
if (which & E_TILDE) |
Cat(path, dp->d_name); |
Cat((u_char *)path, (u_char *)dp->d_name); |
else { |
else { |
strcpy(pathp, dp->d_name); |
(void) strcpy(pathp, dp->d_name); |
Cat(tilde, tpathp); |
Cat((u_char *)tilde, (u_char *)tpathp); |
*pathp = '\0'; |
*pathp = CNULL; |
} |
} |
} |
} |
closedir(dirp); |
closedir(dirp); |
|
|
patherr1: |
patherr1: |
closedir(dirp); |
closedir(dirp); |
patherr2: |
patherr2: |
strcat(path, ": "); |
(void) strcat(path, ": "); |
strcat(path, strerror(errno)); |
(void) strcat(path, SYSERR); |
yyerror(path); |
yyerror(path); |
} |
} |
|
|
static int |
execbrc(p, s) /* quote in p */ |
execbrc(p, s) |
u_char *p, *s; |
char *p, *s; |
|
{ |
{ |
char restbuf[BUFSIZ + 2]; |
u_char restbuf[BUFSIZ + 2]; |
register char *pe, *pm, *pl; |
register u_char *pe, *pm, *pl; |
int brclev = 0; |
int brclev = 0; |
char *lm, savec, *spathp; |
u_char *lm, savec; |
|
char *spathp; |
|
|
for (lm = restbuf; *p != '{'; *lm++ = *p++) |
for (lm = restbuf; *p != '{'; *lm++ = *p++) |
continue; |
if (*p == QUOTECHAR) *lm++ = *p++; |
|
|
for (pe = ++p; *pe; pe++) |
for (pe = ++p; *pe; pe++) |
switch (*pe) { |
switch (*pe) { |
|
|
|
|
|
|
case '[': |
case '[': |
for (pe++; *pe && *pe != ']'; pe++) |
for (pe++; *pe && *pe != ']'; pe++) |
continue; |
if (*p == QUOTECHAR) pe++; |
if (!*pe) |
if (!*pe) |
yyerror("Missing ']'"); |
yyerror("Missing ']'"); |
continue; |
continue; |
|
|
|
case QUOTECHAR: /* skip this character */ |
|
pe++; |
|
continue; |
} |
} |
pend: |
pend: |
if (brclev || !*pe) { |
if (brclev || !*pe) { |
|
|
return (0); |
return (0); |
} |
} |
for (pl = pm = p; pm <= pe; pm++) |
for (pl = pm = p; pm <= pe; pm++) |
switch (*pm & (QUOTE|TRIM)) { |
/* the strip code was a noop */ |
|
switch (*pm) { |
|
|
case '{': |
case '{': |
brclev++; |
brclev++; |
|
|
doit: |
doit: |
savec = *pm; |
savec = *pm; |
*pm = 0; |
*pm = 0; |
strcpy(lm, pl); |
(void) strcpy((char *)lm, (char *)pl); |
strcat(restbuf, pe + 1); |
(void) strcat((char *)restbuf, (char *)pe + 1); |
*pm = savec; |
*pm = savec; |
if (s == 0) { |
if (s == 0) { |
spathp = pathp; |
spathp = pathp; |
expsh(restbuf); |
expsh(restbuf); |
pathp = spathp; |
pathp = spathp; |
*pathp = 0; |
*pathp = 0; |
} else if (amatch(s, restbuf)) |
} else if (amatch((char *)s, restbuf)) |
return (1); |
return (1); |
sort(); |
sort(); |
pl = pm + 1; |
pl = pm + 1; |
|
|
|
|
case '[': |
case '[': |
for (pm++; *pm && *pm != ']'; pm++) |
for (pm++; *pm && *pm != ']'; pm++) |
continue; |
if (*pm == QUOTECHAR) pm++; |
if (!*pm) |
if (!*pm) |
yyerror("Missing ']'"); |
yyerror("Missing ']'"); |
continue; |
continue; |
|
|
|
case QUOTECHAR: /* skip one character */ |
|
pm++; |
|
continue; |
} |
} |
return (0); |
return (0); |
} |
} |
|
|
static int |
match(s, p) /* quote in p */ |
match(s, p) |
|
char *s, *p; |
char *s, *p; |
{ |
{ |
register int c; |
register int c; |
|
|
return (c); |
return (c); |
} |
} |
|
|
static int |
amatch(s, p) /* quote in p */ |
amatch(s, p) |
register char *s; |
register char *s, *p; |
register u_char *p; |
{ |
{ |
register int scc; |
register int scc; |
int ok, lc; |
int ok, lc; |
|
|
|
|
expany = 1; |
expany = 1; |
for (;;) { |
for (;;) { |
scc = *s++ & TRIM; |
scc = *s++; |
switch (c = *p++) { |
switch (c = *p++) { |
|
|
case '{': |
case '{': |
return (execbrc(p - 1, s - 1)); |
return (execbrc((u_char *)p - 1, (u_char *)s - 1)); |
|
|
case '[': |
case '[': |
ok = 0; |
ok = 0; |
|
|
break; |
break; |
return (0); |
return (0); |
} |
} |
|
if (cc == QUOTECHAR) cc = *p++; |
if (cc == '-') { |
if (cc == '-') { |
if (lc <= scc && scc <= *p++) |
if (lc <= scc && scc <= (int)*p++) |
ok++; |
ok++; |
} else |
} else |
if (scc == (lc = cc)) |
if (scc == (lc = cc)) |
|
|
return (1); |
return (1); |
return (0); |
return (0); |
|
|
case '\0': |
case CNULL: |
return (scc == '\0'); |
return (scc == CNULL); |
|
|
default: |
default: |
if ((c & TRIM) != scc) |
if (c != scc) |
return (0); |
return (0); |
continue; |
continue; |
|
|
case '?': |
case '?': |
if (scc == '\0') |
if (scc == CNULL) |
return (0); |
return (0); |
continue; |
continue; |
|
|
|
|
while (*s) |
while (*s) |
addpath(*s++); |
addpath(*s++); |
addpath('/'); |
addpath('/'); |
if (stat(path, &stb) == 0 && ISDIR(stb.st_mode)) |
if (stat(path, &stb) == 0 && S_ISDIR(stb.st_mode)) |
if (*p == '\0') { |
if (*p == CNULL) { |
if (which & E_TILDE) |
if (which & E_TILDE) |
Cat(path, ""); |
Cat((u_char *)path, |
|
(u_char *)""); |
else |
else |
Cat(tilde, tpathp); |
Cat((u_char *)tilde, |
|
(u_char *)tpathp); |
} else |
} else |
expsh(p); |
expsh(p); |
pathp = spathp; |
pathp = spathp; |
*pathp = '\0'; |
*pathp = CNULL; |
return (0); |
return (0); |
} |
} |
} |
} |
} |
|
|
|
static int |
|
smatch(s, p) |
|
register char *s, *p; |
|
{ |
|
register int scc; |
|
int ok, lc; |
|
int c, cc; |
|
|
|
for (;;) { |
|
scc = *s++ & TRIM; |
|
switch (c = *p++) { |
|
|
|
case '[': |
|
ok = 0; |
|
lc = 077777; |
|
while (cc = *p++) { |
|
if (cc == ']') { |
|
if (ok) |
|
break; |
|
return (0); |
|
} |
|
if (cc == '-') { |
|
if (lc <= scc && scc <= *p++) |
|
ok++; |
|
} else |
|
if (scc == (lc = cc)) |
|
ok++; |
|
} |
|
if (cc == 0) { |
|
yyerror("Missing ']'"); |
|
return (0); |
|
} |
|
continue; |
|
|
|
case '*': |
|
if (!*p) |
|
return (1); |
|
for (s--; *s; s++) |
|
if (smatch(s, p)) |
|
return (1); |
|
return (0); |
|
|
|
case '\0': |
|
return (scc == '\0'); |
|
|
|
default: |
|
if ((c & TRIM) != scc) |
|
return (0); |
|
continue; |
|
|
|
case '?': |
|
if (scc == 0) |
|
return (0); |
|
continue; |
|
|
|
} |
|
} |
|
} |
|
|
|
static void |
|
Cat(s1, s2) |
|
register char *s1, *s2; |
|
{ |
|
int len = strlen(s1) + strlen(s2) + 1; |
|
register char *s; |
|
|
|
nleft -= len; |
|
if (nleft <= 0 || ++eargc >= GAVSIZ) |
|
yyerror("Arguments too long"); |
|
eargv[eargc] = 0; |
|
eargv[eargc - 1] = s = malloc(len); |
|
if (s == NULL) |
|
fatal("ran out of memory\n"); |
|
while (*s++ = *s1++ & TRIM) |
|
; |
|
s--; |
|
while (*s++ = *s2++ & TRIM) |
|
; |
|
} |
|
|
|
static void |
|
addpath(c) |
|
int c; |
|
{ |
|
|
|
if (pathp >= lastpathp) |
|
yyerror("Pathname too long"); |
|
else { |
|
*pathp++ = c & TRIM; |
|
*pathp = '\0'; |
|
} |
|
} |
|
|
|
/* |
|
* Expand file names beginning with `~' into the |
|
* user's home directory path name. Return a pointer in buf to the |
|
* part corresponding to `file'. |
|
*/ |
|
char * |
|
exptilde(buf, file) |
|
char buf[]; |
|
register char *file; |
|
{ |
|
register char *s1, *s2, *s3; |
|
extern char homedir[]; |
|
|
|
if (*file != '~') { |
|
strcpy(buf, file); |
|
return(buf); |
|
} |
|
if (*++file == '\0') { |
|
s2 = homedir; |
|
s3 = NULL; |
|
} else if (*file == '/') { |
|
s2 = homedir; |
|
s3 = file; |
|
} else { |
|
s3 = file; |
|
while (*s3 && *s3 != '/') |
|
s3++; |
|
if (*s3 == '/') |
|
*s3 = '\0'; |
|
else |
|
s3 = NULL; |
|
if (pw == NULL || strcmp(pw->pw_name, file) != 0) { |
|
if ((pw = getpwnam(file)) == NULL) { |
|
error("%s: unknown user name\n", file); |
|
if (s3 != NULL) |
|
*s3 = '/'; |
|
return(NULL); |
|
} |
|
} |
|
if (s3 != NULL) |
|
*s3 = '/'; |
|
s2 = pw->pw_dir; |
|
} |
|
for (s1 = buf; *s1++ = *s2++; ) |
|
; |
|
s2 = --s1; |
|
if (s3 != NULL) { |
|
s2++; |
|
while (*s1++ = *s3++) |
|
; |
|
} |
|
return(s2); |
|
} |
} |