Mercurial > hg > Applications > mh
diff uip/aliasbr.c @ 0:bce86c4163a3
Initial revision
author | kono |
---|---|
date | Mon, 18 Apr 2005 23:46:02 +0900 |
parents | |
children | 441a2190cfae |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uip/aliasbr.c Mon Apr 18 23:46:02 2005 +0900 @@ -0,0 +1,612 @@ +/* aliasbr.c - new aliasing mechanism */ +#ifndef lint +static char ident[] = "@(#)$Id$"; +#endif /* lint */ + +#include "../h/mh.h" +#include "../h/aliasbr.h" +#ifdef BSD44 +#include <sys/types.h> +#endif +#include <ctype.h> +#include <grp.h> +#include <pwd.h> +#include <stdio.h> + +static int akvis; +static char *akerrst; + +struct aka *akahead = NULL; +struct aka *akatail = NULL; + +struct home *homehead = NULL; +struct home *hometail = NULL; + +static char *scanp (), *getp (), *seekp (), *akval (), *getalias (); +static struct aka *akalloc (); +static struct home *hmalloc (); + +static add_aka(); +static int aleq(), addfile(), addgroup(), addmember(), addall(); + +#ifndef __STDC__ +#ifdef SYS5 +struct passwd *getpwent (); +struct group *getgrnam (), *getgrgid (); +#endif +#endif + +/* */ + +char *akvalue (s) +register char *s; +{ + register char *v; + + if (akahead == NULL) + (void) alias (AliasFile); + + akvis = -1; + v = akval (akahead, s); + if (akvis == -1) + akvis = 0; + return v; +} + + +int akvisible () { + return akvis; +} + +/* */ + +char *akresult (ak) +register 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 (dp = cp) { + cp = concat (cp, ",", pp, NULLCP); + free (dp); + free (pp); + } + else + cp = pp; + } + + if (akvis == -1) + akvis = ak -> ak_visible; +#ifdef JAPAN + (void) ml_conv(cp); +#endif + return cp; +} + + +static char *akval (ak, s) +register struct aka *ak; +register 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 (string, aliasent) +register char *string, + *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 (file) +register 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 = libpath (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"; + (void) fclose (fp); + return AK_ERROR; + } + if ((i = alias (cp)) != AK_OK) { + (void) fclose (fp); + return i; + } + + case ':': /* comment */ + case ';': + case '#': + case 0: + continue; + } + + akerrst = bp; + if (!*(cp = seekp (pp, &lc, &ap))) { + (void) fclose (fp); + return AK_ERROR; + } + if (!(ak = akalloc (cp))) { + (void) fclose (fp); + return AK_LIMIT; + } + switch (lc) { + case ':': + ak -> ak_visible = 0; + break; + + case ';': + ak -> ak_visible = 1; + break; + + default: + (void) fclose (fp); + return AK_ERROR; + } + + switch (*(pp = scanp (ap))) { + case 0: /* EOL */ + (void) fclose (fp); + return AK_ERROR; + + case '<': /* read values from file */ + if (!*(cp = getp (pp + 1))) { + (void) fclose (fp); + return AK_ERROR; + } + if (!addfile (ak, cp)) { + (void) fclose (fp); + return AK_NOFILE; + } + break; + + case '=': /* UNIX group */ + if (!*(cp = getp (pp + 1))) { + (void) fclose (fp); + return AK_ERROR; + } + if (!addgroup (ak, cp)) { + (void) fclose (fp); + return AK_NOGROUP; + } + break; + + case '+': /* UNIX group members */ + if (!*(cp = getp (pp + 1))) { + (void) fclose (fp); + return AK_ERROR; + } + if (!addmember (ak, cp)) { + (void) fclose (fp); + return AK_NOGROUP; + } + break; + + case '*': /* Everyone */ + (void) addall (ak); + break; + + default: /* list */ + while (cp = getalias (pp)) + add_aka (ak, cp); + break; + } + } + + (void) fclose (fp); + return AK_OK; +} + +/* */ + +char *akerror (i) +int i; +{ + static char buffer[BUFSIZ]; + + switch (i) { + case AK_NOFILE: + (void) sprintf (buffer, "unable to read '%s'", akerrst); + break; + + case AK_ERROR: + (void) sprintf (buffer, "error in line '%s'", akerrst); + break; + + case AK_LIMIT: + (void) sprintf (buffer, "out of memory while on '%s'", akerrst); + break; + + case AK_NOGROUP: + (void) sprintf (buffer, "no such group as '%s'", akerrst); + break; + + default: + (void) sprintf (buffer, "unknown error (%d)", i); + break; + } + + return buffer; +} + +/* */ + +static char *scanp (p) +register char *p; +{ + while (isspace (*p)) + p++; + return p; +} + + +static char *getp (p) +register char *p; +{ + register char *cp = scanp (p); + + p = cp; + while (!isspace (*cp) && *cp) + cp++; + *cp = 0; + + return p; +} + + +static char *seekp (p, c, a) +register char *p, + *c, + **a; +{ + register char *cp = scanp (p); + + p = cp; + while (!isspace (*cp) && *cp && *cp != ':' && *cp != ';') + cp++; + *c = *cp; + *cp++ = 0; + *a = cp; + + return p; +} + +/* */ + +static int addfile (ak, file) +register struct aka *ak; +register char *file; +{ + register char *cp; + char buffer[BUFSIZ]; + register FILE *fp; + + if ((fp = fopen (libpath (file), "r")) == NULL) { + akerrst = file; + return 0; + } + + while (fgets (buffer, sizeof buffer, fp) != NULL) + while (cp = getalias (buffer)) + add_aka (ak, cp); + + (void) fclose (fp); + return 1; +} + +/* */ + +static int addgroup (ak, grp) +register struct aka *ak; +register 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 (ak, grp) +register struct aka *ak; +register char *grp; +{ + int 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 (ak) +register struct aka *ak; +{ + int noshell = NoShell == NULLCP || *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 (addrs) +register 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 add_aka (ak, pp) +register struct aka *ak; +register 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 = index (pp, '@') == NULL && index (pp, '!') == NULL; + ad -> ad_next = NULL; + if (ak -> ak_addr) + ld -> ad_next = ad; + else + ak -> ak_addr = ad; +} + + +init_pw () { + 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 */ + + (void) setpwent (); + + while (pw = getpwent ()) + if (!hmalloc (pw)) + break; + + (void) endpwent (); +#ifdef DBMPWD + } +#endif /* DBMPWD */ +} + +/* */ + +static struct aka *akalloc (id) +register char *id; +{ + register struct aka *p = (struct aka *) malloc (sizeof *p); + + if (!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 (pw) +struct passwd *pw; +{ + register struct home *p = (struct home *) malloc (sizeof *p); + + if (!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); +#if defined(BSD42) || defined(SVR4) + p -> h_ngrps = 0; +#endif /* BSD42 || SVR4 */ + 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 (name) +register 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 (uleq (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; 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 */