3 * aliasbr.c -- new aliasing mechanism
7 * This code is Copyright (c) 2002, by the authors of nmh. See the
8 * COPYRIGHT file in the root directory of the nmh distribution for
9 * complete copyright information.
13 #include <h/aliasbr.h>
21 struct aka *akahead = NULL;
22 struct aka *akatail = NULL;
24 struct home *homehead = NULL;
25 struct home *hometail = NULL;
33 char *akresult (struct aka *);
34 char *akvalue (char *);
37 static char *akval (struct aka *, char *);
38 static int aleq (char *, char *);
39 static char *scanp (char *);
40 static char *getp (char *);
41 static char *seekp (char *, char *, char **);
42 static int addfile (struct aka *, char *);
43 static int addgroup (struct aka *, char *);
44 static int addmember (struct aka *, char *);
45 static int addall (struct aka *);
46 static char *getalias (char *);
47 static void add_aka (struct aka *, char *);
48 static struct aka *akalloc (char *);
49 static struct home *hmalloc (struct passwd *);
51 struct home *seek_home (char *);
55 /* Do mh alias substitution on 's' and return the results. */
65 v = akval (akahead, s);
80 akresult (struct aka *ak)
82 register char *cp = NULL, *dp, *pp;
83 register struct adr *ad;
85 for (ad = ak->ak_addr; ad; ad = ad->ad_next) {
86 pp = ad->ad_local ? akval (ak->ak_next, ad->ad_text)
87 : getcpy (ad->ad_text);
91 cp = concat (cp, ",", pp, NULL);
100 akvis = ak->ak_visible;
106 akval (struct aka *ak, char *s)
111 for (; ak; ak = ak->ak_next)
112 if (aleq (s, ak->ak_name))
113 return akresult (ak);
120 aleq (char *string, char *aliasent)
124 while ((c = *string++))
125 if (*aliasent == '*')
128 if ((c | 040) != (*aliasent | 040))
133 return (*aliasent == 0 || *aliasent == '*');
141 register char *bp, *cp, *pp;
143 register struct aka *ak = NULL;
147 && (strncmp (file, "./", 2) && strncmp (file, "../", 3)))
148 file = etcpath (file);
149 if ((fp = fopen (file, "r")) == NULL) {
154 while (vfgets (fp, &ap) == OK) {
156 switch (*(pp = scanp (bp))) {
157 case '<': /* recurse a level */
158 if (!*(cp = getp (pp + 1))) {
159 akerrst = "'<' without alias-file";
163 if ((i = alias (cp)) != AK_OK) {
168 case ':': /* comment */
176 if (!*(cp = seekp (pp, &lc, &ap))) {
180 if (!(ak = akalloc (cp))) {
198 switch (*(pp = scanp (ap))) {
203 case '<': /* read values from file */
204 if (!*(cp = getp (pp + 1))) {
208 if (!addfile (ak, cp)) {
214 case '=': /* UNIX group */
215 if (!*(cp = getp (pp + 1))) {
219 if (!addgroup (ak, cp)) {
225 case '+': /* UNIX group members */
226 if (!*(cp = getp (pp + 1))) {
230 if (!addmember (ak, cp)) {
236 case '*': /* Everyone */
241 while ((cp = getalias (pp)))
255 static char buffer[BUFSIZ];
259 snprintf (buffer, sizeof(buffer), "unable to read '%s'", akerrst);
263 snprintf (buffer, sizeof(buffer), "error in line '%s'", akerrst);
267 snprintf (buffer, sizeof(buffer), "out of memory while on '%s'", akerrst);
271 snprintf (buffer, sizeof(buffer), "no such group as '%s'", akerrst);
275 snprintf (buffer, sizeof(buffer), "unknown error (%d)", i);
295 register char *cp = scanp (p);
298 while (!isspace (*cp) && *cp)
307 seekp (char *p, char *c, char **a)
312 while (!isspace (*cp) && *cp && *cp != ':' && *cp != ';')
323 addfile (struct aka *ak, char *file)
329 if (!(fp = fopen (etcpath (file), "r"))) {
334 while (fgets (buffer, sizeof buffer, fp))
335 while ((cp = getalias (buffer)))
344 addgroup (struct aka *ak, char *grp)
347 register struct group *gr = getgrnam (grp);
348 register struct home *hm = NULL;
351 gr = getgrgid (atoi (grp));
358 if (homehead == NULL)
362 while ((gp = *gr->gr_mem++))
367 for (hm = homehead; hm; hm = hm->h_next)
368 if (!strcmp (hm->h_name, gp)) {
369 add_aka (ak, hm->h_name);
373 if ((pw = getpwnam(gp)))
386 addmember (struct aka *ak, char *grp)
389 register struct group *gr = getgrnam (grp);
390 register struct home *hm = NULL;
404 if (homehead == NULL)
408 for (hm = homehead; hm; hm = hm->h_next)
409 if (hm->h_gid == gid)
410 add_aka (ak, hm->h_name);
417 addall (struct aka *ak)
419 int noshell = NoShell == NULL || *NoShell == 0;
420 register struct home *hm;
423 if (homehead == NULL)
429 for (hm = homehead; hm; hm = hm->h_next)
430 if (hm->h_uid > Everyone
431 && (noshell || strcmp (hm->h_shell, NoShell)))
432 add_aka (ak, hm->h_name);
434 return homehead != NULL;
439 getalias (char *addrs)
441 register char *pp, *qp;
442 static char *cp = NULL;
450 for (pp = cp; isspace (*pp); pp++)
454 for (qp = pp; *qp != 0 && *qp != ','; qp++)
458 for (cp = qp, qp--; qp > pp; qp--)
471 add_aka (struct aka *ak, char *pp)
473 register struct adr *ad, *ld;
475 for (ad = ak->ak_addr, ld = NULL; ad; ld = ad, ad = ad->ad_next)
476 if (!strcmp (pp, ad->ad_text))
479 ad = (struct adr *) mh_xmalloc (sizeof(*ad));
480 ad->ad_text = getcpy (pp);
481 ad->ad_local = strchr(pp, '@') == NULL && strchr(pp, '!') == NULL;
493 register struct passwd *pw;
499 /* if the list has yet to be initialized */
500 /* zap the list, and rebuild from scratch */
508 while ((pw = getpwent ()))
522 register struct aka *p;
524 p = (struct aka *) mh_xmalloc (sizeof(*p));
526 p->ak_name = getcpy (id);
531 akatail->ak_next = p;
541 hmalloc (struct passwd *pw)
543 register struct home *p;
545 p = (struct home *) mh_xmalloc (sizeof(*p));
547 p->h_name = getcpy (pw->pw_name);
548 p->h_uid = pw->pw_uid;
549 p->h_gid = pw->pw_gid;
550 p->h_home = getcpy (pw->pw_dir);
551 p->h_shell = getcpy (pw->pw_shell);
554 if (hometail != NULL)
555 hometail->h_next = p;
556 if (homehead == NULL)
566 seek_home (char *name)
568 register struct home *hp;
575 if (homehead == NULL)
579 for (hp = homehead; hp; hp = hp->h_next)
580 if (!strcasecmp (name, hp->h_name))
585 * The only place where there might be problems.
586 * This assumes that ALL usernames are kept in lowercase.
588 for (c = name, c1 = lname; *c && (c1 - lname < sizeof(lname) - 1); c++, c1++) {
589 if (isalpha(*c) && isupper(*c))
595 if ((pw = getpwnam(lname)))