(lookup): Preserve errno value.
[kopensolaris-gnu/glibc.git] / hesiod / nss_hesiod / hesiod-pwd.c
1 /* Copyright (C) 1997, 2000, 2002 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 Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the 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    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
19
20 #include <errno.h>
21 #include <hesiod.h>
22 #include <pwd.h>
23 #include <nss.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include "nss_hesiod.h"
29
30 /* Get the declaration of the parser function.  */
31 #define ENTNAME pwent
32 #define STRUCTURE passwd
33 #define EXTERN_PARSER
34 #include <nss/nss_files/files-parse.c>
35
36 enum nss_status
37 _nss_hesiod_setpwent (int stayopen)
38 {
39   return NSS_STATUS_SUCCESS;
40 }
41
42 enum nss_status
43 _nss_hesiod_endpwent (void)
44 {
45   return NSS_STATUS_SUCCESS;
46 }
47
48 static enum nss_status
49 lookup (const char *name, const char *type, struct passwd *pwd,
50         char *buffer, size_t buflen, int *errnop)
51 {
52   struct parser_data *data = (void *) buffer;
53   size_t linebuflen;
54   void *context;
55   char **list;
56   int parse_res;
57   size_t len;
58   int olderr = errno;
59
60   context = _nss_hesiod_init ();
61   if (context == NULL)
62     return NSS_STATUS_UNAVAIL;
63
64   list = hesiod_resolve (context, name, type);
65   if (list == NULL)
66     {
67       int err = errno;
68       hesiod_end (context);
69       __set_errno (olderr);
70       return err == ENOENT ? NSS_STATUS_NOTFOUND : NSS_STATUS_UNAVAIL;
71     }
72
73   linebuflen = buffer + buflen - data->linebuffer;
74   len = strlen (*list) + 1;
75   if (linebuflen < len)
76     {
77       hesiod_free_list (context, list);
78       hesiod_end (context);
79       *errnop = ERANGE;
80       return NSS_STATUS_TRYAGAIN;
81     }
82
83   memcpy (data->linebuffer, *list, len);
84   hesiod_free_list (context, list);
85   hesiod_end (context);
86
87   parse_res = _nss_files_parse_pwent (buffer, pwd, data, buflen, errnop);
88   if (parse_res < 1)
89     {
90       __set_errno (olderr);
91       return parse_res == -1 ? NSS_STATUS_TRYAGAIN : NSS_STATUS_NOTFOUND;
92     }
93
94   return NSS_STATUS_SUCCESS;
95 }
96
97 enum nss_status
98 _nss_hesiod_getpwnam_r (const char *name, struct passwd *pwd,
99                         char *buffer, size_t buflen, int *errnop)
100 {
101   return lookup (name, "passwd", pwd, buffer, buflen, errnop);
102 }
103
104 enum nss_status
105 _nss_hesiod_getpwuid_r (uid_t uid, struct passwd *pwd,
106                         char *buffer, size_t buflen, int *errnop)
107 {
108   char uidstr[21];      /* We will probably never have a gid_t with more
109                            than 64 bits.  */
110
111   snprintf (uidstr, sizeof uidstr, "%d", uid);
112
113   return lookup (uidstr, "uid", pwd, buffer, buflen, errnop);
114 }