version 1.13, 2001/01/16 05:36:08 |
version 1.14, 2001/11/21 15:26:39 |
|
|
|
|
#ifndef lint |
#ifndef lint |
#if 0 |
#if 0 |
static char sccsid[] = "@(#)names.c 8.1 (Berkeley) 6/6/93"; |
static const char sccsid[] = "@(#)names.c 8.1 (Berkeley) 6/6/93"; |
#else |
#else |
static char rcsid[] = "$OpenBSD$"; |
static const char rcsid[] = "$OpenBSD$"; |
#endif |
#endif |
#endif /* not lint */ |
#endif /* not lint */ |
|
|
|
|
* name and return it. |
* name and return it. |
*/ |
*/ |
struct name * |
struct name * |
nalloc(str, ntype) |
nalloc(char *str, int ntype) |
char str[]; |
|
int ntype; |
|
{ |
{ |
struct name *np; |
struct name *np; |
|
|
np = (struct name *)salloc(sizeof(*np)); |
np = (struct name *)salloc(sizeof(*np)); |
np->n_flink = NIL; |
np->n_flink = NULL; |
np->n_blink = NIL; |
np->n_blink = NULL; |
np->n_type = ntype; |
np->n_type = ntype; |
np->n_name = savestr(str); |
np->n_name = savestr(str); |
return(np); |
return(np); |
|
|
* Find the tail of a list and return it. |
* Find the tail of a list and return it. |
*/ |
*/ |
struct name * |
struct name * |
tailof(name) |
tailof(struct name *name) |
struct name *name; |
|
{ |
{ |
struct name *np; |
struct name *np; |
|
|
np = name; |
np = name; |
if (np == NIL) |
if (np == NULL) |
return(NIL); |
return(NULL); |
while (np->n_flink != NIL) |
while (np->n_flink != NULL) |
np = np->n_flink; |
np = np->n_flink; |
return(np); |
return(np); |
} |
} |
|
|
/* |
/* |
* Extract a list of names from a line, |
* Extract a list of names from a line, |
* and make a list of names from it. |
* and make a list of names from it. |
* Return the list or NIL if none found. |
* Return the list or NULL if none found. |
*/ |
*/ |
struct name * |
struct name * |
extract(line, ntype) |
extract(char *line, int ntype) |
char line[]; |
|
int ntype; |
|
{ |
{ |
char *cp; |
char *cp; |
struct name *top, *np, *t; |
struct name *top, *np, *t; |
char *nbuf; |
char *nbuf; |
|
|
if (line == NULL || *line == '\0') |
if (line == NULL || *line == '\0') |
return(NIL); |
return(NULL); |
if ((nbuf = (char *)malloc(strlen(line) + 1)) == NULL) |
if ((nbuf = (char *)malloc(strlen(line) + 1)) == NULL) |
errx(1, "Out of memory"); |
errx(1, "Out of memory"); |
top = NIL; |
top = NULL; |
np = NIL; |
np = NULL; |
cp = line; |
cp = line; |
while ((cp = yankword(cp, nbuf)) != NULL) { |
while ((cp = yankword(cp, nbuf)) != NULL) { |
t = nalloc(nbuf, ntype); |
t = nalloc(nbuf, ntype); |
if (top == NIL) |
if (top == NULL) |
top = t; |
top = t; |
else |
else |
np->n_flink = t; |
np->n_flink = t; |
|
|
* Turn a list of names into a string of the same names. |
* Turn a list of names into a string of the same names. |
*/ |
*/ |
char * |
char * |
detract(np, ntype) |
detract(struct name *np, int ntype) |
struct name *np; |
|
int ntype; |
|
{ |
{ |
int s, comma; |
int s, comma; |
char *cp, *top; |
char *cp, *top; |
struct name *p; |
struct name *p; |
|
|
comma = ntype & GCOMMA; |
comma = ntype & GCOMMA; |
if (np == NIL) |
if (np == NULL) |
return(NULL); |
return(NULL); |
ntype &= ~GCOMMA; |
ntype &= ~GCOMMA; |
s = 0; |
s = 0; |
if (debug && comma) |
if (debug && comma) |
fputs("detract asked to insert commas\n", stderr); |
fputs("detract asked to insert commas\n", stderr); |
for (p = np; p != NIL; p = p->n_flink) { |
for (p = np; p != NULL; p = p->n_flink) { |
if (ntype && (p->n_type & GMASK) != ntype) |
if (ntype && (p->n_type & GMASK) != ntype) |
continue; |
continue; |
s += strlen(p->n_name) + 1; |
s += strlen(p->n_name) + 1; |
|
|
s += 2; |
s += 2; |
top = salloc(s); |
top = salloc(s); |
cp = top; |
cp = top; |
for (p = np; p != NIL; p = p->n_flink) { |
for (p = np; p != NULL; p = p->n_flink) { |
if (ntype && (p->n_type & GMASK) != ntype) |
if (ntype && (p->n_type & GMASK) != ntype) |
continue; |
continue; |
cp = copy(p->n_name, cp); |
cp = copy(p->n_name, cp); |
if (comma && p->n_flink != NIL) |
if (comma && p->n_flink != NULL) |
*cp++ = ','; |
*cp++ = ','; |
*cp++ = ' '; |
*cp++ = ' '; |
} |
} |
|
|
* Throw away things between ()'s, and take anything between <>. |
* Throw away things between ()'s, and take anything between <>. |
*/ |
*/ |
char * |
char * |
yankword(ap, wbuf) |
yankword(char *ap, char *wbuf) |
char *ap, wbuf[]; |
|
{ |
{ |
char *cp, *cp2; |
char *cp, *cp2; |
|
|
|
|
* program and removed. |
* program and removed. |
*/ |
*/ |
struct name * |
struct name * |
outof(names, fo, hp) |
outof(struct name *names, FILE *fo, struct header *hp) |
struct name *names; |
|
FILE *fo; |
|
struct header *hp; |
|
{ |
{ |
int c, ispipe; |
int c, ispipe; |
struct name *np, *top; |
struct name *np, *top; |
|
|
np = names; |
np = names; |
(void)time(&now); |
(void)time(&now); |
date = ctime(&now); |
date = ctime(&now); |
while (np != NIL) { |
while (np != NULL) { |
if (!isfileaddr(np->n_name) && np->n_name[0] != '|') { |
if (!isfileaddr(np->n_name) && np->n_name[0] != '|') { |
np = np->n_flink; |
np = np->n_flink; |
continue; |
continue; |
|
|
* See if we have copied the complete message out yet. |
* See if we have copied the complete message out yet. |
* If not, do so. |
* If not, do so. |
*/ |
*/ |
|
|
if (image < 0) { |
if (image < 0) { |
int fd; |
int fd; |
char tempname[PATHSIZE]; |
char tempname[PATHSIZE]; |
|
|
* or give it as the standard input to the desired |
* or give it as the standard input to the desired |
* program as appropriate. |
* program as appropriate. |
*/ |
*/ |
|
|
if (ispipe) { |
if (ispipe) { |
int pid; |
pid_t pid; |
char *shell; |
char *shell; |
sigset_t nset; |
sigset_t nset; |
|
|
|
|
* be a filename. We cheat with .'s to allow path names like ./... |
* be a filename. We cheat with .'s to allow path names like ./... |
*/ |
*/ |
int |
int |
isfileaddr(name) |
isfileaddr(char *name) |
char *name; |
|
{ |
{ |
char *cp; |
char *cp; |
|
|
|
|
* Changed after all these months of service to recursively |
* Changed after all these months of service to recursively |
* expand names (2/14/80). |
* expand names (2/14/80). |
*/ |
*/ |
|
|
struct name * |
struct name * |
usermap(names) |
usermap(struct name *names) |
struct name *names; |
|
{ |
{ |
struct name *new, *np, *cp; |
struct name *new, *np, *cp; |
struct grouphead *gh; |
struct grouphead *gh; |
int metoo; |
int metoo; |
|
|
new = NIL; |
new = NULL; |
np = names; |
np = names; |
metoo = (value("metoo") != NULL); |
metoo = (value("metoo") != NULL); |
while (np != NIL) { |
while (np != NULL) { |
if (np->n_name[0] == '\\') { |
if (np->n_name[0] == '\\') { |
cp = np->n_flink; |
cp = np->n_flink; |
new = put(new, np); |
new = put(new, np); |
|
|
} |
} |
gh = findgroup(np->n_name); |
gh = findgroup(np->n_name); |
cp = np->n_flink; |
cp = np->n_flink; |
if (gh != NOGRP) |
if (gh != NULL) |
new = gexpand(new, gh, metoo, np->n_type); |
new = gexpand(new, gh, metoo, np->n_type); |
else |
else |
new = put(new, np); |
new = put(new, np); |
|
|
* fixed level to keep things from going haywire. |
* fixed level to keep things from going haywire. |
* Direct recursion is not expanded for convenience. |
* Direct recursion is not expanded for convenience. |
*/ |
*/ |
|
|
struct name * |
struct name * |
gexpand(nlist, gh, metoo, ntype) |
gexpand(struct name *nlist, struct grouphead *gh, int metoo, int ntype) |
struct name *nlist; |
|
struct grouphead *gh; |
|
int metoo, ntype; |
|
{ |
{ |
struct group *gp; |
struct group *gp; |
struct grouphead *ngh; |
struct grouphead *ngh; |
|
|
return(nlist); |
return(nlist); |
} |
} |
depth++; |
depth++; |
for (gp = gh->g_list; gp != NOGE; gp = gp->ge_link) { |
for (gp = gh->g_list; gp != NULL; gp = gp->ge_link) { |
cp = gp->ge_name; |
cp = gp->ge_name; |
if (*cp == '\\') |
if (*cp == '\\') |
goto quote; |
goto quote; |
if (strcmp(cp, gh->g_name) == 0) |
if (strcmp(cp, gh->g_name) == 0) |
goto quote; |
goto quote; |
if ((ngh = findgroup(cp)) != NOGRP) { |
if ((ngh = findgroup(cp)) != NULL) { |
nlist = gexpand(nlist, ngh, metoo, ntype); |
nlist = gexpand(nlist, ngh, metoo, ntype); |
continue; |
continue; |
} |
} |
|
|
* At this point should allow to expand |
* At this point should allow to expand |
* to self if only person in group |
* to self if only person in group |
*/ |
*/ |
if (gp == gh->g_list && gp->ge_link == NOGE) |
if (gp == gh->g_list && gp->ge_link == NULL) |
goto skip; |
goto skip; |
if (!metoo && strcmp(cp, myname) == 0) |
if (!metoo && strcmp(cp, myname) == 0) |
np->n_type |= GDEL; |
np->n_type |= GDEL; |
|
|
* Concatenate the two passed name lists, return the result. |
* Concatenate the two passed name lists, return the result. |
*/ |
*/ |
struct name * |
struct name * |
cat(n1, n2) |
cat(struct name *n1, struct name *n2) |
struct name *n1, *n2; |
|
{ |
{ |
struct name *tail; |
struct name *tail; |
|
|
if (n1 == NIL) |
if (n1 == NULL) |
return(n2); |
return(n2); |
if (n2 == NIL) |
if (n2 == NULL) |
return(n1); |
return(n1); |
tail = tailof(n1); |
tail = tailof(n1); |
tail->n_flink = n2; |
tail->n_flink = n2; |
|
|
* Return an error if the name list won't fit. |
* Return an error if the name list won't fit. |
*/ |
*/ |
char ** |
char ** |
unpack(sm, np) |
unpack(struct name *np, struct name *sm) |
struct name *np, *sm; |
|
{ |
{ |
char **ap, **top; |
char **ap, **top; |
int t, extra, metoo, verbose; |
int t, extra, metoo, verbose; |
|
|
*ap++ = "-m"; |
*ap++ = "-m"; |
if (verbose) |
if (verbose) |
*ap++ = "-v"; |
*ap++ = "-v"; |
for (; sm != NIL; sm = sm->n_flink) |
for (; sm != NULL; sm = sm->n_flink) |
if ((sm->n_type & GDEL) == 0) |
if ((sm->n_type & GDEL) == 0) |
*ap++ = sm->n_name; |
*ap++ = sm->n_name; |
*ap++ = "--"; |
*ap++ = "--"; |
for (; np != NIL; np = np->n_flink) |
for (; np != NULL; np = np->n_flink) |
if ((np->n_type & GDEL) == 0) |
if ((np->n_type & GDEL) == 0) |
*ap++ = np->n_name; |
*ap++ = np->n_name; |
*ap = NULL; |
*ap = NULL; |
|
|
* Return the head of the new list. |
* Return the head of the new list. |
*/ |
*/ |
struct name * |
struct name * |
elide(names) |
elide(struct name *names) |
struct name *names; |
|
{ |
{ |
struct name *np, *t, *new; |
struct name *np, *t, *new; |
struct name *x; |
struct name *x; |
|
|
if (names == NIL) |
if (names == NULL) |
return(NIL); |
return(NULL); |
new = names; |
new = names; |
np = names; |
np = names; |
np = np->n_flink; |
np = np->n_flink; |
if (np != NIL) |
if (np != NULL) |
np->n_blink = NIL; |
np->n_blink = NULL; |
new->n_flink = NIL; |
new->n_flink = NULL; |
while (np != NIL) { |
while (np != NULL) { |
t = new; |
t = new; |
while (strcasecmp(t->n_name, np->n_name) < 0) { |
while (strcasecmp(t->n_name, np->n_name) < 0) { |
if (t->n_flink == NIL) |
if (t->n_flink == NULL) |
break; |
break; |
t = t->n_flink; |
t = t->n_flink; |
} |
} |
|
|
* If we ran out of t's, put the new entry after |
* If we ran out of t's, put the new entry after |
* the current value of t. |
* the current value of t. |
*/ |
*/ |
|
|
if (strcasecmp(t->n_name, np->n_name) < 0) { |
if (strcasecmp(t->n_name, np->n_name) < 0) { |
t->n_flink = np; |
t->n_flink = np; |
np->n_blink = t; |
np->n_blink = t; |
t = np; |
t = np; |
np = np->n_flink; |
np = np->n_flink; |
t->n_flink = NIL; |
t->n_flink = NULL; |
continue; |
continue; |
} |
} |
|
|
|
|
* current t. If at the front of the list, |
* current t. If at the front of the list, |
* the new guy becomes the new head of the list. |
* the new guy becomes the new head of the list. |
*/ |
*/ |
|
|
if (t == new) { |
if (t == new) { |
t = np; |
t = np; |
np = np->n_flink; |
np = np->n_flink; |
t->n_flink = new; |
t->n_flink = new; |
new->n_blink = t; |
new->n_blink = t; |
t->n_blink = NIL; |
t->n_blink = NULL; |
new = t; |
new = t; |
continue; |
continue; |
} |
} |
|
|
* The normal case -- we are inserting into the |
* The normal case -- we are inserting into the |
* middle of the list. |
* middle of the list. |
*/ |
*/ |
|
|
x = np; |
x = np; |
np = np->n_flink; |
np = np->n_flink; |
x->n_flink = t; |
x->n_flink = t; |
|
|
* Now the list headed up by new is sorted. |
* Now the list headed up by new is sorted. |
* Go through it and remove duplicates. |
* Go through it and remove duplicates. |
*/ |
*/ |
|
|
np = new; |
np = new; |
while (np != NIL) { |
while (np != NULL) { |
t = np; |
t = np; |
while (t->n_flink != NIL && |
while (t->n_flink != NULL && |
strcasecmp(np->n_name, t->n_flink->n_name) == 0) |
strcasecmp(np->n_name, t->n_flink->n_name) == 0) |
t = t->n_flink; |
t = t->n_flink; |
if (t == np || t == NIL) { |
if (t == np || t == NULL) { |
np = np->n_flink; |
np = np->n_flink; |
continue; |
continue; |
} |
} |
|
|
* Now t points to the last entry with the same name |
* Now t points to the last entry with the same name |
* as np. Make np point beyond t. |
* as np. Make np point beyond t. |
*/ |
*/ |
|
|
np->n_flink = t->n_flink; |
np->n_flink = t->n_flink; |
if (t->n_flink != NIL) |
if (t->n_flink != NULL) |
t->n_flink->n_blink = np; |
t->n_flink->n_blink = np; |
np = np->n_flink; |
np = np->n_flink; |
} |
} |
|
|
* the list. |
* the list. |
*/ |
*/ |
struct name * |
struct name * |
put(list, node) |
put(struct name *list, struct name *node) |
struct name *list, *node; |
|
{ |
{ |
node->n_flink = list; |
node->n_flink = list; |
node->n_blink = NIL; |
node->n_blink = NULL; |
if (list != NIL) |
if (list != NULL) |
list->n_blink = node; |
list->n_blink = node; |
return(node); |
return(node); |
} |
} |
|
|
* a name list and return it. |
* a name list and return it. |
*/ |
*/ |
int |
int |
count(np) |
count(struct name *np) |
struct name *np; |
|
{ |
{ |
int c; |
int c; |
|
|
for (c = 0; np != NIL; np = np->n_flink) |
for (c = 0; np != NULL; np = np->n_flink) |
if ((np->n_type & GDEL) == 0) |
if ((np->n_type & GDEL) == 0) |
c++; |
c++; |
return(c); |
return(c); |
|
|
* Delete the given name from a namelist. |
* Delete the given name from a namelist. |
*/ |
*/ |
struct name * |
struct name * |
delname(np, name) |
delname(struct name *np, char *name) |
struct name *np; |
|
char name[]; |
|
{ |
{ |
struct name *p; |
struct name *p; |
|
|
for (p = np; p != NIL; p = p->n_flink) |
for (p = np; p != NULL; p = p->n_flink) |
if ((strcasecmp(p->n_name, name) == 0) || |
if ((strcasecmp(p->n_name, name) == 0) || |
(value("allnet") && |
(value("allnet") && |
strncasecmp(p->n_name, name, strlen(name)) == 0 && |
strncasecmp(p->n_name, name, strlen(name)) == 0 && |
*(p->n_name+strlen(name)) == '@')) { |
*(p->n_name+strlen(name)) == '@')) { |
if (p->n_blink == NIL) { |
if (p->n_blink == NULL) { |
if (p->n_flink != NIL) |
if (p->n_flink != NULL) |
p->n_flink->n_blink = NIL; |
p->n_flink->n_blink = NULL; |
np = p->n_flink; |
np = p->n_flink; |
continue; |
continue; |
} |
} |
if (p->n_flink == NIL) { |
if (p->n_flink == NULL) { |
if (p->n_blink != NIL) |
if (p->n_blink != NULL) |
p->n_blink->n_flink = NIL; |
p->n_blink->n_flink = NULL; |
continue; |
continue; |
} |
} |
p->n_blink->n_flink = p->n_flink; |
p->n_blink->n_flink = p->n_flink; |
|
|
* Pretty print a name list |
* Pretty print a name list |
* Uncomment it if you need it. |
* Uncomment it if you need it. |
*/ |
*/ |
|
#if 0 |
/* |
|
void |
void |
prettyprint(name) |
prettyprint(name) |
struct name *name; |
struct name *name; |
|
|
struct name *np; |
struct name *np; |
|
|
np = name; |
np = name; |
while (np != NIL) { |
while (np != NULL) { |
fprintf(stderr, "%s(%d) ", np->n_name, np->n_type); |
fprintf(stderr, "%s(%d) ", np->n_name, np->n_type); |
np = np->n_flink; |
np = np->n_flink; |
} |
} |
putc('\n', stderr); |
putc('\n', stderr); |
} |
} |
*/ |
#endif |