/* -*-c-*-
*
- * $Id: name.c,v 1.1 1997/07/21 13:47:46 mdw Exp $
+ * $Id: name.c,v 1.4 1997/08/20 16:17:59 mdw Exp $
*
* Looking up of names in symbol tables
*
* (c) 1997 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.
+ * along with `become'; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*----- Revision history --------------------------------------------------*
*
* $Log: name.c,v $
- * Revision 1.1 1997/07/21 13:47:46 mdw
+ * Revision 1.4 1997/08/20 16:17:59 mdw
+ * Replace `name_reinit' by `name_end' for more sensible restart.
+ *
+ * Revision 1.3 1997/08/07 09:49:39 mdw
+ * Extensive modifications to handle netgroups. Also sanitise user and group
+ * names before adding them to the symbol table.
+ *
+ * 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
*
*/
/* --- 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>
/* --- Local headers --- */
+#include "config.h"
+
+#include "become.h"
#include "class.h"
#include "name.h"
+#include "netg.h"
#include "sym.h"
#include "userdb.h"
#include "utils.h"
/*----- Main code ---------------------------------------------------------*/
-/* --- @name_init@ --- *
+/* --- @name__get@ --- *
*
- * Arguments: ---
+ * Arguments: @const char *p@ = pointer to the name we want
+ * @unsigned type@ = type of class it should have
*
- * Returns: ---
+ * Returns: A pointer to a name ready to use, or zero if there's a type
+ * conflict.
*
- * Use: Initialises the name table. Requires the user database to
- * be populated (see @userdb_local@ and @userdb_yp@).
+ * Use: Creates a name of the appropriate type all ready to use.
*/
-void name_init(void)
+static name *name__get(const char *p, unsigned type)
{
- /* --- Initialise the name table --- */
+ unsigned f;
+ name *n = sym_find(&name__table, p, -1, sizeof(*n), &f);
+ if (!f) {
+ sym_table *t = xmalloc(sizeof(*t));
+ sym_createTable(t);
+ n->c = class_create(type, t);
+ }
+ return (n->c->type == type ? n : 0);
+}
- sym_createTable(&name__table);
+/* --- @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.
+ */
- /* --- Insert all the users and groups into the table --- */
+static char *name__sanitise(const char *n, char *buf, size_t sz)
+{
+ char *p = buf;
- {
- struct passwd *pw;
- struct group *gr;
+ 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: Adds all of the users registered with the user database to
+ * the name table. Also adds the users' primary groups.
+ */
+
+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;
+ userdb_iterateUsers();
+ while ((pw = userdb_nextUser()) != 0) {
+ name *n;
+ int u = pw->pw_uid;
- /* --- First, add the user to the table --- */
+ /* --- 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;
+ if (name__sanitise(pw->pw_name, buf, sizeof(buf)) &&
+ (n = name__get(buf, clType_user)) != 0)
sym_find(n->c->t, (char *)&u, sizeof(u), sizeof(sym_base), 0);
- /* --- Now handle the user's default group --- */
+ /* --- 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)
+ 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.
+ */
- /* --- Now get the subsidiary groups --- */
+static void name__groups(void)
+{
+ struct group *gr;
+ struct passwd *pw;
+ char **p;
+ char buf[32];
- {
- 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);
- }
+ userdb_iterateGroups();
+ while ((gr = userdb_nextGroup()) != 0) {
+ name *n;
+ int u;
+
+ 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) {
}
}
}
+}
+
+/* --- @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;
+
+ /* --- 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 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;
+ sym_find(sc->h->c->t, a, -1, sizeof(sym_base), 0);
+ done_host:;
+ }
+
+ /* --- Add the user to the users class --- */
+
+ if (sc->f & f_user && user) {
+ struct passwd *pw;
+ int u;
+
+ /* --- 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;
+ u = pw->pw_uid;
+ sym_find(sc->u->c->t, (char *)&u, sizeof(u), sizeof(sym_base), 0);
+ 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);
+ }
+}
+
+/* --- @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_createTable(&name__table);
+
+ /* --- Add everyone into the table --- */
+
+ name__users();
+ name__groups();
+ name__netgroups();
/* --- Finally add in the `all' class --- *
*
}
}
-/* --- @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 --- */
/* --- Destroy and recreate the table --- */
sym_destroyTable(&name__table);
- name_init();
}
/* --- @name_find@ --- *
/* --- @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;
+ trace(TRACE_DEBUG, "name: dumping names");
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 `%s'", n->base.name);
+ class_dump(n->c);
}
+#endif
}
/*----- Test driver -------------------------------------------------------*/
int main(void)
{
+ ego("name-test");
+ /* traceon(stdout, TRACE_ALL); */
userdb_init();
userdb_local();
userdb_yp();
+ netg_init();
name_init();
- name_dump(stdout);
+ printf("loaded (%lu)\n", track_memused());
+ 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();
+ }
return (0);
}