Add initgroups support.
[kopensolaris-gnu/glibc.git] / hesiod / nss_hesiod / hesiod-pwd.c
1 /* Copyright (C) 1997 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1997.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Library General Public License as
7    published by the Free Software Foundation; either version 2 of the
8    License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Library General Public License for more details.
14
15    You should have received a copy of the GNU Library General Public
16    License along with the GNU C Library; see the file COPYING.LIB.  If not,
17    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18    Boston, MA 02111-1307, USA.  */
19
20 #include <bits/libc-lock.h>
21 #include <errno.h>
22 #include <hesiod.h>
23 #include <nss.h>
24 #include <pwd.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28
29 /* Get the declaration of the parser function.  */
30 #define ENTNAME pwent
31 #define STRUCTURE passwd
32 #define EXTERN_PARSER
33 #include <nss/nss_files/files-parse.c>
34
35 /* Locks the static variables in this file.  */
36 __libc_lock_define_initialized (static, lock);
37
38 static void *context = NULL;
39
40 static enum nss_status
41 internal_setpwent (void)
42 {
43   if (!context)
44     {
45       if (hesiod_init (&context) == -1)
46         return NSS_STATUS_UNAVAIL;
47     }
48
49   return NSS_STATUS_SUCCESS;
50 }
51
52 enum nss_status
53 _nss_hesiod_setpwent (void)
54 {
55   enum nss_status status;
56
57   __libc_lock_lock (lock);
58
59   status = internal_setpwent ();
60
61   __libc_lock_unlock (lock);
62
63   return status;
64 }
65
66 enum nss_status
67 _nss_hesiod_endpwent (void)
68 {
69   __libc_lock_lock (lock);
70
71   if (context)
72     {
73       hesiod_end (context);
74       context = NULL;
75     }
76
77   __libc_lock_unlock (lock);
78
79   return NSS_STATUS_SUCCESS;
80 }
81
82 static enum nss_status
83 lookup (const char *name, const char *type, struct passwd *pwd,
84         char *buffer, size_t buflen, int *errnop)
85 {
86   enum nss_status status;
87   struct parser_data *data = (void *) buffer;
88   size_t linebuflen;
89   char **list;
90   int parse_res;
91   size_t len;
92
93   status = internal_setpwent ();
94   if (status != NSS_STATUS_SUCCESS)
95     return status;
96
97   list = hesiod_resolve (context, name, type);
98   if (list == NULL)
99     return errno == ENOENT ? NSS_STATUS_NOTFOUND : NSS_STATUS_UNAVAIL;
100
101   linebuflen = buffer + buflen - data->linebuffer;
102   len = strlen (*list) + 1;
103   if (linebuflen < len)
104     {
105       hesiod_free_list (context, list);
106       *errnop = ERANGE;
107       return NSS_STATUS_TRYAGAIN;
108     }
109
110   memcpy (data->linebuffer, *list, len);
111   hesiod_free_list (context, list);
112
113   parse_res = _nss_files_parse_pwent (buffer, pwd, data, buflen, errnop);
114   if (parse_res < 1)
115     return parse_res == -1 ? NSS_STATUS_TRYAGAIN : NSS_STATUS_NOTFOUND;
116
117   return NSS_STATUS_SUCCESS;
118 }
119
120 enum nss_status
121 _nss_hesiod_getpwnam_r (const char *name, struct passwd *pwd,
122                         char *buffer, size_t buflen, int *errnop)
123 {
124   enum nss_status status;
125
126   __libc_lock_lock (lock);
127
128   status = lookup (name, "passwd", pwd, buffer, buflen, errnop);
129
130   __libc_lock_unlock (lock);
131
132   return status;
133 }
134
135 enum nss_status
136 _nss_hesiod_getpwuid_r (uid_t uid, struct passwd *pwd,
137                         char *buffer, size_t buflen, int *errnop)
138 {
139   enum nss_status status = NSS_STATUS_UNAVAIL;
140   char uidstr[21];      /* We will probably never have a gid_t with more
141                            than 64 bits.  */
142
143   snprintf (uidstr, sizeof uidstr, "%d", uid);
144
145   __libc_lock_lock (lock);
146
147   status = lookup (uidstr, "uid", pwd, buffer, buflen, errnop);
148
149   __libc_lock_unlock (lock);
150
151   return status;
152 }