/* * aliasbr.c -- new aliasing mechanism * * $Id: aliasbr.c,v 1.1.1.1 1999-02-07 18:14:12 danw Exp $ */ #include #include #include #include static int akvis; static char *akerrst; struct aka *akahead = NULL; struct aka *akatail = NULL; struct home *homehead = NULL; struct home *hometail = NULL; /* * prototypes */ int alias (char *); int akvisible (void); void init_pw (void); char *akresult (struct aka *); char *akvalue (char *); char *akerror (int); static char *akval (struct aka *, char *); static int aleq (char *, char *); static char *scanp (char *); static char *getp (char *); static char *seekp (char *, char *, char **); static int addfile (struct aka *, char *); static int addgroup (struct aka *, char *); static int addmember (struct aka *, char *); static int addall (struct aka *); static char *getalias (char *); static void add_aka (struct aka *, char *); static struct aka *akalloc (char *); static struct home *hmalloc (struct passwd *); #ifndef MMDFMTS struct home *seek_home (char *); #endif char * akvalue (char *s) { register char *v; if (akahead == NULL) alias (AliasFile); akvis = -1; v = akval (akahead, s); if (akvis == -1) akvis = 0; return v; } int akvisible (void) { return akvis; } char * akresult (struct aka *ak) { register char *cp = NULL, *dp, *pp; register struct adr *ad; for (ad = ak->ak_addr; ad; ad = ad->ad_next) { pp = ad->ad_local ? akval (ak->ak_next, ad->ad_text) : getcpy (ad->ad_text); if (cp) { dp = cp; cp = concat (cp, ",", pp, NULL); free (dp); free (pp); } else cp = pp; } if (akvis == -1) akvis = ak->ak_visible; return cp; } static char * akval (struct aka *ak, char *s) { if (!s) return s; /* XXX */ for (; ak; ak = ak->ak_next) if (aleq (s, ak->ak_name)) return akresult (ak); return getcpy (s); } static int aleq (char *string, char *aliasent) { register char c; while ((c = *string++)) if (*aliasent == '*') return 1; else if ((c | 040) != (*aliasent | 040)) return 0; else aliasent++; return (*aliasent == 0 || *aliasent == '*'); } int alias (char *file) { int i; register char *bp, *cp, *pp; char lc, *ap; register struct aka *ak = NULL; register FILE *fp; if (*file != '/' && (strncmp (file, "./", 2) && strncmp (file, "../", 3))) file = etcpath (file); if ((fp = fopen (file, "r")) == NULL) { akerrst = file; return AK_NOFILE; } while (vfgets (fp, &ap) == OK) { bp = ap; switch (*(pp = scanp (bp))) { case '<': /* recurse a level */ if (!*(cp = getp (pp + 1))) { akerrst = "'<' without alias-file"; fclose (fp); return AK_ERROR; } if ((i = alias (cp)) != AK_OK) { fclose (fp); return i; } case ':': /* comment */ case ';': case '#': case 0: continue; } akerrst = bp; if (!*(cp = seekp (pp, &lc, &ap))) { fclose (fp); return AK_ERROR; } if (!(ak = akalloc (cp))) { fclose (fp); return AK_LIMIT; } switch (lc) { case ':': ak->ak_visible = 0; break; case ';': ak->ak_visible = 1; break; default: fclose (fp); return AK_ERROR; } switch (*(pp = scanp (ap))) { case 0: /* EOL */ fclose (fp); return AK_ERROR; case '<': /* read values from file */ if (!*(cp = getp (pp + 1))) { fclose (fp); return AK_ERROR; } if (!addfile (ak, cp)) { fclose (fp); return AK_NOFILE; } break; case '=': /* UNIX group */ if (!*(cp = getp (pp + 1))) { fclose (fp); return AK_ERROR; } if (!addgroup (ak, cp)) { fclose (fp); return AK_NOGROUP; } break; case '+': /* UNIX group members */ if (!*(cp = getp (pp + 1))) { fclose (fp); return AK_ERROR; } if (!addmember (ak, cp)) { fclose (fp); return AK_NOGROUP; } break; case '*': /* Everyone */ addall (ak); break; default: /* list */ while ((cp = getalias (pp))) add_aka (ak, cp); break; } } fclose (fp); return AK_OK; } char * akerror (int i) { static char buffer[BUFSIZ]; switch (i) { case AK_NOFILE: snprintf (buffer, sizeof(buffer), "unable to read '%s'", akerrst); break; case AK_ERROR: snprintf (buffer, sizeof(buffer), "error in line '%s'", akerrst); break; case AK_LIMIT: snprintf (buffer, sizeof(buffer), "out of memory while on '%s'", akerrst); break; case AK_NOGROUP: snprintf (buffer, sizeof(buffer), "no such group as '%s'", akerrst); break; default: snprintf (buffer, sizeof(buffer), "unknown error (%d)", i); break; } return buffer; } static char * scanp (char *p) { while (isspace (*p)) p++; return p; } static char * getp (char *p) { register char *cp = scanp (p); p = cp; while (!isspace (*cp) && *cp) cp++; *cp = 0; return p; } static char * seekp (char *p, char *c, char **a) { register char *cp; p = cp = scanp (p); while (!isspace (*cp) && *cp && *cp != ':' && *cp != ';') cp++; *c = *cp; *cp++ = 0; *a = cp; return p; } static int addfile (struct aka *ak, char *file) { register char *cp; char buffer[BUFSIZ]; register FILE *fp; if (!(fp = fopen (etcpath (file), "r"))) { akerrst = file; return 0; } while (fgets (buffer, sizeof buffer, fp)) while ((cp = getalias (buffer))) add_aka (ak, cp); fclose (fp); return 1; } static int addgroup (struct aka *ak, char *grp) { register char *gp; register struct group *gr = getgrnam (grp); register struct home *hm = NULL; if (!gr) gr = getgrgid (atoi (grp)); if (!gr) { akerrst = grp; return 0; } #ifndef DBMPWD if (homehead == NULL) init_pw (); #endif /* DBMPWD */ while ((gp = *gr->gr_mem++)) #ifdef DBMPWD { struct passwd *pw; #endif /* DBMPWD */ for (hm = homehead; hm; hm = hm->h_next) if (!strcmp (hm->h_name, gp)) { add_aka (ak, hm->h_name); break; } #ifdef DBMPWD if ((pw = getpwnam(gp))) { hmalloc(pw); add_aka (ak, gp); } } #endif /* DBMPWD */ return 1; } static int addmember (struct aka *ak, char *grp) { gid_t gid; register struct group *gr = getgrnam (grp); register struct home *hm = NULL; if (gr) gid = gr->gr_gid; else { gid = atoi (grp); gr = getgrgid (gid); } if (!gr) { akerrst = grp; return 0; } #ifndef DBMPWD if (homehead == NULL) #endif /* DBMPWD */ init_pw (); for (hm = homehead; hm; hm = hm->h_next) if (hm->h_gid == gid) add_aka (ak, hm->h_name); return 1; } static int addall (struct aka *ak) { int noshell = NoShell == NULL || *NoShell == 0; register struct home *hm; #ifndef DBMPWD if (homehead == NULL) #endif /* DBMPWD */ init_pw (); if (Everyone < 0) Everyone = EVERYONE; for (hm = homehead; hm; hm = hm->h_next) if (hm->h_uid > Everyone && (noshell || strcmp (hm->h_shell, NoShell))) add_aka (ak, hm->h_name); return homehead != NULL; } static char * getalias (char *addrs) { register char *pp, *qp; static char *cp = NULL; if (cp == NULL) cp = addrs; else if (*cp == 0) return (cp = NULL); for (pp = cp; isspace (*pp); pp++) continue; if (*pp == 0) return (cp = NULL); for (qp = pp; *qp != 0 && *qp != ','; qp++) continue; if (*qp == ',') *qp++ = 0; for (cp = qp, qp--; qp > pp; qp--) if (*qp != 0) if (isspace (*qp)) *qp = 0; else break; return pp; } static void add_aka (struct aka *ak, char *pp) { register struct adr *ad, *ld; for (ad = ak->ak_addr, ld = NULL; ad; ld = ad, ad = ad->ad_next) if (!strcmp (pp, ad->ad_text)) return; ad = (struct adr *) malloc (sizeof(*ad)); if (ad == NULL) return; ad->ad_text = getcpy (pp); ad->ad_local = strchr(pp, '@') == NULL && strchr(pp, '!') == NULL; ad->ad_next = NULL; if (ak->ak_addr) ld->ad_next = ad; else ak->ak_addr = ad; } void init_pw (void) { register struct passwd *pw; #ifdef DBMPWD static int init; if (!init) { /* if the list has yet to be initialized */ /* zap the list, and rebuild from scratch */ homehead=NULL; hometail=NULL; init++; #endif /* DBMPWD */ setpwent (); while ((pw = getpwent ())) if (!hmalloc (pw)) break; endpwent (); #ifdef DBMPWD } #endif /* DBMPWD */ } static struct aka * akalloc (char *id) { register struct aka *p; if (!(p = (struct aka *) malloc (sizeof(*p)))) return NULL; p->ak_name = getcpy (id); p->ak_visible = 0; p->ak_addr = NULL; p->ak_next = NULL; if (akatail != NULL) akatail->ak_next = p; if (akahead == NULL) akahead = p; akatail = p; return p; } static struct home * hmalloc (struct passwd *pw) { register struct home *p; if (!(p = (struct home *) malloc (sizeof(*p)))) return NULL; p->h_name = getcpy (pw->pw_name); p->h_uid = pw->pw_uid; p->h_gid = pw->pw_gid; p->h_home = getcpy (pw->pw_dir); p->h_shell = getcpy (pw->pw_shell); p->h_ngrps = 0; p->h_next = NULL; if (hometail != NULL) hometail->h_next = p; if (homehead == NULL) homehead = p; hometail = p; return p; } #ifndef MMDFMTS struct home * seek_home (char *name) { register struct home *hp; #ifdef DBMPWD struct passwd *pw; char lname[32]; char *c,*c1; #else /* DBMPWD */ if (homehead == NULL) init_pw (); #endif /* DBMPWD */ for (hp = homehead; hp; hp = hp->h_next) if (!strcasecmp (name, hp->h_name)) return hp; #ifdef DBMPWD /* * The only place where there might be problems. * This assumes that ALL usernames are kept in lowercase. */ for (c = name, c1 = lname; *c && (c1 - lname < sizeof(lname) - 1); c++, c1++) { if (isalpha(*c) && isupper(*c)) *c1 = tolower (*c); else *c1 = *c; } *c1 = '\0'; if ((pw = getpwnam(lname))) return(hmalloc(pw)); #endif /* DBMPWD */ return NULL; } #endif /* MMDFMTS */