Expunge revision histories in files.
[become] / src / name.c
index fe61272..1ea34a0 100644 (file)
@@ -1,10 +1,10 @@
 /* -*-c-*-
  *
- * $Id: name.c,v 1.2 1997/08/04 10:24:24 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
  */
 
 /*----- Licensing notice --------------------------------------------------*
  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 
-/*----- Revision history --------------------------------------------------*
- *
- * $Log: name.c,v $
- * Revision 1.2  1997/08/04 10:24:24  mdw
- * Sources placed under CVS control.
- *
- * Revision 1.1  1997/07/21  13:47:46  mdw
- * Initial revision
- *
- */
-
 /*----- Header files ------------------------------------------------------*/
 
 /* --- ANSI headers --- */
 
+#include <ctype.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
 /* --- Unix headers --- */
 
-#include "config.h"
+#include <sys/types.h>
+#include <sys/socket.h>
 
-#ifdef HAVE_YP
-#  include <rpcsvc/ypclnt.h>
-#  include <rpcsvc/yp_prot.h>
-#endif
+#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 --------------------------------------------------*/
 
@@ -72,6 +69,56 @@ static sym_table name__table;                /* Symbol table for everything */
 
 /*----- Main code ---------------------------------------------------------*/
 
+/* --- @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:  ---
@@ -86,35 +133,25 @@ static void name__users(void)
 {
   struct passwd *pw;
   struct group *gr;
+  char buf[32];
 
   userdb_iterateUsers();
   while ((pw = userdb_nextUser()) != 0) {
-    unsigned f;
     name *n;
-    int u;
+    uid_t u = pw->pw_uid;
 
     /* --- First, add the user to the table --- */
 
-    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);
+    if (name__sanitise(pw->pw_name, buf, sizeof(buf)) &&
+       (n = name__get(buf, clType_user)) != 0)
+      n->c = class_addUser(n->c, u);
 
     /* --- 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);
-    }
+    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);
   }
 }
 
@@ -132,30 +169,144 @@ static void name__groups(void)
   struct group *gr;
   struct passwd *pw;
   char **p;
+  char buf[32];
 
   userdb_iterateGroups();
   while ((gr = userdb_nextGroup()) != 0) {
-    unsigned f;
     name *n;
-    int u;
 
-    /* --- Add the group name to the table --- */
+    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;
+    }
+  }
+}
+
+/* --- @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.
+ */
+
+/* --- 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;
 
-    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);
+  /* --- 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;
+      }
     }
 
-    /* --- Now add all of the members --- */
+    /* --- 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 --- */
 
-    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);
+    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:;
+  }
+
+  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);
   }
 }
 
@@ -166,23 +317,25 @@ static void name__groups(void)
  * Returns:    ---
  *
  * Use:                Initialises the name table.  Requires the user database to
- *             be populated (see @userdb_local@ and @userdb_yp@).
+ *             be populated (see @userdb_local@ and @userdb_yp@, and
+ *             @netg_init@).
  */
 
 void name_init(void)
 {
   /* --- Initialise the name table --- */
 
-  sym_createTable(&name__table);
+  sym_create(&name__table);
 
   /* --- Add everyone into the table --- */
 
   name__users();
   name__groups();
+  name__netgroups();
 
-  /* --- Finally add in the `all' class --- *
+  /* --- 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.
    */
 
   {
@@ -193,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 --- */
 
@@ -215,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);
     }
@@ -223,8 +380,7 @@ void name_reinit(void)
 
   /* --- Destroy and recreate the table --- */
 
-  sym_destroyTable(&name__table);
-  name_init();
+  sym_destroy(&name__table);
 }
 
 /* --- @name_find@ --- *
@@ -259,14 +415,19 @@ name *name_find(const char *p, unsigned create, unsigned *f)
 
 void name_dump(void)
 {
+#ifdef TRACING
   sym_iter i;
   name *n;
 
   trace(TRACE_DEBUG, "name: dumping names");
-  for (sym_createIter(&i, &name__table); (n = sym_next(&i)) != 0; ) {
+  for (sym_mkiter(&i, &name__table); (n = sym_next(&i)) != 0; ) {
     trace(TRACE_DEBUG, "name: dumping `%s'", n->base.name);
-    class_dump(n->c);
+    if (!n->c)
+      trace(TRACE_DEBUG, "name:   <empty>");
+    else
+      class_dump(n->c, 1);
   }
+#endif
 }  
 
 /*----- Test driver -------------------------------------------------------*/
@@ -275,13 +436,33 @@ void name_dump(void)
 
 int main(void)
 {
+  ego("name-test");
+  trace_on(stdout, TRACE_ALL);
   userdb_init();
   userdb_local();
   userdb_yp();
-  ego("name-test");
-  traceon(stdout, TRACE_DEBUG);
+  netg_init();
   name_init();
+  /* 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);
 }