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. */
26 #include <libc-lock.h>
27 #include <rpcsvc/yp.h>
28 #include <rpcsvc/ypclnt.h>
29 #include <rpcsvc/nis.h>
30 #include <rpcsvc/nislib.h>
34 #include "nss-nisplus.h"
36 static service_user
*ni
= NULL
;
37 static bool_t use_nisplus
= FALSE
; /* default: passwd_compat: nis */
39 /* Get the declaration of the parser function. */
41 #define STRUCTURE passwd
43 #include "../../nss/nss_files/files-parse.c"
45 /* Structure for remembering -@netgroup and -user members ... */
46 #define BLACKLIST_INITIAL_SIZE 512
47 #define BLACKLIST_INCREMENT 256
66 struct blacklist_t blacklist
;
68 struct __netgrent netgrdata
;
70 typedef struct ent_t ent_t
;
72 static ent_t ext_ent
= {0, 0, 0, NULL
, 0, NULL
, NULL
, 0, NULL
, {NULL
, 0, 0},
73 {NULL
, NULL
, 0, 0, NULL
, NULL
, NULL
}};
75 /* Protect global state against multiple changers. */
76 __libc_lock_define_initialized (static, lock
)
78 /* Prototypes for local functions. */
79 static void blacklist_store_name (const char *, ent_t
*);
80 static int in_blacklist (const char *, int, ent_t
*);
81 extern int _nss_nisplus_parse_pwent (nis_result
*, struct passwd
*,
84 give_pwd_free (struct passwd
*pwd
)
86 if (pwd
->pw_name
!= NULL
)
88 if (pwd
->pw_passwd
!= NULL
)
89 free (pwd
->pw_passwd
);
90 if (pwd
->pw_gecos
!= NULL
)
92 if (pwd
->pw_dir
!= NULL
)
94 if (pwd
->pw_shell
!= NULL
)
97 memset (pwd
, '\0', sizeof (struct passwd
));
101 pwd_need_buflen (struct passwd
*pwd
)
105 if (pwd
->pw_passwd
!= NULL
)
106 len
+= strlen (pwd
->pw_passwd
) + 1;
108 if (pwd
->pw_gecos
!= NULL
)
109 len
+= strlen (pwd
->pw_gecos
) + 1;
111 if (pwd
->pw_dir
!= NULL
)
112 len
+= strlen (pwd
->pw_dir
) + 1;
114 if (pwd
->pw_shell
!= NULL
)
115 len
+= strlen (pwd
->pw_shell
) + 1;
121 copy_pwd_changes (struct passwd
*dest
, struct passwd
*src
,
122 char *buffer
, size_t buflen
)
124 if (src
->pw_passwd
!= NULL
&& strlen (src
->pw_passwd
))
127 dest
->pw_passwd
= strdup (src
->pw_passwd
);
128 else if (dest
->pw_passwd
&&
129 strlen (dest
->pw_passwd
) >= strlen (src
->pw_passwd
))
130 strcpy (dest
->pw_passwd
, src
->pw_passwd
);
133 dest
->pw_passwd
= buffer
;
134 strcpy (dest
->pw_passwd
, src
->pw_passwd
);
135 buffer
+= strlen (dest
->pw_passwd
) + 1;
136 buflen
= buflen
- (strlen (dest
->pw_passwd
) + 1);
140 if (src
->pw_gecos
!= NULL
&& strlen (src
->pw_gecos
))
143 dest
->pw_gecos
= strdup (src
->pw_gecos
);
144 else if (dest
->pw_gecos
&&
145 strlen (dest
->pw_gecos
) >= strlen (src
->pw_gecos
))
146 strcpy (dest
->pw_gecos
, src
->pw_gecos
);
149 dest
->pw_gecos
= buffer
;
150 strcpy (dest
->pw_gecos
, src
->pw_gecos
);
151 buffer
+= strlen (dest
->pw_gecos
) + 1;
152 buflen
= buflen
- (strlen (dest
->pw_gecos
) + 1);
155 if (src
->pw_dir
!= NULL
&& strlen (src
->pw_dir
))
158 dest
->pw_dir
= strdup (src
->pw_dir
);
159 else if (dest
->pw_dir
&&
160 strlen (dest
->pw_dir
) >= strlen (src
->pw_dir
))
161 strcpy (dest
->pw_dir
, src
->pw_dir
);
164 dest
->pw_dir
= buffer
;
165 strcpy (dest
->pw_dir
, src
->pw_dir
);
166 buffer
+= strlen (dest
->pw_dir
) + 1;
167 buflen
= buflen
- (strlen (dest
->pw_dir
) + 1);
171 if (src
->pw_shell
!= NULL
&& strlen (src
->pw_shell
))
174 dest
->pw_shell
= strdup (src
->pw_shell
);
175 else if (dest
->pw_shell
&&
176 strlen (dest
->pw_shell
) >= strlen (src
->pw_shell
))
177 strcpy (dest
->pw_shell
, src
->pw_shell
);
180 dest
->pw_shell
= buffer
;
181 strcpy (dest
->pw_shell
, src
->pw_shell
);
182 buffer
+= strlen (dest
->pw_shell
) + 1;
183 buflen
= buflen
- (strlen (dest
->pw_shell
) + 1);
188 static enum nss_status
189 internal_setpwent (ent_t
*ent
)
191 enum nss_status status
= NSS_STATUS_SUCCESS
;
193 ent
->nis
= ent
->first
= ent
->netgroup
= 0;
195 /* If something was left over free it. */
197 __internal_endnetgrent (&ent
->netgrdata
);
199 if (ent
->oldkey
!= NULL
)
206 if (ent
->result
!= NULL
)
208 nis_freeresult (ent
->result
);
212 if (ent
->names
!= NULL
)
214 nis_freenames (ent
->names
);
218 ent
->blacklist
.current
= 0;
219 if (ent
->blacklist
.data
!= NULL
)
220 ent
->blacklist
.data
[0] = '\0';
222 if (ent
->stream
== NULL
)
224 ent
->stream
= fopen ("/etc/passwd", "r");
226 if (ent
->stream
== NULL
)
227 status
= errno
== EAGAIN
? NSS_STATUS_TRYAGAIN
: NSS_STATUS_UNAVAIL
;
230 rewind (ent
->stream
);
232 give_pwd_free (&ent
->pwd
);
239 _nss_compat_setpwent (void)
241 enum nss_status result
;
243 __libc_lock_lock (lock
);
247 __nss_database_lookup ("passwd_compat", NULL
, "nis", &ni
);
248 use_nisplus
= (strcmp (ni
->name
, "nisplus") == 0);
251 result
= internal_setpwent (&ext_ent
);
253 __libc_lock_unlock (lock
);
259 static enum nss_status
260 internal_endpwent (ent_t
*ent
)
262 if (ent
->stream
!= NULL
)
264 fclose (ent
->stream
);
268 ent
->nis
= ent
->first
= ent
->netgroup
= 0;
270 if (ent
->oldkey
!= NULL
)
277 if (ent
->result
!= NULL
)
279 nis_freeresult (ent
->result
);
283 if (ent
->names
!= NULL
)
285 nis_freenames (ent
->names
);
290 ent
->blacklist
.current
= 0;
291 if (ent
->blacklist
.data
!= NULL
)
292 ent
->blacklist
.data
[0] = '\0';
294 give_pwd_free (&ent
->pwd
);
296 return NSS_STATUS_SUCCESS
;
300 _nss_compat_endpwent (void)
302 enum nss_status result
;
304 __libc_lock_lock (lock
);
306 if (ext_ent
.netgroup
)
307 __internal_endnetgrent (&ext_ent
.netgrdata
);
309 result
= internal_endpwent (&ext_ent
);
311 __libc_lock_unlock (lock
);
316 static enum nss_status
317 getpwent_next_nis_netgr (struct passwd
*result
, ent_t
*ent
, char *group
,
318 char *buffer
, size_t buflen
)
320 struct parser_data
*data
= (void *) buffer
;
321 char *ypdomain
, *host
, *user
, *domain
, *outval
, *p
, *p2
;
322 int status
, outvallen
;
325 if (yp_get_default_domain (&ypdomain
) != YPERR_SUCCESS
)
329 give_pwd_free (&ent
->pwd
);
330 return NSS_STATUS_UNAVAIL
;
333 if (ent
->first
== TRUE
)
335 memset (&ent
->netgrdata
, 0, sizeof (struct __netgrent
));
336 __internal_setnetgrent (group
, &ent
->netgrdata
);
342 status
= __internal_getnetgrent_r (&host
, &user
, &domain
,
343 &ent
->netgrdata
, buffer
, buflen
);
346 __internal_endnetgrent (&ent
->netgrdata
);
348 give_pwd_free (&ent
->pwd
);
349 return NSS_STATUS_RETURN
;
352 if (user
== NULL
|| user
[0] == '-')
355 if (domain
!= NULL
&& strcmp (ypdomain
, domain
) != 0)
358 if (yp_match (ypdomain
, "passwd.byname", user
,
359 strlen (user
), &outval
, &outvallen
)
363 p2len
= pwd_need_buflen (&ent
->pwd
);
366 __set_errno (ERANGE
);
367 return NSS_STATUS_TRYAGAIN
;
369 p2
= buffer
+ (buflen
- p2len
);
371 p
= strncpy (buffer
, outval
, buflen
);
375 if (_nss_files_parse_pwent (p
, result
, data
, buflen
))
377 copy_pwd_changes (result
, &ent
->pwd
, p2
, p2len
);
382 return NSS_STATUS_SUCCESS
;
385 static enum nss_status
386 getpwent_next_nisplus_netgr (struct passwd
*result
, ent_t
*ent
, char *group
,
387 char *buffer
, size_t buflen
)
389 char *ypdomain
, *host
, *user
, *domain
, *p2
;
390 int status
, parse_res
;
394 /* Maybe we should use domainname here ? We need the current
395 domainname for the domain field in netgroups */
396 if (yp_get_default_domain (&ypdomain
) != YPERR_SUCCESS
)
400 give_pwd_free (&ent
->pwd
);
401 return NSS_STATUS_UNAVAIL
;
404 if (ent
->first
== TRUE
)
406 bzero (&ent
->netgrdata
, sizeof (struct __netgrent
));
407 __internal_setnetgrent (group
, &ent
->netgrdata
);
413 status
= __internal_getnetgrent_r (&host
, &user
, &domain
,
414 &ent
->netgrdata
, buffer
, buflen
);
417 __internal_endnetgrent (&ent
->netgrdata
);
419 give_pwd_free (&ent
->pwd
);
420 return NSS_STATUS_RETURN
;
423 if (user
== NULL
|| user
[0] == '-')
426 if (domain
!= NULL
&& strcmp (ypdomain
, domain
) != 0)
429 p2len
= pwd_need_buflen (&ent
->pwd
);
432 __set_errno (ERANGE
);
433 return NSS_STATUS_TRYAGAIN
;
435 p2
= buffer
+ (buflen
- p2len
);
438 char buf
[strlen (user
) + 30];
439 sprintf(buf
, "[name=%s],passwd.org_dir", user
);
440 nisres
= nis_list(buf
, EXPAND_NAME
, NULL
, NULL
);
442 if (niserr2nss (nisres
->status
) != NSS_STATUS_SUCCESS
)
444 nis_freeresult (nisres
);
447 parse_res
= _nss_nisplus_parse_pwent (nisres
, result
, buffer
, buflen
);
448 nis_freeresult (nisres
);
452 copy_pwd_changes (result
, &ent
->pwd
, p2
, p2len
);
457 return NSS_STATUS_SUCCESS
;
460 static enum nss_status
461 getpwent_next_netgr (struct passwd
*result
, ent_t
*ent
, char *group
,
462 char *buffer
, size_t buflen
)
465 return getpwent_next_nisplus_netgr (result
, ent
, group
, buffer
, buflen
);
467 return getpwent_next_nis_netgr (result
, ent
, group
, buffer
, buflen
);
470 static enum nss_status
471 getpwent_next_nisplus (struct passwd
*result
, ent_t
*ent
, char *buffer
,
478 if (ent
->names
== NULL
)
480 ent
->names
= nis_getnames ("passwd.org_dir");
481 if (ent
->names
== NULL
|| ent
->names
[0] == NULL
)
484 return NSS_STATUS_UNAVAIL
;
488 p2len
= pwd_need_buflen (&ent
->pwd
);
491 __set_errno (ERANGE
);
492 return NSS_STATUS_TRYAGAIN
;
494 p2
= buffer
+ (buflen
- p2len
);
501 ent
->result
= nis_first_entry(ent
->names
[ent
->names_nr
]);
502 if (niserr2nss (ent
->result
->status
) != NSS_STATUS_SUCCESS
)
505 give_pwd_free (&ent
->pwd
);
506 return niserr2nss (ent
->result
->status
);
514 res
= nis_next_entry(ent
->names
[ent
->names_nr
],
515 &ent
->result
->cookie
);
516 nis_freeresult (ent
->result
);
518 if (niserr2nss (ent
->result
->status
) != NSS_STATUS_SUCCESS
)
520 if ((ent
->result
->status
== NIS_NOTFOUND
) &&
521 ent
->names
[ent
->names_nr
+ 1] != NULL
)
523 nis_freeresult (ent
->result
);
530 give_pwd_free (&ent
->pwd
);
531 return niserr2nss (ent
->result
->status
);
535 parse_res
= _nss_nisplus_parse_pwent (ent
->result
, result
, buffer
,
538 in_blacklist (result
->pw_name
, strlen (result
->pw_name
), ent
))
539 parse_res
= 0; /* if result->pw_name in blacklist,search next entry */
543 copy_pwd_changes (result
, &ent
->pwd
, p2
, p2len
);
545 return NSS_STATUS_SUCCESS
;
548 static enum nss_status
549 getpwent_next_nis (struct passwd
*result
, ent_t
*ent
, char *buffer
,
552 struct parser_data
*data
= (void *) buffer
;
553 char *domain
, *outkey
, *outval
, *p
, *p2
;
554 int outkeylen
, outvallen
, parse_res
;
557 if (yp_get_default_domain (&domain
) != YPERR_SUCCESS
)
560 give_pwd_free (&ent
->pwd
);
561 return NSS_STATUS_UNAVAIL
;
564 p2len
= pwd_need_buflen (&ent
->pwd
);
567 __set_errno (ERANGE
);
568 return NSS_STATUS_TRYAGAIN
;
570 p2
= buffer
+ (buflen
- p2len
);
576 if (yp_first (domain
, "passwd.byname", &outkey
, &outkeylen
,
577 &outval
, &outvallen
) != YPERR_SUCCESS
)
580 give_pwd_free (&ent
->pwd
);
581 return NSS_STATUS_UNAVAIL
;
584 ent
->oldkey
= outkey
;
585 ent
->oldkeylen
= outkeylen
;
590 if (yp_next (domain
, "passwd.byname", ent
->oldkey
, ent
->oldkeylen
,
591 &outkey
, &outkeylen
, &outval
, &outvallen
)
595 give_pwd_free (&ent
->pwd
);
596 return NSS_STATUS_NOTFOUND
;
600 ent
->oldkey
= outkey
;
601 ent
->oldkeylen
= outkeylen
;
604 /* Copy the found data to our buffer */
605 p
= strncpy (buffer
, outval
, buflen
);
607 /* ...and free the data. */
612 parse_res
= _nss_files_parse_pwent (p
, result
, data
, buflen
);
614 in_blacklist (result
->pw_name
, strlen (result
->pw_name
), ent
))
619 copy_pwd_changes (result
, &ent
->pwd
, p2
, p2len
);
621 return NSS_STATUS_SUCCESS
;
624 /* This function handle the +user entrys in /etc/passwd */
625 static enum nss_status
626 getpwent_next_file_plususer (struct passwd
*result
, char *buffer
,
629 struct parser_data
*data
= (void *) buffer
;
635 memset (&pwd
, '\0', sizeof (struct passwd
));
637 copy_pwd_changes (&pwd
, result
, NULL
, 0);
639 plen
= pwd_need_buflen (&pwd
);
642 __set_errno (ERANGE
);
643 return NSS_STATUS_TRYAGAIN
;
645 p
= buffer
+ (buflen
- plen
);
648 if (use_nisplus
) /* Do the NIS+ query here */
651 char buf
[strlen (result
->pw_name
) + 24];
653 sprintf(buf
, "[name=%s],passwd.org_dir",
654 &result
->pw_name
[1]);
655 res
= nis_list(buf
, EXPAND_NAME
, NULL
, NULL
);
656 if (niserr2nss (res
->status
) != NSS_STATUS_SUCCESS
)
658 enum nss_status status
= niserr2nss (res
->status
);
660 nis_freeresult (res
);
663 parse_res
= _nss_nisplus_parse_pwent (res
, result
, buffer
, buflen
);
664 nis_freeresult (res
);
672 if (yp_get_default_domain (&domain
) != YPERR_SUCCESS
)
673 return NSS_STATUS_TRYAGAIN
;
675 if (yp_match (domain
, "passwd.byname", &result
->pw_name
[1],
676 strlen (result
->pw_name
) - 1, &outval
, &outvallen
)
678 return NSS_STATUS_TRYAGAIN
;
679 p
= strncpy (buffer
, outval
,
680 buflen
< (size_t) outvallen
? buflen
: (size_t) outvallen
);
684 parse_res
= _nss_files_parse_pwent (p
, result
, data
, buflen
);
689 copy_pwd_changes (result
, &pwd
, p
, plen
);
690 give_pwd_free (&pwd
);
691 /* We found the entry. */
692 return NSS_STATUS_SUCCESS
;
696 /* Give buffer the old len back */
698 give_pwd_free (&pwd
);
700 return NSS_STATUS_RETURN
;
703 static enum nss_status
704 getpwent_next_file (struct passwd
*result
, ent_t
*ent
,
705 char *buffer
, size_t buflen
)
707 struct parser_data
*data
= (void *) buffer
;
714 p
= fgets (buffer
, buflen
, ent
->stream
);
716 return NSS_STATUS_NOTFOUND
;
718 /* Terminate the line for any case. */
719 buffer
[buflen
- 1] = '\0';
721 /* Skip leading blanks. */
725 while (*p
== '\0' || *p
== '#' || /* Ignore empty and comment lines. */
726 /* Parse the line. If it is invalid, loop to
727 get the next line of the file to parse. */
728 !_nss_files_parse_pwent (p
, result
, data
, buflen
));
730 if (result
->pw_name
[0] != '+' && result
->pw_name
[0] != '-')
731 /* This is a real entry. */
735 if (result
->pw_name
[0] == '-' && result
->pw_name
[1] == '@'
736 && result
->pw_name
[2] != '\0')
739 char *user
, *host
, *domain
;
740 struct __netgrent netgrdata
;
742 bzero (&netgrdata
, sizeof (struct __netgrent
));
743 __internal_setnetgrent (&result
->pw_name
[2], &netgrdata
);
744 while (__internal_getnetgrent_r (&host
, &user
, &domain
,
745 &netgrdata
, buf2
, sizeof (buf2
)))
747 if (user
!= NULL
&& user
[0] != '-')
748 blacklist_store_name (user
, ent
);
750 __internal_endnetgrent (&netgrdata
);
755 if (result
->pw_name
[0] == '+' && result
->pw_name
[1] == '@'
756 && result
->pw_name
[2] != '\0')
760 ent
->netgroup
= TRUE
;
762 copy_pwd_changes (&ent
->pwd
, result
, NULL
, 0);
764 status
= getpwent_next_netgr (result
, ent
, &result
->pw_name
[2],
766 if (status
== NSS_STATUS_RETURN
)
773 if (result
->pw_name
[0] == '-' && result
->pw_name
[1] != '\0'
774 && result
->pw_name
[1] != '@')
776 blacklist_store_name (&result
->pw_name
[1], ent
);
781 if (result
->pw_name
[0] == '+' && result
->pw_name
[1] != '\0'
782 && result
->pw_name
[1] != '@')
784 enum nss_status status
;
786 status
= getpwent_next_file_plususer (result
, buffer
, buflen
);
787 if (status
== NSS_STATUS_SUCCESS
) /* We found the entry. */
790 if (status
== NSS_STATUS_RETURN
) /* We couldn't parse the entry */
797 if (result
->pw_name
[0] == '+' && result
->pw_name
[1] == '\0')
801 copy_pwd_changes (&ent
->pwd
, result
, NULL
, 0);
804 return getpwent_next_nisplus (result
, ent
, buffer
, buflen
);
806 return getpwent_next_nis (result
, ent
, buffer
, buflen
);
810 return NSS_STATUS_SUCCESS
;
814 static enum nss_status
815 internal_getpwent_r (struct passwd
*pw
, ent_t
*ent
, char *buffer
,
822 /* We are searching members in a netgroup */
823 /* Since this is not the first call, we don't need the group name */
824 status
= getpwent_next_netgr (pw
, ent
, NULL
, buffer
, buflen
);
825 if (status
== NSS_STATUS_RETURN
)
826 return getpwent_next_file (pw
, ent
, buffer
, buflen
);
833 return getpwent_next_nisplus (pw
, ent
, buffer
, buflen
);
835 return getpwent_next_nis (pw
, ent
, buffer
, buflen
);
838 return getpwent_next_file (pw
, ent
, buffer
, buflen
);
842 _nss_compat_getpwent_r (struct passwd
*pwd
, char *buffer
,
845 enum nss_status status
= NSS_STATUS_SUCCESS
;
847 __libc_lock_lock (lock
);
851 __nss_database_lookup ("passwd_compat", NULL
, "nis", &ni
);
852 use_nisplus
= (strcmp (ni
->name
, "nisplus") == 0);
855 /* Be prepared that the setpwent function was not called before. */
856 if (ext_ent
.stream
== NULL
)
857 status
= internal_setpwent (&ext_ent
);
859 if (status
== NSS_STATUS_SUCCESS
)
860 status
= internal_getpwent_r (pwd
, &ext_ent
, buffer
, buflen
);
862 __libc_lock_unlock (lock
);
869 _nss_compat_getpwnam_r (const char *name
, struct passwd
*pwd
,
870 char *buffer
, size_t buflen
)
872 ent_t ent
= {0, 0, 0, NULL
, 0, NULL
, NULL
, 0, NULL
, {NULL
, 0, 0},
873 {NULL
, NULL
, 0, 0, NULL
, NULL
, NULL
}};
874 enum nss_status status
;
876 if (name
[0] == '-' || name
[0] == '+')
877 return NSS_STATUS_NOTFOUND
;
879 __libc_lock_lock (lock
);
883 __nss_database_lookup ("passwd_compat", NULL
, "nis", &ni
);
884 use_nisplus
= (strcmp (ni
->name
, "nisplus") == 0);
887 __libc_lock_unlock (lock
);
889 status
= internal_setpwent (&ent
);
890 if (status
!= NSS_STATUS_SUCCESS
)
893 while ((status
= internal_getpwent_r (pwd
, &ent
, buffer
, buflen
))
894 == NSS_STATUS_SUCCESS
)
895 if (strcmp (pwd
->pw_name
, name
) == 0)
898 internal_endpwent (&ent
);
904 _nss_compat_getpwuid_r (uid_t uid
, struct passwd
*pwd
,
905 char *buffer
, size_t buflen
)
907 ent_t ent
= {0, 0, 0, NULL
, 0, NULL
, NULL
, 0, NULL
, {NULL
, 0, 0},
908 {NULL
, NULL
, 0, 0, NULL
, NULL
, NULL
}};
909 enum nss_status status
;
911 __libc_lock_lock (lock
);
915 __nss_database_lookup ("passwd_compat", NULL
, "nis", &ni
);
916 use_nisplus
= (strcmp (ni
->name
, "nisplus") == 0);
919 __libc_lock_unlock (lock
);
921 status
= internal_setpwent (&ent
);
922 if (status
!= NSS_STATUS_SUCCESS
)
925 while ((status
= internal_getpwent_r (pwd
, &ent
, buffer
, buflen
))
926 == NSS_STATUS_SUCCESS
)
927 if (pwd
->pw_uid
== uid
&& pwd
->pw_name
[0] != '+' && pwd
->pw_name
[0] != '-')
930 internal_endpwent (&ent
);
935 /* Support routines for remembering -@netgroup and -user entries.
936 The names are stored in a single string with `|' as separator. */
938 blacklist_store_name (const char *name
, ent_t
*ent
)
940 int namelen
= strlen (name
);
943 /* first call, setup cache */
944 if (ent
->blacklist
.size
== 0)
946 ent
->blacklist
.size
= MAX (BLACKLIST_INITIAL_SIZE
, 2 * namelen
);
947 ent
->blacklist
.data
= malloc (ent
->blacklist
.size
);
948 if (ent
->blacklist
.data
== NULL
)
950 ent
->blacklist
.data
[0] = '|';
951 ent
->blacklist
.data
[1] = '\0';
952 ent
->blacklist
.current
= 1;
956 if (in_blacklist (name
, namelen
, ent
))
957 return; /* no duplicates */
959 if (ent
->blacklist
.current
+ namelen
+ 1 >= ent
->blacklist
.size
)
961 ent
->blacklist
.size
+= MAX (BLACKLIST_INCREMENT
, 2 * namelen
);
962 tmp
= realloc (ent
->blacklist
.data
, ent
->blacklist
.size
);
965 free (ent
->blacklist
.data
);
966 ent
->blacklist
.size
= 0;
969 ent
->blacklist
.data
= tmp
;
973 tmp
= stpcpy (ent
->blacklist
.data
+ ent
->blacklist
.current
, name
);
976 ent
->blacklist
.current
+= namelen
+ 1;
981 /* returns TRUE if ent->blacklist contains name, else FALSE */
983 in_blacklist (const char *name
, int namelen
, ent_t
*ent
)
985 char buf
[namelen
+ 3];
988 if (ent
->blacklist
.data
== NULL
)
992 cp
= stpcpy (&buf
[1], name
);
995 return strstr (ent
->blacklist
.data
, buf
) != NULL
;