summaryrefslogtreecommitdiff
path: root/hesiod
diff options
context:
space:
mode:
Diffstat (limited to 'hesiod')
-rw-r--r--hesiod/Makefile49
-rw-r--r--hesiod/hesiod.c470
-rw-r--r--hesiod/hesiod.h73
-rw-r--r--hesiod/hesiod_p.h41
-rw-r--r--hesiod/libnss_hesiod.map12
-rw-r--r--hesiod/nss_hesiod/hesiod-grp.c150
-rw-r--r--hesiod/nss_hesiod/hesiod-pwd.c150
-rw-r--r--hesiod/nss_hesiod/hesiod-service.c165
8 files changed, 1110 insertions, 0 deletions
diff --git a/hesiod/Makefile b/hesiod/Makefile
new file mode 100644
index 0000000000..8d0363b50d
--- /dev/null
+++ b/hesiod/Makefile
@@ -0,0 +1,49 @@
+# Copyright (C) 1997 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Library General Public License for more details.
+
+# You should have received a copy of the GNU Library General Public
+# License along with the GNU C Library; see the file COPYING.LIB. If not,
+# write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+#
+# Sub-makefile for hesiod portion of the library.
+#
+subdir := hesiod
+
+distribute := hesiod.h hesiod_p.h
+
+extra-libs := libnss_hesiod
+extra-libs-others = $(extra-libs)
+
+subdir-dirs = nss_hesiod
+vpath %.c nss_hesiod
+
+libnss_hesiod-routines := hesiod hesiod-grp hesiod-pwd hesiod-service
+libnss_hesiod-map := libnss_hesiod.map
+ifneq ($(build-static-nss),yes)
+libnss_hesiod-inhibit-o = $(filter-out .os,$(object-suffixes))
+endif
+
+include ../Rules
+
+CFLAGS-hesiod.c = -DSYSCONFDIR='"$(sysconfdir)"'
+
+# Depend on libc.so so a DT_NEEDED is generated in the shared objects.
+# This ensures they will load libc.so for needed symbols if loaded by
+# a statically-linked program that hasn't already loaded it.
+# The Hesiod NSS modules also needs the resolver and some help from
+# the file service.
+$(objpfx)libnss_hesiod.so: $(common-objpfx)resolv/libresolv.so \
+ $(common-objpfx)nss/libnss_files.so \
+ $(common-objpfx)libc.so
diff --git a/hesiod/hesiod.c b/hesiod/hesiod.c
new file mode 100644
index 0000000000..8e95dfb393
--- /dev/null
+++ b/hesiod/hesiod.c
@@ -0,0 +1,470 @@
+/* Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/* Copyright 1996 by the Massachusetts Institute of Technology.
+ *
+ * Permission to use, copy, modify, and distribute this
+ * software and its documentation for any purpose and without
+ * fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting
+ * documentation, and that the name of M.I.T. not be used in
+ * advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ */
+
+/* This file is part of the hesiod library. It implements the core
+ * portion of the hesiod resolver.
+ *
+ * This file is loosely based on an interim version of hesiod.c from
+ * the BIND IRS library, which was in turn based on an earlier version
+ * of this file. Extensive changes have been made on each step of the
+ * path.
+ *
+ * This implementation is not truly thread-safe at the moment because
+ * it uses res_send() and accesses _res.
+ */
+
+static const char rcsid[] = "$Id$";
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <errno.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "hesiod.h"
+#include "hesiod_p.h"
+
+/* A few operating systems don't define these. */
+#ifndef C_HS
+#define C_HS 4
+#endif
+#ifndef T_TXT
+#define T_TXT 16
+#endif
+
+static int read_config_file(struct hesiod_p *ctx, const char *filename);
+static char **get_txt_records(struct hesiod_p *ctx, int class,
+ const char *name);
+static int cistrcmp(const char *s1, const char *s2);
+
+/* This function is called to initialize a hesiod_p. */
+int hesiod_init(void **context)
+{
+ struct hesiod_p *ctx;
+ const char *p, *configname;
+
+ ctx = malloc(sizeof(struct hesiod_p));
+ if (ctx)
+ {
+ *context = ctx;
+ configname = __secure_getenv("HESIOD_CONFIG");
+ if (!configname)
+ configname = SYSCONFDIR "/hesiod.conf";
+ if (read_config_file(ctx, configname) >= 0)
+ {
+ /* The default rhs can be overridden by an environment variable. */
+ p = __secure_getenv("HES_DOMAIN");
+ if (p)
+ {
+ if (ctx->rhs)
+ free(ctx->rhs);
+ ctx->rhs = malloc(strlen(p) + 2);
+ if (ctx->rhs)
+ {
+ *ctx->rhs = '.';
+ strcpy(ctx->rhs + 1, (*p == '.') ? p + 1 : p);
+ return 0;
+ }
+ else
+ __set_errno (ENOMEM);
+ }
+ else
+ return 0;
+ }
+ }
+ else
+ __set_errno (ENOMEM);
+
+ if (ctx->lhs)
+ free(ctx->lhs);
+ if (ctx->rhs)
+ free(ctx->rhs);
+ if (ctx)
+ free(ctx);
+ return -1;
+}
+
+/* This function deallocates the hesiod_p. */
+void hesiod_end(void *context)
+{
+ struct hesiod_p *ctx = (struct hesiod_p *) context;
+
+ free(ctx->rhs);
+ if (ctx->lhs)
+ free(ctx->lhs);
+ free(ctx);
+}
+
+/* This function takes a hesiod (name, type) and returns a DNS
+ * name which is to be resolved.
+ */
+char *hesiod_to_bind(void *context, const char *name, const char *type)
+{
+ struct hesiod_p *ctx = (struct hesiod_p *) context;
+ char bindname[MAXDNAME], *p, *ret, **rhs_list = NULL;
+ const char *rhs;
+ int len;
+
+ strcpy(bindname, name);
+
+ /* Find the right right hand side to use, possibly truncating bindname. */
+ p = strchr(bindname, '@');
+ if (p)
+ {
+ *p++ = 0;
+ if (strchr(p, '.'))
+ rhs = name + (p - bindname);
+ else
+ {
+ rhs_list = hesiod_resolve(context, p, "rhs-extension");
+ if (rhs_list)
+ rhs = *rhs_list;
+ else
+ {
+ __set_errno (ENOENT);
+ return NULL;
+ }
+ }
+ } else
+ rhs = ctx->rhs;
+
+ /* See if we have enough room. */
+ len = strlen(bindname) + 1 + strlen(type);
+ if (ctx->lhs)
+ len += strlen(ctx->lhs) + ((ctx->lhs[0] != '.') ? 1 : 0);
+ len += strlen(rhs) + ((rhs[0] != '.') ? 1 : 0);
+ if (len > sizeof(bindname) - 1)
+ {
+ if (rhs_list)
+ hesiod_free_list(context, rhs_list);
+ __set_errno (EMSGSIZE);
+ return NULL;
+ }
+
+ /* Put together the rest of the domain. */
+ strcat(bindname, ".");
+ strcat(bindname, type);
+ if (ctx->lhs)
+ {
+ if (ctx->lhs[0] != '.')
+ strcat(bindname, ".");
+ strcat(bindname, ctx->lhs);
+ }
+ if (rhs[0] != '.')
+ strcat(bindname, ".");
+ strcat(bindname, rhs);
+
+ /* rhs_list is no longer needed, since we're done with rhs. */
+ if (rhs_list)
+ hesiod_free_list(context, rhs_list);
+
+ /* Make a copy of the result and return it to the caller. */
+ ret = malloc(strlen(bindname) + 1);
+ if (!ret)
+ {
+ __set_errno (ENOMEM);
+ return NULL;
+ }
+ strcpy(ret, bindname);
+ return ret;
+}
+
+/* This is the core function. Given a hesiod name and type, it
+ * returns an array of strings returned by the resolver.
+ */
+char **hesiod_resolve(void *context, const char *name, const char *type)
+{
+ struct hesiod_p *ctx = (struct hesiod_p *) context;
+ char *bindname, **retvec;
+
+ bindname = hesiod_to_bind(context, name, type);
+ if (!bindname)
+ return NULL;
+
+ retvec = get_txt_records(ctx, ctx->classes[0], bindname);
+ if (retvec == NULL && errno == ENOENT && ctx->classes[1])
+ retvec = get_txt_records(ctx, ctx->classes[1], bindname);
+
+ free(bindname);
+ return retvec;
+}
+
+void hesiod_free_list(void *context, char **list)
+{
+ char **p;
+
+ for (p = list; *p; p++)
+ free(*p);
+ free(list);
+}
+
+/* This function parses the /etc/hesiod.conf file. Returns 0 on success,
+ * -1 on failure. On failure, it might leave values in ctx->lhs or
+ * ctx->rhs which need to be freed by the caller. */
+static int read_config_file(struct hesiod_p *ctx, const char *filename)
+{
+ char *key, *data, *p, **which;
+ char buf[MAXDNAME + 7];
+ int n;
+ FILE *fp;
+
+ /* Set default query classes. */
+ ctx->classes[0] = C_IN;
+ ctx->classes[1] = C_HS;
+
+ /* Try to open the configuration file. */
+ fp = fopen(filename, "r");
+ if (!fp)
+ {
+ /* Use compiled in default domain names. */
+ ctx->lhs = malloc(strlen(DEF_LHS) + 1);
+ ctx->rhs = malloc(strlen(DEF_RHS) + 1);
+ if (ctx->lhs && ctx->rhs)
+ {
+ strcpy(ctx->lhs, DEF_LHS);
+ strcpy(ctx->rhs, DEF_RHS);
+ return 0;
+ }
+ else
+ {
+ __set_errno (ENOMEM);
+ return -1;
+ }
+ }
+
+ ctx->lhs = NULL;
+ ctx->rhs = NULL;
+ while (fgets(buf, sizeof(buf), fp) != NULL)
+ {
+ p = buf;
+ if (*p == '#' || *p == '\n' || *p == '\r')
+ continue;
+ while(*p == ' ' || *p == '\t')
+ p++;
+ key = p;
+ while(*p != ' ' && *p != '\t' && *p != '=')
+ p++;
+ *p++ = 0;
+
+ while(isspace(*p) || *p == '=')
+ p++;
+ data = p;
+ while(!isspace(*p))
+ p++;
+ *p = 0;
+
+ if (cistrcmp(key, "lhs") == 0 || cistrcmp(key, "rhs") == 0)
+ {
+ which = (strcmp(key, "lhs") == 0) ? &ctx->lhs : &ctx->rhs;
+ *which = malloc(strlen(data) + 1);
+ if (!*which)
+ {
+ __set_errno (ENOMEM);
+ return -1;
+ }
+ strcpy(*which, data);
+ }
+ else if (cistrcmp(key, "classes") == 0)
+ {
+ n = 0;
+ while (*data && n < 2)
+ {
+ p = data;
+ while (*p && *p != ',')
+ p++;
+ if (*p)
+ *p++ = 0;
+ if (cistrcmp(data, "IN") == 0)
+ ctx->classes[n++] = C_IN;
+ else if (cistrcmp(data, "HS") == 0)
+ ctx->classes[n++] = C_HS;
+ data = p;
+ }
+ while (n < 2)
+ ctx->classes[n++] = 0;
+ }
+ }
+ fclose(fp);
+
+ if (!ctx->rhs || ctx->classes[0] == 0 || ctx->classes[0] == ctx->classes[1])
+ {
+ __set_errno (ENOEXEC);
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Given a DNS class and a DNS name, do a lookup for TXT records, and
+ * return a list of them.
+ */
+static char **get_txt_records(struct hesiod_p *ctx, int qclass,
+ const char *name)
+{
+ HEADER *hp;
+ unsigned char qbuf[PACKETSZ], abuf[MAX_HESRESP], *p, *eom, *eor;
+ char *dst, **list;
+ int ancount, qdcount, i, j, n, skip, type, class, len;
+
+ /* Make sure the resolver is initialized. */
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1)
+ return NULL;
+
+ /* Construct the query. */
+ n = res_mkquery(QUERY, name, qclass, T_TXT, NULL, 0,
+ NULL, qbuf, PACKETSZ);
+ if (n < 0)
+ return NULL;
+
+ /* Send the query. */
+ n = res_send(qbuf, n, abuf, MAX_HESRESP);
+ if (n < 0)
+ {
+ __set_errno (ECONNREFUSED);
+ return NULL;
+ }
+
+ /* Parse the header of the result. */
+ hp = (HEADER *) abuf;
+ ancount = ntohs(hp->ancount);
+ qdcount = ntohs(hp->qdcount);
+ p = abuf + sizeof(HEADER);
+ eom = abuf + n;
+
+ /* Skip questions, trying to get to the answer section which follows. */
+ for (i = 0; i < qdcount; i++)
+ {
+ skip = dn_skipname(p, eom);
+ if (skip < 0 || p + skip + QFIXEDSZ > eom)
+ {
+ __set_errno (EMSGSIZE);
+ return NULL;
+ }
+ p += skip + QFIXEDSZ;
+ }
+
+ /* Allocate space for the text record answers. */
+ list = malloc((ancount + 1) * sizeof(char *));
+ if (!list)
+ {
+ __set_errno (ENOMEM);
+ return NULL;
+ }
+
+ /* Parse the answers. */
+ j = 0;
+ for (i = 0; i < ancount; i++)
+ {
+ /* Parse the header of this answer. */
+ skip = dn_skipname(p, eom);
+ if (skip < 0 || p + skip + 10 > eom)
+ break;
+ type = p[skip + 0] << 8 | p[skip + 1];
+ class = p[skip + 2] << 8 | p[skip + 3];
+ len = p[skip + 8] << 8 | p[skip + 9];
+ p += skip + 10;
+ if (p + len > eom)
+ {
+ __set_errno (EMSGSIZE);
+ break;
+ }
+
+ /* Skip entries of the wrong class and type. */
+ if (class != qclass || type != T_TXT)
+ {
+ p += len;
+ continue;
+ }
+
+ /* Allocate space for this answer. */
+ list[j] = malloc(len);
+ if (!list[j])
+ {
+ __set_errno (ENOMEM);
+ break;
+ }
+ dst = list[j++];
+
+ /* Copy answer data into the allocated area. */
+ eor = p + len;
+ while (p < eor)
+ {
+ n = (unsigned char) *p++;
+ if (p + n > eor)
+ {
+ __set_errno (EMSGSIZE);
+ break;
+ }
+ memcpy(dst, p, n);
+ p += n;
+ dst += n;
+ }
+ if (p < eor)
+ {
+ __set_errno (EMSGSIZE);
+ break;
+ }
+ *dst = 0;
+ }
+
+ /* If we didn't terminate the loop normally, something went wrong. */
+ if (i < ancount)
+ {
+ for (i = 0; i < j; i++)
+ free(list[i]);
+ free(list);
+ return NULL;
+ }
+
+ if (j == 0)
+ {
+ __set_errno (ENOENT);
+ free(list);
+ return NULL;
+ }
+
+ list[j] = NULL;
+ return list;
+}
+
+static int cistrcmp(const char *s1, const char *s2)
+{
+ while (*s1 && tolower(*s1) == tolower(*s2))
+ {
+ s1++;
+ s2++;
+ }
+ return tolower(*s1) - tolower(*s2);
+}
diff --git a/hesiod/hesiod.h b/hesiod/hesiod.h
new file mode 100644
index 0000000000..9c3d323811
--- /dev/null
+++ b/hesiod/hesiod.h
@@ -0,0 +1,73 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#ifndef HESIOD__INCLUDED
+#define HESIOD__INCLUDED
+
+#include <sys/types.h>
+#include <pwd.h>
+#include <netdb.h>
+
+/* Application-visible define to signal that we have the new interfaces. */
+#define HESIOD_INTERFACES
+
+struct hesiod_postoffice {
+ char *hesiod_po_type;
+ char *hesiod_po_host;
+ char *hesiod_po_name;
+};
+
+int hesiod_init(void **context);
+void hesiod_end(void *context);
+char *hesiod_to_bind(void *context, const char *name, const char *type);
+char **hesiod_resolve(void *context, const char *name, const char *type);
+void hesiod_free_list(void *context, char **list);
+struct passwd *hesiod_getpwnam(void *context, const char *name);
+struct passwd *hesiod_getpwuid(void *context, uid_t uid);
+void hesiod_free_passwd(void *context, struct passwd *pw);
+struct servent *hesiod_getservbyname(void *context, const char *name,
+ const char *proto);
+void hesiod_free_servent(void *context, struct servent *serv);
+struct hesiod_postoffice *hesiod_getmailhost(void *context, const char *user);
+void hesiod_free_postoffice(void *context, struct hesiod_postoffice *po);
+
+/* Compatibility stuff. */
+
+#define HES_ER_UNINIT -1 /* uninitialized */
+#define HES_ER_OK 0 /* no error */
+#define HES_ER_NOTFOUND 1 /* Hesiod name not found by server */
+#define HES_ER_CONFIG 2 /* local problem (no config file?) */
+#define HES_ER_NET 3 /* network problem */
+
+struct hes_postoffice {
+ char *po_type;
+ char *po_host;
+ char *po_name;
+};
+
+int hes_init(void);
+char *hes_to_bind(const char *name, const char *type);
+char **hes_resolve(const char *name, const char *type);
+int hes_error(void);
+struct passwd *hes_getpwnam(const char *name);
+struct passwd *hes_getpwuid(uid_t uid);
+struct servent *hes_getservbyname(const char *name, const char *proto);
+struct hes_postoffice *hes_getmailhost(const char *name);
+
+#endif
diff --git a/hesiod/hesiod_p.h b/hesiod/hesiod_p.h
new file mode 100644
index 0000000000..809916ac2b
--- /dev/null
+++ b/hesiod/hesiod_p.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+ * $Id$
+ */
+
+/*
+ * hesiod_p.h -- private definitions for the hesiod library
+ */
+
+#ifndef HESIOD_P_H_INCLUDED
+#define HESIOD_P_H_INCLUDED
+
+/* Defaults if the configuration file is not present. */
+#define DEF_RHS ".athena.mit.edu"
+#define DEF_LHS ".ns"
+
+struct hesiod_p {
+ char *lhs; /* normally ".ns" */
+ char *rhs; /* AKA the default hesiod domain */
+ int classes[2]; /* The class search order. */
+};
+
+#define MAX_HESRESP 1024
+
+#endif /*HESIOD_P_H_INCLUDED*/
diff --git a/hesiod/libnss_hesiod.map b/hesiod/libnss_hesiod.map
new file mode 100644
index 0000000000..6c1fd5eba9
--- /dev/null
+++ b/hesiod/libnss_hesiod.map
@@ -0,0 +1,12 @@
+GLIBC_2.0 {
+ global:
+ _nss_hesiod_setpwent; _nss_hesiod_endpwent;
+ _nss_hesiod_getpwnam_r; _nss_hesiod_getpwuid;
+ _nss_hesiod_setgrent; _nss_hesiod_endgrent;
+ _nss_hesiod_getgrnam_r; _nss_hesiod_getgrgid;
+ _nss_hesiod_setservent; _nss_hesiod_endservent;
+ _nss_hesiod_getservbyname_r;
+
+ local:
+ *;
+};
diff --git a/hesiod/nss_hesiod/hesiod-grp.c b/hesiod/nss_hesiod/hesiod-grp.c
new file mode 100644
index 0000000000..7b0832dbe3
--- /dev/null
+++ b/hesiod/nss_hesiod/hesiod-grp.c
@@ -0,0 +1,150 @@
+/* Copyright (C) 1997 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1997.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <bits/libc-lock.h>
+#include <errno.h>
+#include <hesiod.h>
+#include <nss.h>
+#include <grp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* Get the declaration of the parser function. */
+#define ENTNAME grent
+#define STRUCTURE group
+#define EXTERN_PARSER
+#include <nss/nss_files/files-parse.c>
+
+/* Locks the static variables in this file. */
+__libc_lock_define_initialized (static, lock);
+
+static void *context = NULL;
+
+static enum nss_status
+internal_setgrent (void)
+{
+ if (!context)
+ {
+ if (hesiod_init (&context) == -1)
+ return NSS_STATUS_UNAVAIL;
+ }
+
+ return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_hesiod_setgrent (void)
+{
+ enum nss_status status;
+
+ __libc_lock_lock (lock);
+
+ status = internal_setgrent ();
+
+ __libc_lock_unlock (lock);
+
+ return status;
+}
+
+enum nss_status
+_nss_hesiod_endgrent (void)
+{
+ __libc_lock_lock (lock);
+
+ if (context)
+ {
+ hesiod_end (context);
+ context = NULL;
+ }
+
+ __libc_lock_unlock (lock);
+
+ return NSS_STATUS_SUCCESS;
+}
+
+static enum nss_status
+lookup (const char *name, const char *type, struct group *grp,
+ char *buffer, size_t buflen)
+{
+ enum nss_status status;
+ struct parser_data *data = (void *) buffer;
+ size_t linebuflen;
+ char **list;
+ int parse_res;
+
+ status = internal_setgrent ();
+ if (status != NSS_STATUS_SUCCESS)
+ return status;
+
+ list = hesiod_resolve (context, name, type);
+ if (list == NULL)
+ return errno == ENOENT ? NSS_STATUS_NOTFOUND : NSS_STATUS_UNAVAIL;
+
+ linebuflen = buffer + buflen - data->linebuffer;
+ if (linebuflen < strlen (*list) + 1)
+ {
+ hesiod_free_list (context, list);
+ __set_errno (ERANGE);
+ return NSS_STATUS_TRYAGAIN;
+ }
+
+ strcpy (buffer, *list);
+ hesiod_free_list (context, list);
+
+ parse_res = _nss_files_parse_grent (buffer, grp, data, buflen);
+ if (parse_res < 1)
+ return parse_res == -1 ? NSS_STATUS_TRYAGAIN : NSS_STATUS_NOTFOUND;
+
+ return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_hesiod_getgrnam_r (const char *name, struct group *grp,
+ char *buffer, size_t buflen)
+{
+ enum nss_status status;
+
+ __libc_lock_lock (lock);
+
+ status = lookup (name, "group", grp, buffer, buflen);
+
+ __libc_lock_unlock (lock);
+
+ return status;
+}
+
+enum nss_status
+_nss_hesiod_getgrgid_r (gid_t gid, struct group *grp,
+ char *buffer, size_t buflen)
+{
+ enum nss_status status = NSS_STATUS_UNAVAIL;
+ char gidstr[21]; /* We will probably never have a gid_t with more
+ than 64 bits. */
+
+ snprintf (gidstr, sizeof gidstr, "%d", gid);
+
+ __libc_lock_lock (lock);
+
+ status = lookup (gidstr, "gid", grp, buffer, buflen);
+
+ __libc_lock_unlock (lock);
+
+ return status;
+}
diff --git a/hesiod/nss_hesiod/hesiod-pwd.c b/hesiod/nss_hesiod/hesiod-pwd.c
new file mode 100644
index 0000000000..bb2a4c8785
--- /dev/null
+++ b/hesiod/nss_hesiod/hesiod-pwd.c
@@ -0,0 +1,150 @@
+/* Copyright (C) 1997 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1997.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <bits/libc-lock.h>
+#include <errno.h>
+#include <hesiod.h>
+#include <nss.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* Get the declaration of the parser function. */
+#define ENTNAME pwent
+#define STRUCTURE passwd
+#define EXTERN_PARSER
+#include <nss/nss_files/files-parse.c>
+
+/* Locks the static variables in this file. */
+__libc_lock_define_initialized (static, lock);
+
+static void *context = NULL;
+
+static enum nss_status
+internal_setpwent (void)
+{
+ if (!context)
+ {
+ if (hesiod_init (&context) == -1)
+ return NSS_STATUS_UNAVAIL;
+ }
+
+ return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_hesiod_setpwent (void)
+{
+ enum nss_status status;
+
+ __libc_lock_lock (lock);
+
+ status = internal_setpwent ();
+
+ __libc_lock_unlock (lock);
+
+ return status;
+}
+
+enum nss_status
+_nss_hesiod_endpwent (void)
+{
+ __libc_lock_lock (lock);
+
+ if (context)
+ {
+ hesiod_end (context);
+ context = NULL;
+ }
+
+ __libc_lock_unlock (lock);
+
+ return NSS_STATUS_SUCCESS;
+}
+
+static enum nss_status
+lookup (const char *name, const char *type, struct passwd *pwd,
+ char *buffer, size_t buflen)
+{
+ enum nss_status status;
+ struct parser_data *data = (void *) buffer;
+ size_t linebuflen;
+ char **list;
+ int parse_res;
+
+ status = internal_setpwent ();
+ if (status != NSS_STATUS_SUCCESS)
+ return status;
+
+ list = hesiod_resolve (context, name, type);
+ if (list == NULL)
+ return errno == ENOENT ? NSS_STATUS_NOTFOUND : NSS_STATUS_UNAVAIL;
+
+ linebuflen = buffer + buflen - data->linebuffer;
+ if (linebuflen < strlen (*list) + 1)
+ {
+ hesiod_free_list (context, list);
+ __set_errno (ERANGE);
+ return NSS_STATUS_TRYAGAIN;
+ }
+
+ strcpy (data->linebuffer, *list);
+ hesiod_free_list (context, list);
+
+ parse_res = _nss_files_parse_pwent (buffer, pwd, data, buflen);
+ if (parse_res < 1)
+ return parse_res == -1 ? NSS_STATUS_TRYAGAIN : NSS_STATUS_NOTFOUND;
+
+ return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_hesiod_getpwnam_r (const char *name, struct passwd *pwd,
+ char *buffer, size_t buflen)
+{
+ enum nss_status status;
+
+ __libc_lock_lock (lock);
+
+ status = lookup (name, "passwd", pwd, buffer, buflen);
+
+ __libc_lock_unlock (lock);
+
+ return status;
+}
+
+enum nss_status
+_nss_hesiod_getpwuid_r (uid_t uid, struct passwd *pwd,
+ char *buffer, size_t buflen)
+{
+ enum nss_status status = NSS_STATUS_UNAVAIL;
+ char uidstr[21]; /* We will probably never have a gid_t with more
+ than 64 bits. */
+
+ snprintf (uidstr, sizeof uidstr, "%d", uid);
+
+ __libc_lock_lock (lock);
+
+ status = lookup (uidstr, "uid", pwd, buffer, buflen);
+
+ __libc_lock_unlock (lock);
+
+ return status;
+}
diff --git a/hesiod/nss_hesiod/hesiod-service.c b/hesiod/nss_hesiod/hesiod-service.c
new file mode 100644
index 0000000000..f74877f748
--- /dev/null
+++ b/hesiod/nss_hesiod/hesiod-service.c
@@ -0,0 +1,165 @@
+/* Copyright (C) 1997 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1997.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <bits/libc-lock.h>
+#include <errno.h>
+#include <hesiod.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <nss.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+/* Hesiod uses a format for service entries that differs from the
+ traditional format. We therefore declare our own parser. */
+
+#define ENTNAME servent
+
+#define ENTDATA servent_data
+struct servent_data {};
+
+#define TRAILING_LIST_MEMBER s_aliases
+#define TRAILING_LIST_SEPARATOR_P isspace
+#include <nss/nss_files/files-parse.c>
+#define ISSEMICOLON(c) ((c) == ';')
+LINE_PARSER
+("",
+ (void) entdata;
+ STRING_FIELD (result->s_name, ISSEMICOLON, 1);
+ STRING_FIELD (result->s_proto, ISSEMICOLON, 1);
+ INT_FIELD (result->s_port, ISSEMICOLON, 10, 0, htons);
+ )
+
+
+/* Locks the static variables in this file. */
+__libc_lock_define_initialized (static, lock);
+
+static void *context = NULL;
+
+static enum nss_status
+internal_setservent (void)
+{
+ if (!context)
+ {
+ if (hesiod_init (&context) == -1)
+ return NSS_STATUS_UNAVAIL;
+ }
+
+ return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_hesiod_setservent (void)
+{
+ enum nss_status status;
+
+ __libc_lock_lock (lock);
+
+ status = internal_setservent ();
+
+ __libc_lock_unlock (lock);
+
+ return status;
+}
+
+enum nss_status
+_nss_hesiod_endservent (void)
+{
+ __libc_lock_lock (lock);
+
+ if (context)
+ {
+ hesiod_end (context);
+ context = NULL;
+ }
+
+ __libc_lock_unlock (lock);
+
+ return NSS_STATUS_SUCCESS;
+}
+
+static enum nss_status
+lookup (const char *name, const char *protocol, struct servent *serv,
+ char *buffer, size_t buflen)
+{
+ enum nss_status status;
+ struct parser_data *data = (void *) buffer;
+ size_t linebuflen;
+ char **list, **item;
+ int parse_res;
+ int found;
+
+ status = internal_setservent ();
+ if (status != NSS_STATUS_SUCCESS)
+ return status;
+
+ list = hesiod_resolve (context, name, "service");
+ if (list == NULL)
+ return errno == ENOENT ? NSS_STATUS_NOTFOUND : NSS_STATUS_UNAVAIL;
+
+ linebuflen = buffer + buflen - data->linebuffer;
+
+ item = list;
+ found = 0;
+ do
+ {
+ if (linebuflen < strlen (*item) + 1)
+ {
+ hesiod_free_list (context, list);
+ __set_errno (ERANGE);
+ return NSS_STATUS_TRYAGAIN;
+ }
+
+ strcpy (data->linebuffer, *item);
+
+ parse_res = parse_line (buffer, serv, data, buflen);
+ if (parse_res == -1)
+ {
+ hesiod_free_list (context, list);
+ return NSS_STATUS_TRYAGAIN;
+ }
+
+ if (parse_res > 0)
+ found = protocol == NULL || strcmp (serv->s_proto, protocol) == 0;
+
+ ++item;
+ }
+ while (*item != NULL && !found);
+
+ hesiod_free_list (context, list);
+
+ return found ? NSS_STATUS_SUCCESS : NSS_STATUS_NOTFOUND;
+}
+
+enum nss_status
+_nss_hesiod_getservbyname_r (const char *name, const char *protocol,
+ struct servent *serv,
+ char *buffer, size_t buflen)
+{
+ enum nss_status status;
+
+ __libc_lock_lock (lock);
+
+ status = lookup (name, protocol, serv, buffer, buflen);
+
+ __libc_lock_unlock (lock);
+
+ return status;
+}