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>
18 struct aka *akahead = NULL;
19 struct aka *akatail = NULL;
21 struct home *homehead = NULL;
22 struct home *hometail = NULL;
30 char *akresult(struct aka *);
31 char *akvalue(char *);
34 static char *akval(struct aka *, char *);
35 static int aleq(char *, char *);
36 static char *scanp(unsigned char *);
37 static char *getp(char *);
38 static char *seekp(char *, char *, char **);
39 static int addfile(struct aka *, char *);
40 static int addgroup(struct aka *, char *);
41 static int addmember(struct aka *, char *);
42 static int addall(struct aka *);
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. */
60 v = akval(akahead, s);
75 akresult(struct aka *ak)
77 register char *cp = NULL, *dp, *pp;
78 register struct adr *ad;
80 for (ad = ak->ak_addr; ad; ad = ad->ad_next) {
81 pp = ad->ad_local ? akval(ak->ak_next, ad->ad_text)
82 : getcpy(ad->ad_text);
86 cp = concat(cp, ",", pp, NULL);
94 akvis = ak->ak_visible;
100 akval(struct aka *ak, char *s)
105 for (; ak; ak = ak->ak_next)
106 if (aleq(s, ak->ak_name))
114 aleq(char *string, char *aliasent)
118 while ((c = *string++))
119 if (*aliasent == '*')
122 if ((c | 040) != (*aliasent | 040))
127 return (*aliasent == 0 || *aliasent == '*');
135 register char *bp, *cp, *pp;
137 register struct aka *ak = NULL;
141 && (strncmp(file, "./", 2) && strncmp(file, "../", 3)))
142 file = etcpath(file);
143 if ((fp = fopen(file, "r")) == NULL) {
148 while (vfgets(fp, &ap) == OK) {
150 switch (*(pp = scanp(bp))) {
151 case '<': /* recurse a level */
152 if (!*(cp = getp(pp + 1))) {
153 akerrst = "'<' without alias-file";
157 if ((i = alias(cp)) != AK_OK) {
162 case ':': /* comment */
170 if (!*(cp = seekp(pp, &lc, &ap))) {
174 if (!(ak = akalloc(cp))) {
192 switch (*(pp = scanp(ap))) {
197 case '<': /* read values from file */
198 if (!*(cp = getp(pp + 1))) {
202 if (!addfile(ak, cp)) {
208 case '=': /* UNIX group */
209 if (!*(cp = getp(pp + 1))) {
213 if (!addgroup(ak, cp)) {
219 case '+': /* UNIX group members */
220 if (!*(cp = getp(pp + 1))) {
224 if (!addmember(ak, cp)) {
230 case '*': /* Everyone */
235 while ((cp = getalias(pp)))
249 static char buffer[BUFSIZ];
253 snprintf(buffer, sizeof(buffer), "unable to read '%s'", akerrst);
257 snprintf(buffer, sizeof(buffer), "error in line '%s'", akerrst);
261 snprintf(buffer, sizeof(buffer), "out of memory while on '%s'", akerrst);
265 snprintf(buffer, sizeof(buffer), "no such group as '%s'", akerrst);
269 snprintf(buffer, sizeof(buffer), "unknown error (%d)", i);
278 scanp(unsigned char *p)
289 register unsigned char *cp = scanp(p);
292 while (!isspace(*cp) && *cp)
301 seekp(char *p, char *c, char **a)
303 register unsigned char *cp;
306 while (!isspace(*cp) && *cp && *cp != ':' && *cp != ';')
317 addfile(struct aka *ak, char *file)
323 if (!(fp = fopen(etcpath(file), "r"))) {
328 while (fgets(buffer, sizeof buffer, fp))
329 while ((cp = getalias(buffer)))
338 addgroup(struct aka *ak, char *grp)
341 register struct group *gr = getgrnam(grp);
342 register struct home *hm = NULL;
345 gr = getgrgid(atoi(grp));
352 if (homehead == NULL)
356 while ((gp = *gr->gr_mem++))
361 for (hm = homehead; hm; hm = hm->h_next)
362 if (!strcmp(hm->h_name, gp)) {
363 add_aka(ak, hm->h_name);
367 if ((pw = getpwnam(gp))) {
379 addmember(struct aka *ak, char *grp)
382 register struct group *gr = getgrnam(grp);
383 register struct home *hm = NULL;
397 if (homehead == NULL)
401 for (hm = homehead; hm; hm = hm->h_next)
402 if (hm->h_gid == gid)
403 add_aka(ak, hm->h_name);
410 addall(struct aka *ak)
412 int noshell = NoShell == NULL || *NoShell == 0;
413 register struct home *hm;
416 if (homehead == NULL)
422 for (hm = homehead; hm; hm = hm->h_next)
423 if (hm->h_uid > Everyone
424 && (noshell || strcmp(hm->h_shell, NoShell)))
425 add_aka(ak, hm->h_name);
427 return homehead != NULL;
432 getalias(char *addrs)
434 register unsigned char *pp, *qp;
435 static char *cp = NULL;
443 for (pp = cp; isspace(*pp); pp++)
447 for (qp = pp; *qp != 0 && *qp != ','; qp++)
451 for (cp = qp, qp--; qp > pp; qp--)
464 add_aka(struct aka *ak, char *pp)
466 register struct adr *ad, *ld;
468 for (ad = ak->ak_addr, ld = NULL; ad; ld = ad, ad = ad->ad_next)
469 if (!strcmp(pp, ad->ad_text))
472 ad = (struct adr *) mh_xmalloc(sizeof(*ad));
473 ad->ad_text = getcpy(pp);
474 ad->ad_local = strchr(pp, '@') == NULL && strchr(pp, '!') == NULL;
486 register struct passwd *pw;
491 /* if the list has yet to be initialized */
492 /* zap the list, and rebuild from scratch */
500 while ((pw = getpwent()))
514 register struct aka *p;
516 p = (struct aka *) mh_xmalloc(sizeof(*p));
518 p->ak_name = getcpy(id);
523 akatail->ak_next = p;
533 hmalloc(struct passwd *pw)
535 register struct home *p;
537 p = (struct home *) mh_xmalloc(sizeof(*p));
539 p->h_name = getcpy(pw->pw_name);
540 p->h_uid = pw->pw_uid;
541 p->h_gid = pw->pw_gid;
542 p->h_home = getcpy(pw->pw_dir);
543 p->h_shell = getcpy(pw->pw_shell);
546 if (hometail != NULL)
547 hometail->h_next = p;
548 if (homehead == NULL)
557 seek_home(char *name)
559 register struct home *hp;
567 if (homehead == NULL)
571 for (hp = homehead; hp; hp = hp->h_next)
572 if (!mh_strcasecmp(name, hp->h_name))
577 ** The only place where there might be problems.
578 ** This assumes that ALL usernames are kept in lowercase.
580 for (c = name, c1 = lname; *c && (c1 - lname < sizeof(lname) - 1);
582 if (isalpha(*c) && isupper(*c))
588 if ((pw = getpwnam(lname)))