Expunge revision histories in files.
[become] / src / name.c
index faa06ab..1ea34a0 100644 (file)
@@ -1,13 +1,13 @@
 /* -*-c-*-
  *
- * $Id: name.c,v 1.1 1997/07/21 13:47:46 mdw Exp $
+ * $Id: name.c,v 1.10 2004/04/08 01:36:20 mdw Exp $
  *
  * Looking up of names in symbol tables
  *
- * (c) 1997 EBI
+ * (c) 1998 EBI
  */
 
-/*----- Licencing notice --------------------------------------------------*
+/*----- Licensing notice --------------------------------------------------*
  *
  * This file is part of `become'
  *
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with `become'; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/*----- Revision history --------------------------------------------------*
- *
- * $Log: name.c,v $
- * Revision 1.1  1997/07/21 13:47:46  mdw
- * Initial revision
- *
+ * along with `become'; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 
 /*----- Header files ------------------------------------------------------*/
 
 /* --- ANSI headers --- */
 
+#include <ctype.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
 /* --- Unix headers --- */
 
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+
+#include <arpa/inet.h>
+
+#include <netdb.h>
 #include <grp.h>
 #include <pwd.h>
 
+/* --- mLib headers --- */
+
+#include <mLib/alloc.h>
+#include <mLib/sym.h>
+
 /* --- Local headers --- */
 
+#include "config.h"
+
+#include "become.h"
 #include "class.h"
 #include "name.h"
-#include "sym.h"
+#include "netg.h"
 #include "userdb.h"
-#include "utils.h"
 
 /*----- Static variables --------------------------------------------------*/
 
@@ -61,91 +69,273 @@ static sym_table name__table;              /* Symbol table for everything */
 
 /*----- Main code ---------------------------------------------------------*/
 
-/* --- @name_init@ --- *
+/* --- @name__get@ --- *
+ *
+ * Arguments:  @const char *p@ = pointer to the name we want
+ *             @unsigned type@ = type of class it should have
+ *
+ * Returns:    A pointer to a name ready to use, or zero if there's a type
+ *             conflict.
+ *
+ * Use:                Creates a name of the appropriate type all ready to use.
+ */
+
+static name *name__get(const char *p, unsigned type)
+{
+  unsigned f;
+  name *n = sym_find(&name__table, p, -1, sizeof(*n), &f);
+  if (!f)
+    n->c = 0;
+  return ((n->c && !(n->c->type & type)) ? 0 : n);
+}
+
+/* --- @name__sanitise@ --- *
+ *
+ * Arguments:  @const char *n@ = pointer to a name
+ *             @char *buf@ = pointer to a buffer of space
+ *             @size_t sz@ = size of the buffer
+ *
+ * Returns:    A pointer to the transformed name in the buffer, or null
+ *             if there wasn't enough space.
+ *
+ * Use:                Transforms a name so that it only contains nice characters.
+ */
+
+static char *name__sanitise(const char *n, char *buf, size_t sz)
+{
+  char *p = buf;
+
+  if (strlen(n) + 1 > sz)
+    return (0);
+
+  while (*n) {
+    if (isalnum((unsigned char)*n))
+      *p++ = *n;
+    else
+      *p++ = '_';
+    n++;
+  }
+  *p++ = 0;
+  return (buf);
+}
+
+/* --- @name__users@ --- *
  *
  * Arguments:  ---
  *
  * Returns:    ---
  *
- * Use:                Initialises the name table.  Requires the user database to
- *             be populated (see @userdb_local@ and @userdb_yp@).
+ * Use:                Adds all of the users registered with the user database to
+ *             the name table.  Also adds the users' primary groups.
  */
 
