2 ** aliasbr.c -- new aliasing mechanism
4 ** This code is Copyright (c) 2002, by the authors of nmh. See the
5 ** COPYRIGHT file in the root directory of the nmh distribution for
6 ** complete copyright information.
10 #include <h/aliasbr.h>
19 struct aka *akahead = NULL;
20 struct aka *akatail = NULL;
22 struct home *homehead = NULL;
23 struct home *hometail = NULL;
31 char *akresult(struct aka *);
32 char *akvalue(char *);
35 static char *akval(struct aka *, char *);
36 static int aleq(char *, char *);
37 static char *scanp(unsigned char *);
38 static char *getp(char *);
39 static char *seekp(char *, char *, char **);
40 static int addfile(struct aka *, char *);
41 static int addgroup(struct aka *, char *);
42 static int addmember(struct aka *, char *);
43 static char *getalias(char *);
44 static void add_aka(struct aka *, char *);
45 static struct aka *akalloc(char *);
46 static struct home *hmalloc(struct passwd *);
47 struct home *seek_home(char *);
50 /* Do mh alias substitution on 's' and return the results. */
57 v = akval(akahead, s);
72 akresult(struct aka *ak)
74 char *cp = NULL, *dp, *pp;
77 for (ad = ak->ak_addr; ad; ad = ad->ad_next) {
78 pp = ad->ad_local ? akval(ak->ak_next, ad->ad_text)
79 : getcpy(ad->ad_text);
83 cp = concat(cp, ",", pp, NULL);
91 akvis = ak->ak_visible;
97 akval(struct aka *ak, char *s)
102 for (; ak; ak = ak->ak_next)
103 if (aleq(s, ak->ak_name))
111 aleq(char *string, char *aliasent)
115 while ((c = *string++))
116 if (*aliasent == '*')
118 else if ((c | 040) != (*aliasent | 040))
123 return (*aliasent == 0 || *aliasent == '*');
128 ** file needs to be absolute or relative to cwd
136 struct aka *ak = NULL;
139 if ((fp = fopen(file, "r")) == NULL) {
144 while (vfgets(fp, &ap) == OK) {
146 switch (*(pp = scanp(bp))) {
147 case '<': /* recurse a level */
148 if (!*(cp = getp(pp + 1))) {
149 akerrst = "'<' without alias-file";
153 if ((i = alias(cp)) != AK_OK) {
158 case ':': /* comment */
166 if (!*(cp = seekp(pp, &lc, &ap))) {
170 if (!(ak = akalloc(cp))) {
188 switch (*(pp = scanp(ap))) {
193 case '<': /* read values from file */
194 if (!*(cp = getp(pp + 1))) {
198 if (!addfile(ak, cp)) {
204 case '=': /* UNIX group */
205 if (!*(cp = getp(pp + 1))) {
209 if (!addgroup(ak, cp)) {
215 case '+': /* UNIX group members */
216 if (!*(cp = getp(pp + 1))) {
220 if (!addmember(ak, cp)) {
227 while ((cp = getalias(pp)))
241 static char buffer[BUFSIZ];
245 snprintf(buffer, sizeof(buffer), "unable to read '%s'",
250 snprintf(buffer, sizeof(buffer), "error in line '%s'",
255 snprintf(buffer, sizeof(buffer), "out of memory while on '%s'",
260 snprintf(buffer, sizeof(buffer), "no such group as '%s'",
265 snprintf(buffer, sizeof(buffer), "unknown error (%d)", i);
274 scanp(unsigned char *p)
285 unsigned char *cp = scanp(p);
288 while (!isspace(*cp) && *cp)
297 seekp(char *p, char *c, char **a)
302 while (!isspace(*cp) && *cp && *cp != ':' && *cp != ';')
313 addfile(struct aka *ak, char *file)
319 if (!(fp = fopen(etcpath(file), "r"))) {
324 while (fgets(buffer, sizeof buffer, fp))
325 while ((cp = getalias(buffer)))
334 addgroup(struct aka *ak, char *grp)
337 struct group *gr = getgrnam(grp);
338 struct home *hm = NULL;
341 gr = getgrgid(atoi(grp));
347 while ((gp = *gr->gr_mem++))
350 for (hm = homehead; hm; hm = hm->h_next)
351 if (strcmp(hm->h_name, gp)==0) {
352 add_aka(ak, hm->h_name);
355 if ((pw = getpwnam(gp))) {
366 addmember(struct aka *ak, char *grp)
369 struct group *gr = getgrnam(grp);
370 struct home *hm = NULL;
385 for (hm = homehead; hm; hm = hm->h_next)
386 if (hm->h_gid == gid)
387 add_aka(ak, hm->h_name);
394 getalias(char *addrs)
396 unsigned char *pp, *qp;
397 static char *cp = NULL;
405 for (pp = cp; isspace(*pp); pp++)
409 for (qp = pp; *qp != 0 && *qp != ','; qp++)
413 for (cp = qp, qp--; qp > pp; qp--)
426 add_aka(struct aka *ak, char *pp)
430 for (ad = ak->ak_addr, ld = NULL; ad; ld = ad, ad = ad->ad_next)
431 if (strcmp(pp, ad->ad_text)==0)
434 ad = (struct adr *) mh_xmalloc(sizeof(*ad));
435 ad->ad_text = getcpy(pp);
436 ad->ad_local = strchr(pp, '@') == NULL;
452 /* read the passwd database and build a list */
454 while ((pw = getpwent())) {
461 init++; /* now we're initialized */
471 p = (struct aka *) mh_xmalloc(sizeof(*p));
473 p->ak_name = getcpy(id);
478 akatail->ak_next = p;
488 hmalloc(struct passwd *pw)
492 p = (struct home *) mh_xmalloc(sizeof(*p));
494 p->h_name = getcpy(pw->pw_name);
495 p->h_uid = pw->pw_uid;
496 p->h_gid = pw->pw_gid;
497 p->h_home = getcpy(pw->pw_dir);
498 p->h_shell = getcpy(pw->pw_shell);
505 hometail->h_next = p;
513 seek_home(char *name)
521 for (hp = homehead; hp; hp = hp->h_next)
522 if (!mh_strcasecmp(name, hp->h_name))
526 ** The only place where there might be problems.
527 ** This assumes that ALL usernames are kept in lowercase.
529 for (c = name, c1 = lname; *c && (c1 - lname < (int)sizeof(lname) - 1);
531 if (isalpha(*c) && isupper(*c))
537 if ((pw = getpwnam(lname)))