summaryrefslogtreecommitdiff
path: root/Src/hashnameddir.c
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2011-05-09 10:38:02 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2011-05-09 10:38:02 +0000
commitbafa15955d1c0c9e892615afa7fff2476302c7a5 (patch)
tree1c80c56af719d08d25d3fd52dadf7b654c351403 /Src/hashnameddir.c
parentae4a0ab46cbd2c6db916b702f05436b492a72d4d (diff)
downloadzsh-bafa15955d1c0c9e892615afa7fff2476302c7a5.tar.gz
zsh-bafa15955d1c0c9e892615afa7fff2476302c7a5.zip
29195: Separate nameddir hash to avoid clash of
"bool" type on Solaris
Diffstat (limited to 'Src/hashnameddir.c')
-rw-r--r--Src/hashnameddir.c307
1 files changed, 307 insertions, 0 deletions
diff --git a/Src/hashnameddir.c b/Src/hashnameddir.c
new file mode 100644
index 000000000..bed43d025
--- /dev/null
+++ b/Src/hashnameddir.c
@@ -0,0 +1,307 @@
+/*
+ * hashtable.c - hash tables
+ *
+ * This file is part of zsh, the Z shell.
+ *
+ * Copyright (c) 1992-1997 Paul Falstad
+ * All rights reserved.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and to distribute modified versions of this software for any
+ * purpose, provided that the above copyright notice and the following
+ * two paragraphs appear in all copies of this software.
+ *
+ * In no event shall Paul Falstad or the Zsh Development Group be liable
+ * to any party for direct, indirect, special, incidental, or consequential
+ * damages arising out of the use of this software and its documentation,
+ * even if Paul Falstad and the Zsh Development Group have been advised of
+ * the possibility of such damage.
+ *
+ * Paul Falstad and the Zsh Development Group specifically disclaim any
+ * warranties, including, but not limited to, the implied warranties of
+ * merchantability and fitness for a particular purpose. The software
+ * provided hereunder is on an "as is" basis, and Paul Falstad and the
+ * Zsh Development Group have no obligation to provide maintenance,
+ * support, updates, enhancements, or modifications.
+ *
+ */
+
+#include "../config.h"
+
+/*
+ * On Solaris 8 there's a clash between "bool" in curses and RPC.
+ * We don't need curses here, so ensure it doesn't get included.
+ */
+#define ZSH_NO_TERM_HANDLING
+
+#include "zsh.mdh"
+#include "hashnameddir.pro"
+
+/****************************************/
+/* Named Directory Hash Table Functions */
+/****************************************/
+
+#ifdef HAVE_NIS_PLUS
+# include <rpcsvc/nis.h>
+#else
+# ifdef HAVE_NIS
+# include <rpc/types.h>
+# include <rpc/rpc.h>
+# include <rpcsvc/ypclnt.h>
+# include <rpcsvc/yp_prot.h>
+# endif
+#endif
+
+/* hash table containing named directories */
+
+/**/
+mod_export HashTable nameddirtab;
+
+/* != 0 if all the usernames have already been *
+ * added to the named directory hash table. */
+
+static int allusersadded;
+
+/* Create new hash table for named directories */
+
+/**/
+void
+createnameddirtable(void)
+{
+ nameddirtab = newhashtable(201, "nameddirtab", NULL);
+
+ nameddirtab->hash = hasher;
+ nameddirtab->emptytable = emptynameddirtable;
+ nameddirtab->filltable = fillnameddirtable;
+ nameddirtab->cmpnodes = strcmp;
+ nameddirtab->addnode = addnameddirnode;
+ nameddirtab->getnode = gethashnode;
+ nameddirtab->getnode2 = gethashnode2;
+ nameddirtab->removenode = removenameddirnode;
+ nameddirtab->disablenode = NULL;
+ nameddirtab->enablenode = NULL;
+ nameddirtab->freenode = freenameddirnode;
+ nameddirtab->printnode = printnameddirnode;
+
+ allusersadded = 0;
+ finddir(NULL); /* clear the finddir cache */
+}
+
+/* Empty the named directories table */
+
+/**/
+static void
+emptynameddirtable(HashTable ht)
+{
+ emptyhashtable(ht);
+ allusersadded = 0;
+ finddir(NULL); /* clear the finddir cache */
+}
+
+/* Add all the usernames in the password file/database *
+ * to the named directories table. */
+
+#ifdef HAVE_NIS_PLUS
+static int
+add_userdir(nis_name table, nis_object *object, void *userdata)
+{
+ if (object->zo_data.objdata_u.en_data.en_cols.en_cols_len >= 6) {
+ static char name[40], dir[PATH_MAX + 1];
+ register entry_col *ec =
+ object->zo_data.objdata_u.en_data.en_cols.en_cols_val;
+ register int nl = minimum(ec[0].ec_value.ec_value_len, 39);
+ register int dl = minimum(ec[5].ec_value.ec_value_len, PATH_MAX);
+
+ memcpy(name, ec[0].ec_value.ec_value_val, nl);
+ name[nl] = '\0';
+ memcpy(dir, ec[5].ec_value.ec_value_val, dl);
+ dir[dl] = '\0';
+
+ adduserdir(name, dir, ND_USERNAME, 1);
+ }
+ return 0;
+}
+#else
+# ifdef HAVE_NIS
+static int
+add_userdir(int status, char *key, int keylen, char *val, int vallen, char *dummy)
+{
+ char *p, *d, *de;
+
+ if (status != YP_TRUE)
+ return 1;
+
+ if (vallen > keylen && *(p = val + keylen) == ':') {
+ *p++ = '\0';
+ for (de = val + vallen - 1; *de != ':' && de > val; de--);
+ if (de > val) {
+ *de = '\0';
+ if ((d = strrchr(p, ':'))) {
+ if (*++d && val[0])
+ adduserdir(val, d, ND_USERNAME, 1);
+ }
+ }
+ }
+ return 0;
+}
+# endif /* HAVE_NIS */
+#endif /* HAVE_NIS_PLUS */
+
+/**/
+static void
+fillnameddirtable(UNUSED(HashTable ht))
+{
+ if (!allusersadded) {
+#if defined(HAVE_NIS) || defined(HAVE_NIS_PLUS)
+ FILE *pwf;
+ char buf[BUFSIZ], *p, *d, *de;
+ int skipping, oldct = nameddirtab->ct, usepwf = 1;
+
+# ifndef HAVE_NIS_PLUS
+ char domain[YPMAXDOMAIN];
+ struct ypall_callback cb;
+
+ /* Get potential matches from NIS and cull those without local accounts */
+ if (getdomainname(domain, YPMAXDOMAIN) == 0) {
+ cb.foreach = (int (*)()) add_userdir;
+ cb.data = NULL;
+ yp_all(domain, PASSWD_MAP, &cb);
+ }
+# else /* HAVE_NIS_PLUS */
+ /* Maybe we should turn this string into a #define'd constant...? */
+
+ nis_list("passwd.org_dir", EXPAND_NAME|ALL_RESULTS|FOLLOW_LINKS|FOLLOW_PATH,
+ add_userdir, 0);
+# endif
+ if (nameddirtab->ct == oldct) {
+ /* Using NIS or NIS+ didn't add any user directories. This seems
+ * fishy, so we fall back to using getpwent(). If we don't have
+ * that, we only use the passwd file. */
+#ifdef HAVE_GETPWENT
+ struct passwd *pw;
+
+ setpwent();
+
+ /* loop through the password file/database *
+ * and add all entries returned. */
+ while ((pw = getpwent()) && !errflag)
+ adduserdir(pw->pw_name, pw->pw_dir, ND_USERNAME, 1);
+
+ endpwent();
+ usepwf = 0;
+#endif /* HAVE_GETPWENT */
+ }
+ if (usepwf) {
+ /* Don't forget the non-NIS matches from the flat passwd file */
+ if ((pwf = fopen(PASSWD_FILE, "r")) != NULL) {
+ skipping = 0;
+ while (fgets(buf, BUFSIZ, pwf) != NULL) {
+ if (strchr(buf, '\n') != NULL) {
+ if (!skipping) {
+ if ((p = strchr(buf, ':')) != NULL) {
+ *p++ = '\0';
+ if ((de = strrchr(p, ':'))) {
+ *de = '\0';
+ if ((d = strrchr(p, ':'))) {
+ if (*++d && buf[0])
+ adduserdir(buf, d, ND_USERNAME, 1);
+ }
+ }
+ }
+ } else
+ skipping = 0;
+ } else
+ skipping = 1;
+ }
+ fclose(pwf);
+ }
+ }
+#else /* no NIS or NIS_PLUS */
+#ifdef USE_GETPWENT
+ struct passwd *pw;
+
+ setpwent();
+
+ /* loop through the password file/database *
+ * and add all entries returned. */
+ while ((pw = getpwent()) && !errflag)
+ adduserdir(pw->pw_name, pw->pw_dir, ND_USERNAME, 1);
+
+ endpwent();
+#endif /* HAVE_GETPWENT */
+#endif
+ allusersadded = 1;
+ }
+}
+
+/* Add an entry to the named directory hash *
+ * table, clearing the finddir() cache and *
+ * initialising the `diff' member. */
+
+/**/
+static void
+addnameddirnode(HashTable ht, char *nam, void *nodeptr)
+{
+ Nameddir nd = (Nameddir) nodeptr;
+
+ nd->diff = strlen(nd->dir) - strlen(nam);
+ finddir(NULL); /* clear the finddir cache */
+ addhashnode(ht, nam, nodeptr);
+}
+
+/* Remove an entry from the named directory *
+ * hash table, clearing the finddir() cache. */
+
+/**/
+static HashNode
+removenameddirnode(HashTable ht, const char *nam)
+{
+ HashNode hn = removehashnode(ht, nam);
+
+ if(hn)
+ finddir(NULL); /* clear the finddir cache */
+ return hn;
+}
+
+/* Free up the memory used by a named directory hash node. */
+
+/**/
+static void
+freenameddirnode(HashNode hn)
+{
+ Nameddir nd = (Nameddir) hn;
+
+ zsfree(nd->node.nam);
+ zsfree(nd->dir);
+ zfree(nd, sizeof(struct nameddir));
+}
+
+/* Print a named directory */
+
+/**/
+static void
+printnameddirnode(HashNode hn, int printflags)
+{
+ Nameddir nd = (Nameddir) hn;
+
+ if (printflags & PRINT_NAMEONLY) {
+ zputs(nd->node.nam, stdout);
+ putchar('\n');
+ return;
+ }
+
+ if (printflags & PRINT_LIST) {
+ printf("hash -d ");
+
+ if(nd->node.nam[0] == '-')
+ printf("-- ");
+ }
+
+ quotedzputs(nd->node.nam, stdout);
+ putchar('=');
+ quotedzputs(nd->dir, stdout);
+ putchar('\n');
+}
+
+#include "../config.h"