-void name_init(void)
+static void name__users(void)
 {
-  /* --- Initialise the name table --- */
+  struct passwd *pw;
+  struct group *gr;
+  char buf[32];
 
-  sym_createTable(&name__table);
+  userdb_iterateUsers();
+  while ((pw = userdb_nextUser()) != 0) {
+    name *n;
+    uid_t u = pw->pw_uid;
 
-  /* --- Insert all the users and groups into the table --- */
+    /* --- First, add the user to the table --- */
 
-  {
-    struct passwd *pw;
-    struct group *gr;
+    if (name__sanitise(pw->pw_name, buf, sizeof(buf)) &&
+       (n = name__get(buf, clType_user)) != 0)
+      n->c = class_addUser(n->c, u);
 
-    userdb_iterateUsers();
-    while ((pw = userdb_nextUser()) != 0) {
-      unsigned f;
-      name *n;
-      int u;
+    /* --- Now handle the user's default group --- */
 
-      /* --- First, add the user to the table --- */
+    if ((gr = userdb_groupById(pw->pw_gid)) != 0 &&
+       name__sanitise(gr->gr_name, buf, sizeof(buf)) &&
+       (n = name__get(buf, clType_user)) != 0)
+      n->c = class_addUser(n->c, u);
+  }
+}
 
-      n = sym_find(&name__table, pw->pw_name, -1, sizeof(name), &f);
-      if (!f) {
-       sym_table *t = xmalloc(sizeof(*t));
-       sym_createTable(t);
-       n->c = class_create(clType_user, t);
-      }
-      u = pw->pw_uid;
-      sym_find(n->c->t, (char *)&u, sizeof(u), sizeof(sym_base), 0);
-
-      /* --- Now handle the user's default group --- */
-
-      if ((gr = userdb_groupById(pw->pw_gid)) != 0) {
-       n = sym_find(&name__table, gr->gr_name, -1, sizeof(name), &f);
-       if (!f) {
-         sym_table *t = xmalloc(sizeof(*t));
-         sym_createTable(t);
-         n->c = class_create(clType_user, t);
-       }
-       sym_find(n->c->t, (char *)&u, sizeof(u), sizeof(sym_base), 0);
+/* --- @name__groups@ --- *
+ *
+ * Arguments:  ---
+ *
+ * Returns:    ---
+ *
+ * Use:                Adds users into all of their supplementary groups.
+ */
+
+static void name__groups(void)
+{
+  struct group *gr;
+  struct passwd *pw;
+  char **p;
+  char buf[32];
+
+  userdb_iterateGroups();
+  while ((gr = userdb_nextGroup()) != 0) {
+    name *n;
+
+    if (name__sanitise(gr->gr_name, buf, sizeof(buf)) &&
+       (n = name__get(buf, clType_user)) != 0) {
+
+      /* --- Now add all of the members --- */
+
+      for (p = gr->gr_mem; *p; p++) {
+       if ((pw = userdb_userByName(*p)) != 0)
+         n->c = class_addUser(n->c, pw->pw_uid);
       }
+      if (!n->c)
+       n->c = class_none;
     }
   }
+}
 
-  /* --- Now get the subsidiary groups --- */
+/* --- @name__scan@ --- *
+ *
+ * Arguments:  @netg *n@ = the netgroup handle we're scanning
+ *             @const char *host@ = the host name
+ *             @const char *user@ = the user name
+ *             @const char *domain@ = the (NIS?) domain name
+ *             @void *ctx@ = some context pointer
+ *
+ * Returns:    Zero to continue scanning.
+ *
+ * Use:                Scans a netgroup, adding items to the name table.
+ */
 
-  {
-    struct group *gr;
-    struct passwd *pw;
-    char **p;
-
-    userdb_iterateGroups();
-    while ((gr = userdb_nextGroup()) != 0) {
-      unsigned f;
-      name *n;
-      int u;
-
-      n = sym_find(&name__table, gr->gr_name, -1, sizeof(name), &f);
-      if (!f) {
-       sym_table *t = xmalloc(sizeof(*t));
-       sym_createTable(t);
-       n->c = class_create(clType_user, t);
+/* --- A data type --- */
+
+typedef struct name__scanctx {
+  char *name;                          /* Netgroup name prefixed with `?_'*/
+  unsigned f;                          /* Various interesting flags */
+  name *h;                             /* Name entry for hosts */
+  name *u;                             /* Name entry for users */
+} name__scanctx;
+
+enum { f_host = 1, f_user = 2 };
+
+/* --- And now for the real code --- */
+
+static int name__scan(netg *n, const char *host, const char *user,
+                     const char *domain, void *ctx)
+{
+  name__scanctx *sc = ctx;
+
+  /* --- Add the host to the hosts class --- */
+
+  if (sc->f & f_host && host) {
+    struct hostent *h;
+    struct in_addr in;
+    const char *a;
+
+    /* --- First ensure that I have a host class --- */
+
+    if (!sc->h) {
+      sc->name[0] = 'h';
+      sc->h = name__get(sc->name, clType_host);
+      if (!sc->h) {
+       sc->f &= ~f_host;
+       goto done_host;
       }
+    }
 
-      for (p = gr->gr_mem; *p; p++) {
-       if ((pw = userdb_userByName(*p)) != 0) {
-         u = pw->pw_uid;
-         sym_find(n->c->t, (char *)&u, sizeof(u), sizeof(sym_base), 0);
-       }
+    /* --- Now that I've done that, try to add the host --- *
+     *
+     * I'll turn it into an IP address.  There's less chance of confusion
+     * that way.
+     */
+
+    if ((h = gethostbyname(host)) == 0)
+      goto done_host;
+    memcpy(&in, h->h_addr, sizeof(in));
+    if ((a = inet_ntoa(in)) == 0)
+      goto done_host;
+    sc->h->c = class_addString(sc->h->c, a);
+  done_host:;
+  }
+
+  /* --- Add the user to the users class --- */
+
+  if (sc->f & f_user && user) {
+    struct passwd *pw;
+    
+    /* --- First ensure that I have a user class --- */
+
+    if (!sc->u) {
+      sc->name[0] = 'u';
+      sc->u = name__get(sc->name, clType_user);
+      if (!sc->u) {
+       sc->f &= ~f_user;
+       goto done_user;
       }
     }
+
+    /* --- Add the user to the list --- */
+
+    if ((pw = userdb_userByName(user)) == 0)
+      goto done_user;
+    sc->u->c = class_addUser(sc->u->c, pw->pw_uid);
+  done_user:;
   }
 
-  /* --- Finally add in the `all' class --- *
+  return (0);
+}
+
+/* --- @name__netgroups@ --- *
+ *
+ * Arguments:  ---
+ *
+ * Returns:    ---
+ *
+ * Use:                Populates the name table with netgroup information.
+ */
+
+void name__netgroups(void)
+{
+  netg *n;
+  char buf[32];
+  const char *p;
+  name__scanctx sc;
+
+  netg_iterate();
+  buf[1] = '_';
+  while ((n = netg_next()) != 0) {
+    p = netg_name(n);
+    if (name__sanitise(p, buf + 2, sizeof(buf) - 2) == 0)
+      continue;
+    sc.name = buf;
+    sc.u = sc.h = 0;
+    sc.f = f_host | f_user;
+    netg_scan(n, name__scan, &sc);
+  }
+}
+
+/* --- @name_init@ --- *
+ *
+ * Arguments:  ---
+ *
+ * Returns:    ---
+ *
+ * Use:                Initialises the name table.  Requires the user database to
+ *             be populated (see @userdb_local@ and @userdb_yp@, and
+ *             @netg_init@).
+ */
+
+void name_init(void)
+{
+  /* --- Initialise the name table --- */
+
+  sym_create(&name__table);
+
+  /* --- Add everyone into the table --- */
+
+  name__users();
+  name__groups();
+  name__netgroups();
+
+  /* --- Finally add in the `all' and `none' classes --- *
    *
-   * Do that now, to prevent it being overwritten by the above.
+   * Do that now, to prevent them being overwritten by the above.
    */
 
   {
@@ -156,21 +346,25 @@ void name_init(void)
     if (f)
       class_dec(n->c);
     n->c = class_all;
+
+    n = sym_find(&name__table, "none", -1, sizeof(name), &f);
+    if (f)
+      class_dec(n->c);
+    n->c = class_none;
   }
 }
 
-/* --- @name_reinit@ --- *
+/* --- @name_end@ --- *
  *
  * Arguments:  ---
  *
  * Returns:    ---
  *
- * Use:                Reinitialises the names table.  It's cleared and then
- *             initialised with the current user and group ids as for
- *             @name_init@ above.
+ * Use:                Closes down the name database, so that it can be
+ *             reinitialised.
  */
 
-void name_reinit(void)
+void name_end(void)
 {
   /* --- Empty the symbol table --- */
 
@@ -178,7 +372,7 @@ void name_reinit(void)
     sym_iter i;
     name *n;
 
-    for (sym_createIter(&i, &name__table); (n = sym_next(&i)) != 0; ) {
+    for (sym_mkiter(&i, &name__table); (n = sym_next(&i)) != 0; ) {
       if (n->c)
        class_dec(n->c);
     }
@@ -186,8 +380,7 @@ void name_reinit(void)
 
   /* --- Destroy and recreate the table --- */
 
-  sym_destroyTable(&name__table);
-  name_init();
+  sym_destroy(&name__table);
 }
 
 /* --- @name_find@ --- *
@@ -213,22 +406,28 @@ name *name_find(const char *p, unsigned create, unsigned *f)
 
 /* --- @name_dump@ --- *
  *
- * Arguments:  @FILE *fp@ = stream to dump on
+ * Arguments:  ---
  *
  * Returns:    ---
  *
  * Use:                Dumps a complete listing of the symbol table.
  */
 
-void name_dump(FILE *fp)
+void name_dump(void)
 {
+#ifdef TRACING
   sym_iter i;
   name *n;
 
-  for (sym_createIter(&i, &name__table); (n = sym_next(&i)) != 0; ) {
-    fprintf(fp, "\n--- name `%s'\n", n->base.name);
-    class_dump(n->c, fp);
+  trace(TRACE_DEBUG, "name: dumping names");
+  for (sym_mkiter(&i, &name__table); (n = sym_next(&i)) != 0; ) {
+    trace(TRACE_DEBUG, "name: dumping `%s'", n->base.name);
+    if (!n->c)
+      trace(TRACE_DEBUG, "name:   <empty>");
+    else
+      class_dump(n->c, 1);
   }
+#endif
 }  
 
 /*----- Test driver -------------------------------------------------------*/
@@ -237,11 +436,33 @@ void name_dump(FILE *fp)
 
 int main(void)
 {
+  ego("name-test");
+  trace_on(stdout, TRACE_ALL);
   userdb_init();
   userdb_local();
   userdb_yp();
+  netg_init();
   name_init();
-  name_dump(stdout);
+  /* printf("loaded (%lu)\n", track_memused()); */
+#ifdef notdef
+  getchar();
+  for (;;) {
+    name_end();
+    netg_end();
+    userdb_end();
+    /* printf("cleared (%lu)\n", track_memused()); */
+    /* track_memlist(); */
+    userdb_init();
+    userdb_local();
+    userdb_yp();
+    netg_init();
+    name_init();
+    /* printf("reloaded (%lu)\n", track_memused()); */
+    getchar();
+  }
+#else
+  name_dump();
+#endif
   return (0);
 }