1 /* Copyright (C) 1996, 1997 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996.
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.
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.
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. */
27 #include <bits/libc-lock.h>
28 #include <rpcsvc/yp.h>
29 #include <rpcsvc/ypclnt.h>
30 #include <rpcsvc/nis.h>
31 #include <rpcsvc/nislib.h>
35 #include "nss-nisplus.h"
36 #include "nisplus-parser.h"
38 static service_user
*ni
= NULL
;
39 static bool_t use_nisplus
= FALSE
; /* default: passwd_compat: nis */
40 static nis_name pwdtable
= NULL
; /* Name of the pwd table */
41 static size_t pwdtablelen
= 0;
43 /* Get the declaration of the parser function. */
45 #define STRUCTURE passwd
47 #include "../../nss/nss_files/files-parse.c"
49 /* Structure for remembering -@netgroup and -user members ... */
50 #define BLACKLIST_INITIAL_SIZE 512
51 #define BLACKLIST_INCREMENT 256
68 struct blacklist_t blacklist
;
70 struct __netgrent netgrdata
;
72 typedef struct ent_t ent_t
;
74 static ent_t ext_ent
= {0, 0, 0, NULL
, 0, NULL
, NULL
, {NULL
, 0, 0},
75 {NULL
, NULL
, 0, 0, NULL
, NULL
, NULL
}};
77 /* Protect global state against multiple changers. */
78 __libc_lock_define_initialized (static, lock
)
80 /* Prototypes for local functions. */
81 static void blacklist_store_name (const char *, ent_t
*);
82 static int in_blacklist (const char *, int, ent_t
*);
85 give_pwd_free (struct passwd
*pwd
)
87 if (pwd
->pw_name
!= NULL
)
89 if (pwd
->pw_passwd
!= NULL
)
90 free (pwd
->pw_passwd
);
91 if (pwd
->pw_gecos
!= NULL
)
93 if (pwd
->pw_dir
!= NULL
)
95 if (pwd
->pw_shell
!= NULL
)
98 memset (pwd
, '\0', sizeof (struct passwd
));
102 pwd_need_buflen (struct passwd
*pwd
)
106 if (pwd
->pw_passwd
!= NULL
)
107 len
+= strlen (pwd
->pw_passwd
) + 1;
109 if (pwd
->pw_gecos
!= NULL
)
110 len
+= strlen (pwd
->pw_gecos
) + 1;
112 if (pwd
->pw_dir
!= NULL
)
113 len
+= strlen (pwd
->pw_dir
) + 1;
115 if (pwd
->pw_shell
!= NULL
)
116 len
+= strlen (pwd
->pw_shell
) + 1;
122 copy_pwd_changes (struct passwd
*dest
, struct passwd
*src
,
123 char *buffer
, size_t buflen
)
125 if (src
->pw_passwd
!= NULL
&& strlen (src
->pw_passwd
))
128 dest
->pw_passwd
= strdup (src
->pw_passwd
);
129 else if (dest
->pw_passwd
&&
130 strlen (dest
->pw_passwd
) >= strlen (src
->pw_passwd
))
131 strcpy (dest
->pw_passwd
, src
->pw_passwd
);
134 dest
->pw_passwd
= buffer
;
135 strcpy (dest
->pw_passwd
, src
->pw_passwd
);
136 buffer
+= strlen (dest
->pw_passwd
) + 1;
137 buflen
= buflen
- (strlen (dest
->pw_passwd
) + 1);
141 if (src
->pw_gecos
!= NULL
&& strlen (src
->pw_gecos
))
144 dest
->pw_gecos
= strdup (src
->pw_gecos
);
145 else if (dest
->pw_gecos
&&
146 strlen (dest
->pw_gecos
) >= strlen (src
->pw_gecos
))
147 strcpy (dest
->pw_gecos
, src
->pw_gecos
);
150 dest
->pw_gecos
= buffer
;
151 strcpy (dest
->pw_gecos
, src
->pw_gecos
);
152 buffer
+= strlen (dest
->pw_gecos
) + 1;
153 buflen
= buflen
- (strlen (dest
->pw_gecos
) + 1);
156 if (src
->pw_dir
!= NULL
&& strlen (src
->pw_dir
))
159 dest
->pw_dir
= strdup (src
->pw_dir
);
160 else if (dest
->pw_dir
&&
161 strlen (dest
->pw_dir
) >= strlen (src
->pw_dir
))
162 strcpy (dest
->pw_dir
, src
->pw_dir
);
165 dest
->pw_dir
= buffer
;
166 strcpy (dest
->pw_dir
, src
->pw_dir
);
167 buffer
+= strlen (dest
->pw_dir
) + 1;
168 buflen
= buflen
- (strlen (dest
->pw_dir
) + 1);
172 if (src
->pw_shell
!= NULL
&& strlen (src
->pw_shell
))
175 dest
->pw_shell
= strdup (src
->pw_shell
);
176 else if (dest
->pw_shell
&&
177 strlen (dest
->pw_shell
) >= strlen (src
->pw_shell
))
178 strcpy (dest
->pw_shell
, src
->pw_shell
);
181 dest
->pw_shell
= buffer
;
182 strcpy (dest
->pw_shell
, src
->pw_shell
);
183 buffer
+= strlen (dest
->pw_shell
) + 1;
184 buflen
= buflen
- (strlen (dest
->pw_shell
) + 1);
189 static enum nss_status
190 internal_setpwent (ent_t
*ent
)
192 enum nss_status status
= NSS_STATUS_SUCCESS
;
194 ent
->nis
= ent
->first
= ent
->netgroup
= 0;
196 /* If something was left over free it. */
198 __internal_endnetgrent (&ent
->netgrdata
);
200 if (ent
->oldkey
!= NULL
)
207 if (ent
->result
!= NULL
)
209 nis_freeresult (ent
->result
);
213 if (pwdtable
== NULL
)
215 char buf
[20 + strlen (nis_local_directory ())];
218 p
= stpcpy (buf
, "passwd.org_dir.");
219 p
= stpcpy (p
, nis_local_directory ());
220 pwdtable
= strdup (buf
);
221 if (pwdtable
== NULL
)
222 return NSS_STATUS_TRYAGAIN
;
223 pwdtablelen
= strlen (pwdtable
);
226 ent
->blacklist
.current
= 0;
227 if (ent
->blacklist
.data
!= NULL
)
228 ent
->blacklist
.data
[0] = '\0';
230 if (ent
->stream
== NULL
)
232 ent
->stream
= fopen ("/etc/passwd", "r");
234 if (ent
->stream
== NULL
)
235 status
= errno
== EAGAIN
? NSS_STATUS_TRYAGAIN
: NSS_STATUS_UNAVAIL
;
238 /* We have to make sure the file is `closed on exec'. */
241 result
= flags
= fcntl (fileno (ent
->stream
), F_GETFD
, 0);
245 result
= fcntl (fileno (ent
->stream
), F_SETFD
, flags
);
249 /* Something went wrong. Close the stream and return a
251 fclose (ent
->stream
);
253 status
= NSS_STATUS_UNAVAIL
;
258 rewind (ent
->stream
);
260 give_pwd_free (&ent
->pwd
);
267 _nss_compat_setpwent (void)
269 enum nss_status result
;
271 __libc_lock_lock (lock
);
275 __nss_database_lookup ("passwd_compat", NULL
, "nis", &ni
);
276 use_nisplus
= (strcmp (ni
->name
, "nisplus") == 0);
279 result
= internal_setpwent (&ext_ent
);
281 __libc_lock_unlock (lock
);
287 static enum nss_status
288 internal_endpwent (ent_t
*ent
)
290 if (ent
->stream
!= NULL
)
292 fclose (ent
->stream
);
297 __internal_endnetgrent (&ent
->netgrdata
);
299 ent
->nis
= ent
->first
= ent
->netgroup
= 0;
301 if (ent
->oldkey
!= NULL
)
308 if (ent
->result
!= NULL
)
310 nis_freeresult (ent
->result
);
314 ent
->blacklist
.current
= 0;
315 if (ent
->blacklist
.data
!= NULL
)
316 ent
->blacklist
.data
[0] = '\0';
318 give_pwd_free (&ent
->pwd
);
320 return NSS_STATUS_SUCCESS
;
324 _nss_compat_endpwent (void)
326 enum nss_status result
;
328 __libc_lock_lock (lock
);
330 result
= internal_endpwent (&ext_ent
);
332 __libc_lock_unlock (lock
);
337 static enum nss_status
338 getpwent_next_nis_netgr (struct passwd
*result
, ent_t
*ent
, char *group
,
339 char *buffer
, size_t buflen
)
341 struct parser_data
*data
= (void *) buffer
;
342 char *ypdomain
, *host
, *user
, *domain
, *outval
, *p
, *p2
;
343 int status
, outvallen
;
346 if (yp_get_default_domain (&ypdomain
) != YPERR_SUCCESS
)
350 give_pwd_free (&ent
->pwd
);
351 return NSS_STATUS_UNAVAIL
;
354 if (ent
->first
== TRUE
)
356 memset (&ent
->netgrdata
, 0, sizeof (struct __netgrent
));
357 __internal_setnetgrent (group
, &ent
->netgrdata
);
366 saved_cursor
= ent
->netgrdata
.cursor
;
367 status
= __internal_getnetgrent_r (&host
, &user
, &domain
,
368 &ent
->netgrdata
, buffer
, buflen
);
371 __internal_endnetgrent (&ent
->netgrdata
);
373 give_pwd_free (&ent
->pwd
);
374 return NSS_STATUS_RETURN
;
377 if (user
== NULL
|| user
[0] == '-')
380 if (domain
!= NULL
&& strcmp (ypdomain
, domain
) != 0)
383 if (yp_match (ypdomain
, "passwd.byname", user
,
384 strlen (user
), &outval
, &outvallen
)
388 p2len
= pwd_need_buflen (&ent
->pwd
);
391 __set_errno (ERANGE
);
392 return NSS_STATUS_TRYAGAIN
;
394 p2
= buffer
+ (buflen
- p2len
);
396 p
= strncpy (buffer
, outval
, buflen
);
400 if ((parse_res
= _nss_files_parse_pwent (p
, result
, data
, buflen
)) == -1)
402 ent
->netgrdata
.cursor
= saved_cursor
;
403 return NSS_STATUS_TRYAGAIN
;
408 copy_pwd_changes (result
, &ent
->pwd
, p2
, p2len
);
413 return NSS_STATUS_SUCCESS
;
416 static enum nss_status
417 getpwent_next_nisplus_netgr (struct passwd
*result
, ent_t
*ent
, char *group
,
418 char *buffer
, size_t buflen
)
420 char *ypdomain
, *host
, *user
, *domain
, *p2
;
421 int status
, parse_res
;
425 /* Maybe we should use domainname here ? We need the current
426 domainname for the domain field in netgroups */
427 if (yp_get_default_domain (&ypdomain
) != YPERR_SUCCESS
)
431 give_pwd_free (&ent
->pwd
);
432 return NSS_STATUS_UNAVAIL
;
435 if (ent
->first
== TRUE
)
437 bzero (&ent
->netgrdata
, sizeof (struct __netgrent
));
438 __internal_setnetgrent (group
, &ent
->netgrdata
);
446 saved_cursor
= ent
->netgrdata
.cursor
;
447 status
= __internal_getnetgrent_r (&host
, &user
, &domain
,
448 &ent
->netgrdata
, buffer
, buflen
);
451 __internal_endnetgrent (&ent
->netgrdata
);
453 give_pwd_free (&ent
->pwd
);
454 return NSS_STATUS_RETURN
;
457 if (user
== NULL
|| user
[0] == '-')
460 if (domain
!= NULL
&& strcmp (ypdomain
, domain
) != 0)
463 p2len
= pwd_need_buflen (&ent
->pwd
);
466 __set_errno (ERANGE
);
467 return NSS_STATUS_TRYAGAIN
;
469 p2
= buffer
+ (buflen
- p2len
);
472 char buf
[strlen (user
) + 30 + pwdtablelen
];
473 sprintf(buf
, "[name=%s],%s", user
, pwdtable
);
474 nisres
= nis_list(buf
, FOLLOW_PATH
| FOLLOW_LINKS
, NULL
, NULL
);
476 if (niserr2nss (nisres
->status
) != NSS_STATUS_SUCCESS
)
478 nis_freeresult (nisres
);
481 if ((parse_res
= _nss_nisplus_parse_pwent (nisres
, result
, buffer
,
484 nis_freeresult (nisres
);
485 ent
->netgrdata
.cursor
= saved_cursor
;
486 return NSS_STATUS_TRYAGAIN
;
488 nis_freeresult (nisres
);
492 copy_pwd_changes (result
, &ent
->pwd
, p2
, p2len
);
497 return NSS_STATUS_SUCCESS
;
500 static enum nss_status
501 getpwent_next_netgr (struct passwd
*result
, ent_t
*ent
, char *group
,
502 char *buffer
, size_t buflen
)
505 return getpwent_next_nisplus_netgr (result
, ent
, group
, buffer
, buflen
);
507 return getpwent_next_nis_netgr (result
, ent
, group
, buffer
, buflen
);
510 static enum nss_status
511 getpwent_next_nisplus (struct passwd
*result
, ent_t
*ent
, char *buffer
,
518 p2len
= pwd_need_buflen (&ent
->pwd
);
521 __set_errno (ERANGE
);
522 return NSS_STATUS_TRYAGAIN
;
524 p2
= buffer
+ (buflen
- p2len
);
529 nis_result
*saved_res
;
534 saved_res
= ent
->result
;
536 ent
->result
= nis_first_entry(pwdtable
);
537 if (niserr2nss (ent
->result
->status
) != NSS_STATUS_SUCCESS
)
540 give_pwd_free (&ent
->pwd
);
541 return niserr2nss (ent
->result
->status
);
549 res
= nis_next_entry(pwdtable
, &ent
->result
->cookie
);
550 saved_res
= ent
->result
;
553 if (niserr2nss (ent
->result
->status
) != NSS_STATUS_SUCCESS
)
556 nis_freeresult (saved_res
);
557 give_pwd_free (&ent
->pwd
);
558 return niserr2nss (ent
->result
->status
);
561 if ((parse_res
= _nss_nisplus_parse_pwent (ent
->result
, result
, buffer
,
564 nis_freeresult (ent
->result
);
565 ent
->result
= saved_res
;
566 ent
->first
= saved_first
;
567 __set_errno (ERANGE
);
568 return NSS_STATUS_TRYAGAIN
;
573 nis_freeresult (saved_res
);
577 in_blacklist (result
->pw_name
, strlen (result
->pw_name
), ent
))
578 parse_res
= 0; /* if result->pw_name in blacklist,search next entry */
582 copy_pwd_changes (result
, &ent
->pwd
, p2
, p2len
);
584 return NSS_STATUS_SUCCESS
;
587 static enum nss_status
588 getpwent_next_nis (struct passwd
*result
, ent_t
*ent
, char *buffer
,
591 struct parser_data
*data
= (void *) buffer
;
592 char *domain
, *outkey
, *outval
, *p
, *p2
;
593 int outkeylen
, outvallen
, parse_res
;
596 if (yp_get_default_domain (&domain
) != YPERR_SUCCESS
)
599 give_pwd_free (&ent
->pwd
);
600 return NSS_STATUS_UNAVAIL
;
603 p2len
= pwd_need_buflen (&ent
->pwd
);
606 __set_errno (ERANGE
);
607 return NSS_STATUS_TRYAGAIN
;
609 p2
= buffer
+ (buflen
- p2len
);
619 if (yp_first (domain
, "passwd.byname", &outkey
, &outkeylen
,
620 &outval
, &outvallen
) != YPERR_SUCCESS
)
623 give_pwd_free (&ent
->pwd
);
624 return NSS_STATUS_UNAVAIL
;
628 saved_oldkey
= ent
->oldkey
;
629 saved_oldlen
= ent
->oldkeylen
;
630 ent
->oldkey
= outkey
;
631 ent
->oldkeylen
= outkeylen
;
636 if (yp_next (domain
, "passwd.byname", ent
->oldkey
, ent
->oldkeylen
,
637 &outkey
, &outkeylen
, &outval
, &outvallen
)
641 give_pwd_free (&ent
->pwd
);
642 return NSS_STATUS_NOTFOUND
;
646 saved_oldkey
= ent
->oldkey
;
647 saved_oldlen
= ent
->oldkeylen
;
648 ent
->oldkey
= outkey
;
649 ent
->oldkeylen
= outkeylen
;
652 /* Copy the found data to our buffer */
653 p
= strncpy (buffer
, outval
, buflen
);
655 /* ...and free the data. */
660 if ((parse_res
= _nss_files_parse_pwent (p
, result
, data
, buflen
)) == -1)
663 ent
->oldkey
= saved_oldkey
;
664 ent
->oldkeylen
= saved_oldlen
;
665 ent
->first
= saved_first
;
666 __set_errno (ERANGE
);
667 return NSS_STATUS_TRYAGAIN
;
675 in_blacklist (result
->pw_name
, strlen (result
->pw_name
), ent
))
680 copy_pwd_changes (result
, &ent
->pwd
, p2
, p2len
);
682 return NSS_STATUS_SUCCESS
;
685 /* This function handle the +user entrys in /etc/passwd */
686 static enum nss_status
687 getpwent_next_file_plususer (struct passwd
*result
, char *buffer
,
690 struct parser_data
*data
= (void *) buffer
;
696 memset (&pwd
, '\0', sizeof (struct passwd
));
698 copy_pwd_changes (&pwd
, result
, NULL
, 0);
700 plen
= pwd_need_buflen (&pwd
);
703 __set_errno (ERANGE
);
704 return NSS_STATUS_TRYAGAIN
;
706 p
= buffer
+ (buflen
- plen
);
709 if (use_nisplus
) /* Do the NIS+ query here */
712 char buf
[strlen (result
->pw_name
) + 24 + pwdtablelen
];
714 sprintf(buf
, "[name=%s],%s", &result
->pw_name
[1], pwdtable
);
715 res
= nis_list(buf
, FOLLOW_PATH
| FOLLOW_LINKS
, NULL
, NULL
);
716 if (niserr2nss (res
->status
) != NSS_STATUS_SUCCESS
)
718 enum nss_status status
= niserr2nss (res
->status
);
720 nis_freeresult (res
);
723 if ((parse_res
= _nss_nisplus_parse_pwent (res
, result
, buffer
,
726 nis_freeresult (res
);
727 __set_errno (ERANGE
);
728 return NSS_STATUS_TRYAGAIN
;
730 nis_freeresult (res
);
738 if (yp_get_default_domain (&domain
) != YPERR_SUCCESS
)
739 return NSS_STATUS_TRYAGAIN
;
741 if (yp_match (domain
, "passwd.byname", &result
->pw_name
[1],
742 strlen (result
->pw_name
) - 1, &outval
, &outvallen
)
744 return NSS_STATUS_TRYAGAIN
;
745 p
= strncpy (buffer
, outval
,
746 buflen
< (size_t) outvallen
? buflen
: (size_t) outvallen
);
750 if ((parse_res
= _nss_files_parse_pwent (p
, result
, data
, buflen
)) == -1)
752 __set_errno (ERANGE
);
753 return NSS_STATUS_TRYAGAIN
;
759 copy_pwd_changes (result
, &pwd
, p
, plen
);
760 give_pwd_free (&pwd
);
761 /* We found the entry. */
762 return NSS_STATUS_SUCCESS
;
766 /* Give buffer the old len back */
768 give_pwd_free (&pwd
);
770 return NSS_STATUS_RETURN
;
773 static enum nss_status
774 getpwent_next_file (struct passwd
*result
, ent_t
*ent
,
775 char *buffer
, size_t buflen
)
777 struct parser_data
*data
= (void *) buffer
;
786 fgetpos (ent
->stream
, &pos
);
787 p
= fgets (buffer
, buflen
, ent
->stream
);
789 return NSS_STATUS_NOTFOUND
;
791 /* Terminate the line for any case. */
792 buffer
[buflen
- 1] = '\0';
794 /* Skip leading blanks. */
798 while (*p
== '\0' || *p
== '#' || /* Ignore empty and comment lines. */
799 /* Parse the line. If it is invalid, loop to
800 get the next line of the file to parse. */
801 !(parse_res
= _nss_files_parse_pwent (p
, result
, data
, buflen
)));
805 /* The parser ran out of space. */
806 fsetpos (ent
->stream
, &pos
);
807 __set_errno (ERANGE
);
808 return NSS_STATUS_TRYAGAIN
;
811 if (result
->pw_name
[0] != '+' && result
->pw_name
[0] != '-')
812 /* This is a real entry. */
816 if (result
->pw_name
[0] == '-' && result
->pw_name
[1] == '@'
817 && result
->pw_name
[2] != '\0')
820 char *user
, *host
, *domain
;
821 struct __netgrent netgrdata
;
823 bzero (&netgrdata
, sizeof (struct __netgrent
));
824 __internal_setnetgrent (&result
->pw_name
[2], &netgrdata
);
825 while (__internal_getnetgrent_r (&host
, &user
, &domain
,
826 &netgrdata
, buf2
, sizeof (buf2
)))
828 if (user
!= NULL
&& user
[0] != '-')
829 blacklist_store_name (user
, ent
);
831 __internal_endnetgrent (&netgrdata
);
836 if (result
->pw_name
[0] == '+' && result
->pw_name
[1] == '@'
837 && result
->pw_name
[2] != '\0')
841 ent
->netgroup
= TRUE
;
843 copy_pwd_changes (&ent
->pwd
, result
, NULL
, 0);
845 status
= getpwent_next_netgr (result
, ent
, &result
->pw_name
[2],
847 if (status
== NSS_STATUS_RETURN
)
854 if (result
->pw_name
[0] == '-' && result
->pw_name
[1] != '\0'
855 && result
->pw_name
[1] != '@')
857 blacklist_store_name (&result
->pw_name
[1], ent
);
862 if (result
->pw_name
[0] == '+' && result
->pw_name
[1] != '\0'
863 && result
->pw_name
[1] != '@')
865 enum nss_status status
;
867 status
= getpwent_next_file_plususer (result
, buffer
, buflen
);
868 if (status
== NSS_STATUS_SUCCESS
) /* We found the entry. */
871 if (status
== NSS_STATUS_RETURN
) /* We couldn't parse the entry */
878 if (result
->pw_name
[0] == '+' && result
->pw_name
[1] == '\0')
882 copy_pwd_changes (&ent
->pwd
, result
, NULL
, 0);
885 return getpwent_next_nisplus (result
, ent
, buffer
, buflen
);
887 return getpwent_next_nis (result
, ent
, buffer
, buflen
);
891 return NSS_STATUS_SUCCESS
;
895 static enum nss_status
896 internal_getpwent_r (struct passwd
*pw
, ent_t
*ent
, char *buffer
,
903 /* We are searching members in a netgroup */
904 /* Since this is not the first call, we don't need the group name */
905 status
= getpwent_next_netgr (pw
, ent
, NULL
, buffer
, buflen
);
906 if (status
== NSS_STATUS_RETURN
)
907 return getpwent_next_file (pw
, ent
, buffer
, buflen
);
914 return getpwent_next_nisplus (pw
, ent
, buffer
, buflen
);
916 return getpwent_next_nis (pw
, ent
, buffer
, buflen
);
919 return getpwent_next_file (pw
, ent
, buffer
, buflen
);
923 _nss_compat_getpwent_r (struct passwd
*pwd
, char *buffer
,
926 enum nss_status status
= NSS_STATUS_SUCCESS
;
928 __libc_lock_lock (lock
);
932 __nss_database_lookup ("passwd_compat", NULL
, "nis", &ni
);
933 use_nisplus
= (strcmp (ni
->name
, "nisplus") == 0);
936 /* Be prepared that the setpwent function was not called before. */
937 if (ext_ent
.stream
== NULL
)
938 status
= internal_setpwent (&ext_ent
);
940 if (status
== NSS_STATUS_SUCCESS
)
941 status
= internal_getpwent_r (pwd
, &ext_ent
, buffer
, buflen
);
943 __libc_lock_unlock (lock
);
950 _nss_compat_getpwnam_r (const char *name
, struct passwd
*pwd
,
951 char *buffer
, size_t buflen
)
953 ent_t ent
= {0, 0, 0, NULL
, 0, NULL
, NULL
, {NULL
, 0, 0},
954 {NULL
, NULL
, 0, 0, NULL
, NULL
, NULL
}};
955 enum nss_status status
;
957 if (name
[0] == '-' || name
[0] == '+')
958 return NSS_STATUS_NOTFOUND
;
960 __libc_lock_lock (lock
);
964 __nss_database_lookup ("passwd_compat", NULL
, "nis", &ni
);
965 use_nisplus
= (strcmp (ni
->name
, "nisplus") == 0);
968 __libc_lock_unlock (lock
);
970 status
= internal_setpwent (&ent
);
971 if (status
!= NSS_STATUS_SUCCESS
)
974 while ((status
= internal_getpwent_r (pwd
, &ent
, buffer
, buflen
))
975 == NSS_STATUS_SUCCESS
)
976 if (strcmp (pwd
->pw_name
, name
) == 0)
979 internal_endpwent (&ent
);
985 _nss_compat_getpwuid_r (uid_t uid
, struct passwd
*pwd
,
986 char *buffer
, size_t buflen
)
988 ent_t ent
= {0, 0, 0, NULL
, 0, NULL
, NULL
, {NULL
, 0, 0},
989 {NULL
, NULL
, 0, 0, NULL
, NULL
, NULL
}};
990 enum nss_status status
;
992 __libc_lock_lock (lock
);
996 __nss_database_lookup ("passwd_compat", NULL
, "nis", &ni
);
997 use_nisplus
= (strcmp (ni
->name
, "nisplus") == 0);
1000 __libc_lock_unlock (lock
);
1002 status
= internal_setpwent (&ent
);
1003 if (status
!= NSS_STATUS_SUCCESS
)
1006 while ((status
= internal_getpwent_r (pwd
, &ent
, buffer
, buflen
))
1007 == NSS_STATUS_SUCCESS
)
1008 if (pwd
->pw_uid
== uid
&& pwd
->pw_name
[0] != '+' && pwd
->pw_name
[0] != '-')
1011 internal_endpwent (&ent
);
1016 /* Support routines for remembering -@netgroup and -user entries.
1017 The names are stored in a single string with `|' as separator. */
1019 blacklist_store_name (const char *name
, ent_t
*ent
)
1021 int namelen
= strlen (name
);
1024 /* first call, setup cache */
1025 if (ent
->blacklist
.size
== 0)
1027 ent
->blacklist
.size
= MAX (BLACKLIST_INITIAL_SIZE
, 2 * namelen
);
1028 ent
->blacklist
.data
= malloc (ent
->blacklist
.size
);
1029 if (ent
->blacklist
.data
== NULL
)
1031 ent
->blacklist
.data
[0] = '|';
1032 ent
->blacklist
.data
[1] = '\0';
1033 ent
->blacklist
.current
= 1;
1037 if (in_blacklist (name
, namelen
, ent
))
1038 return; /* no duplicates */
1040 if (ent
->blacklist
.current
+ namelen
+ 1 >= ent
->blacklist
.size
)
1042 ent
->blacklist
.size
+= MAX (BLACKLIST_INCREMENT
, 2 * namelen
);
1043 tmp
= realloc (ent
->blacklist
.data
, ent
->blacklist
.size
);
1046 free (ent
->blacklist
.data
);
1047 ent
->blacklist
.size
= 0;
1050 ent
->blacklist
.data
= tmp
;
1054 tmp
= stpcpy (ent
->blacklist
.data
+ ent
->blacklist
.current
, name
);
1057 ent
->blacklist
.current
+= namelen
+ 1;
1062 /* returns TRUE if ent->blacklist contains name, else FALSE */
1064 in_blacklist (const char *name
, int namelen
, ent_t
*ent
)
1066 char buf
[namelen
+ 3];
1069 if (ent
->blacklist
.data
== NULL
)
1073 cp
= stpcpy (&buf
[1], name
);
1076 return strstr (ent
->blacklist
.data
, buf
) != NULL
;