]> sourceware.org Git - glibc.git/blob - nis/nss_compat/compat-pwd.c
Update.
[glibc.git] / nis / nss_compat / compat-pwd.c
1 /* Copyright (C) 1996, 1997, 1998 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.
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 <nss.h>
21 #include <pwd.h>
22 #include <errno.h>
23 #include <ctype.h>
24 #include <fcntl.h>
25 #include <netdb.h>
26 #include <string.h>
27 #include <bits/libc-lock.h>
28 #include <rpcsvc/yp.h>
29 #include <rpcsvc/ypclnt.h>
30 #include <rpcsvc/nis.h>
31 #include <nsswitch.h>
32
33 #include "netgroup.h"
34 #include "nss-nisplus.h"
35 #include "nisplus-parser.h"
36
37 static service_user *ni = NULL;
38 static bool_t use_nisplus = FALSE; /* default: passwd_compat: nis */
39 static nis_name pwdtable = NULL; /* Name of the pwd table */
40 static size_t pwdtablelen = 0;
41
42 /* Get the declaration of the parser function. */
43 #define ENTNAME pwent
44 #define STRUCTURE passwd
45 #define EXTERN_PARSER
46 #include <nss/nss_files/files-parse.c>
47
48 /* Structure for remembering -@netgroup and -user members ... */
49 #define BLACKLIST_INITIAL_SIZE 512
50 #define BLACKLIST_INCREMENT 256
51 struct blacklist_t
52 {
53 char *data;
54 int current;
55 int size;
56 };
57
58 struct ent_t
59 {
60 bool_t netgroup;
61 bool_t nis;
62 bool_t first;
63 char *oldkey;
64 int oldkeylen;
65 nis_result *result;
66 FILE *stream;
67 struct blacklist_t blacklist;
68 struct passwd pwd;
69 struct __netgrent netgrdata;
70 };
71 typedef struct ent_t ent_t;
72
73 static ent_t ext_ent = {0, 0, 0, NULL, 0, NULL, NULL, {NULL, 0, 0},
74 {NULL, NULL, 0, 0, NULL, NULL, NULL}};
75
76 /* Protect global state against multiple changers. */
77 __libc_lock_define_initialized (static, lock)
78
79 /* Prototypes for local functions. */
80 static void blacklist_store_name (const char *, ent_t *);
81 static int in_blacklist (const char *, int, ent_t *);
82
83 static void
84 give_pwd_free (struct passwd *pwd)
85 {
86 if (pwd->pw_name != NULL)
87 free (pwd->pw_name);
88 if (pwd->pw_passwd != NULL)
89 free (pwd->pw_passwd);
90 if (pwd->pw_gecos != NULL)
91 free (pwd->pw_gecos);
92 if (pwd->pw_dir != NULL)
93 free (pwd->pw_dir);
94 if (pwd->pw_shell != NULL)
95 free (pwd->pw_shell);
96
97 memset (pwd, '\0', sizeof (struct passwd));
98 }
99
100 static size_t
101 pwd_need_buflen (struct passwd *pwd)
102 {
103 size_t len = 0;
104
105 if (pwd->pw_passwd != NULL)
106 len += strlen (pwd->pw_passwd) + 1;
107
108 if (pwd->pw_gecos != NULL)
109 len += strlen (pwd->pw_gecos) + 1;
110
111 if (pwd->pw_dir != NULL)
112 len += strlen (pwd->pw_dir) + 1;
113
114 if (pwd->pw_shell != NULL)
115 len += strlen (pwd->pw_shell) + 1;
116
117 return len;
118 }
119
120 static void
121 copy_pwd_changes (struct passwd *dest, struct passwd *src,
122 char *buffer, size_t buflen)
123 {
124 if (src->pw_passwd != NULL && strlen (src->pw_passwd))
125 {
126 if (buffer == NULL)
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);
131 else
132 {
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);
137 }
138 }
139
140 if (src->pw_gecos != NULL && strlen (src->pw_gecos))
141 {
142 if (buffer == NULL)
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);
147 else
148 {
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);
153 }
154 }
155 if (src->pw_dir != NULL && strlen (src->pw_dir))
156 {
157 if (buffer == NULL)
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);
162 else
163 {
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);
168 }
169 }
170
171 if (src->pw_shell != NULL && strlen (src->pw_shell))
172 {
173 if (buffer == NULL)
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);
178 else
179 {
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);
184 }
185 }
186 }
187
188 static enum nss_status
189 internal_setpwent (ent_t *ent)
190 {
191 enum nss_status status = NSS_STATUS_SUCCESS;
192
193 ent->nis = ent->first = ent->netgroup = 0;
194
195 /* If something was left over free it. */
196 if (ent->netgroup)
197 __internal_endnetgrent (&ent->netgrdata);
198
199 if (ent->oldkey != NULL)
200 {
201 free (ent->oldkey);
202 ent->oldkey = NULL;
203 ent->oldkeylen = 0;
204 }
205
206 if (ent->result != NULL)
207 {
208 nis_freeresult (ent->result);
209 ent->result = NULL;
210 }
211
212 if (pwdtable == NULL)
213 {
214 static const char key[] = "passwd.org_dir.";
215 const char *local_dir = nis_local_directory ();
216 size_t len_local_dir = strlen (local_dir);
217
218 pwdtable = malloc (sizeof (key) + len_local_dir);
219 if (pwdtable == NULL)
220 return NSS_STATUS_TRYAGAIN;
221
222 pwdtablelen = ((char *) mempcpy (mempcpy (pwdtable,
223 key, sizeof (key) - 1),
224 local_dir, len_local_dir + 1)
225 - pwdtable) - 1;
226 }
227
228 if (ent->blacklist.data != NULL)
229 {
230 ent->blacklist.current = 1;
231 ent->blacklist.data[0] = '|';
232 ent->blacklist.data[1] = '\0';
233 }
234 else
235 ent->blacklist.current = 0;
236
237 if (ent->stream == NULL)
238 {
239 ent->stream = fopen ("/etc/passwd", "r");
240
241 if (ent->stream == NULL)
242 status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
243 else
244 {
245 /* We have to make sure the file is `closed on exec'. */
246 int result, flags;
247
248 result = flags = fcntl (fileno (ent->stream), F_GETFD, 0);
249 if (result >= 0)
250 {
251 flags |= FD_CLOEXEC;
252 result = fcntl (fileno (ent->stream), F_SETFD, flags);
253 }
254 if (result < 0)
255 {
256 /* Something went wrong. Close the stream and return a
257 failure. */
258 fclose (ent->stream);
259 ent->stream = NULL;
260 status = NSS_STATUS_UNAVAIL;
261 }
262 }
263 }
264 else
265 rewind (ent->stream);
266
267 give_pwd_free (&ent->pwd);
268
269 return status;
270 }
271
272
273 enum nss_status
274 _nss_compat_setpwent (void)
275 {
276 enum nss_status result;
277
278 __libc_lock_lock (lock);
279
280 if (ni == NULL)
281 {
282 __nss_database_lookup ("passwd_compat", NULL, "nis", &ni);
283 use_nisplus = (strcmp (ni->name, "nisplus") == 0);
284 }
285
286 result = internal_setpwent (&ext_ent);
287
288 __libc_lock_unlock (lock);
289
290 return result;
291 }
292
293
294 static enum nss_status
295 internal_endpwent (ent_t *ent)
296 {
297 if (ent->stream != NULL)
298 {
299 fclose (ent->stream);
300 ent->stream = NULL;
301 }
302
303 if (ent->netgroup)
304 __internal_endnetgrent (&ent->netgrdata);
305
306 ent->nis = ent->first = ent->netgroup = 0;
307
308 if (ent->oldkey != NULL)
309 {
310 free (ent->oldkey);
311 ent->oldkey = NULL;
312 ent->oldkeylen = 0;
313 }
314
315 if (ent->result != NULL)
316 {
317 nis_freeresult (ent->result);
318 ent->result = NULL;
319 }
320
321 if (ent->blacklist.data != NULL)
322 {
323 ent->blacklist.current = 1;
324 ent->blacklist.data[0] = '|';
325 ent->blacklist.data[1] = '\0';
326 }
327 else
328 ent->blacklist.current = 0;
329
330 give_pwd_free (&ent->pwd);
331
332 return NSS_STATUS_SUCCESS;
333 }
334
335 enum nss_status
336 _nss_compat_endpwent (void)
337 {
338 enum nss_status result;
339
340 __libc_lock_lock (lock);
341
342 result = internal_endpwent (&ext_ent);
343
344 __libc_lock_unlock (lock);
345
346 return result;
347 }
348
349 static enum nss_status
350 getpwent_next_nis_netgr (const char *name, struct passwd *result, ent_t *ent,
351 char *group, char *buffer, size_t buflen, int *errnop)
352 {
353 struct parser_data *data = (void *) buffer;
354 char *ypdomain, *host, *user, *domain, *outval, *p, *p2;
355 int status, outvallen;
356 size_t p2len;
357
358 if (yp_get_default_domain (&ypdomain) != YPERR_SUCCESS)
359 {
360 ent->netgroup = 0;
361 ent->first = 0;
362 give_pwd_free (&ent->pwd);
363 return NSS_STATUS_UNAVAIL;
364 }
365
366 if (ent->first == TRUE)
367 {
368 memset (&ent->netgrdata, 0, sizeof (struct __netgrent));
369 __internal_setnetgrent (group, &ent->netgrdata);
370 ent->first = FALSE;
371 }
372
373 while (1)
374 {
375 char *saved_cursor;
376 int parse_res;
377
378 saved_cursor = ent->netgrdata.cursor;
379 status = __internal_getnetgrent_r (&host, &user, &domain,
380 &ent->netgrdata, buffer, buflen,
381 errnop);
382 if (status != 1)
383 {
384 __internal_endnetgrent (&ent->netgrdata);
385 ent->netgroup = 0;
386 give_pwd_free (&ent->pwd);
387 return NSS_STATUS_RETURN;
388 }
389
390 if (user == NULL || user[0] == '-')
391 continue;
392
393 if (domain != NULL && strcmp (ypdomain, domain) != 0)
394 continue;
395
396 /* If name != NULL, we are called from getpwnam */
397 if (name != NULL)
398 if (strcmp (user, name) != 0)
399 continue;
400
401 if (yp_match (ypdomain, "passwd.byname", user,
402 strlen (user), &outval, &outvallen)
403 != YPERR_SUCCESS)
404 continue;
405
406 p2len = pwd_need_buflen (&ent->pwd);
407 if (p2len > buflen)
408 {
409 *errnop = ERANGE;
410 return NSS_STATUS_TRYAGAIN;
411 }
412 p2 = buffer + (buflen - p2len);
413 buflen -= p2len;
414 p = strncpy (buffer, outval, buflen);
415 while (isspace (*p))
416 p++;
417 free (outval);
418 parse_res = _nss_files_parse_pwent (p, result, data, buflen, errnop);
419 if (parse_res == -1)
420 {
421 ent->netgrdata.cursor = saved_cursor;
422 return NSS_STATUS_TRYAGAIN;
423 }
424
425 if (parse_res)
426 {
427 /* Store the User in the blacklist for the "+" at the end of
428 /etc/passwd */
429 blacklist_store_name (result->pw_name, ent);
430 copy_pwd_changes (result, &ent->pwd, p2, p2len);
431 break;
432 }
433 }
434
435 return NSS_STATUS_SUCCESS;
436 }
437
438 static enum nss_status
439 getpwent_next_nisplus_netgr (const char *name, struct passwd *result,
440 ent_t *ent, char *group, char *buffer,
441 size_t buflen, int *errnop)
442 {
443 char *ypdomain, *host, *user, *domain, *p2;
444 int status, parse_res;
445 size_t p2len;
446 nis_result *nisres;
447
448 /* Maybe we should use domainname here ? We need the current
449 domainname for the domain field in netgroups */
450 if (yp_get_default_domain (&ypdomain) != YPERR_SUCCESS)
451 {
452 ent->netgroup = 0;
453 ent->first = 0;
454 give_pwd_free (&ent->pwd);
455 return NSS_STATUS_UNAVAIL;
456 }
457
458 if (ent->first == TRUE)
459 {
460 bzero (&ent->netgrdata, sizeof (struct __netgrent));
461 __internal_setnetgrent (group, &ent->netgrdata);
462 ent->first = FALSE;
463 }
464
465 while (1)
466 {
467 char *saved_cursor;
468
469 saved_cursor = ent->netgrdata.cursor;
470 status = __internal_getnetgrent_r (&host, &user, &domain,
471 &ent->netgrdata, buffer, buflen,
472 errnop);
473 if (status != 1)
474 {
475 __internal_endnetgrent (&ent->netgrdata);
476 ent->netgroup = 0;
477 give_pwd_free (&ent->pwd);
478 return NSS_STATUS_RETURN;
479 }
480
481 if (user == NULL || user[0] == '-')
482 continue;
483
484 if (domain != NULL && strcmp (ypdomain, domain) != 0)
485 continue;
486
487 /* If name != NULL, we are called from getpwnam */
488 if (name != NULL)
489 if (strcmp (user, name) != 0)
490 continue;
491
492 p2len = pwd_need_buflen (&ent->pwd);
493 if (p2len > buflen)
494 {
495 *errnop = ERANGE;
496 return NSS_STATUS_TRYAGAIN;
497 }
498 p2 = buffer + (buflen - p2len);
499 buflen -= p2len;
500 {
501 char buf[strlen (user) + 30 + pwdtablelen];
502 sprintf(buf, "[name=%s],%s", user, pwdtable);
503 nisres = nis_list(buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
504 }
505 if (niserr2nss (nisres->status) != NSS_STATUS_SUCCESS)
506 {
507 nis_freeresult (nisres);
508 continue;
509 }
510 parse_res = _nss_nisplus_parse_pwent (nisres, result, buffer,
511 buflen, errnop);
512 if (parse_res == -1)
513 {
514 nis_freeresult (nisres);
515 ent->netgrdata.cursor = saved_cursor;
516 *errnop = ERANGE;
517 return NSS_STATUS_TRYAGAIN;
518 }
519 nis_freeresult (nisres);
520
521 if (parse_res)
522 {
523 /* Store the User in the blacklist for the "+" at the end of
524 /etc/passwd */
525 blacklist_store_name (result->pw_name, ent);
526 copy_pwd_changes (result, &ent->pwd, p2, p2len);
527 break;
528 }
529 }
530
531 return NSS_STATUS_SUCCESS;
532 }
533
534 /* get the next user from NIS+ (+ entry) */
535 static enum nss_status
536 getpwent_next_nisplus (struct passwd *result, ent_t *ent, char *buffer,
537 size_t buflen, int *errnop)
538 {
539 int parse_res;
540 size_t p2len;
541 char *p2;
542
543 p2len = pwd_need_buflen (&ent->pwd);
544 if (p2len > buflen)
545 {
546 *errnop = ERANGE;
547 return NSS_STATUS_TRYAGAIN;
548 }
549 p2 = buffer + (buflen - p2len);
550 buflen -= p2len;
551 do
552 {
553 bool_t saved_first;
554 nis_result *saved_res;
555
556 if (ent->first)
557 {
558 saved_first = TRUE;
559 saved_res = ent->result;
560
561 ent->result = nis_first_entry (pwdtable);
562 if (niserr2nss (ent->result->status) != NSS_STATUS_SUCCESS)
563 {
564 ent->nis = 0;
565 give_pwd_free (&ent->pwd);
566 return niserr2nss (ent->result->status);
567 }
568 ent->first = FALSE;
569 }
570 else
571 {
572 nis_result *res;
573
574 res = nis_next_entry (pwdtable, &ent->result->cookie);
575 saved_res = ent->result;
576 saved_first = FALSE;
577 ent->result = res;
578 if (niserr2nss (ent->result->status) != NSS_STATUS_SUCCESS)
579 {
580 ent->nis = 0;
581 nis_freeresult (saved_res);
582 give_pwd_free (&ent->pwd);
583 return niserr2nss (ent->result->status);
584 }
585 }
586 parse_res = _nss_nisplus_parse_pwent (ent->result, result, buffer,
587 buflen, errnop);
588 if (parse_res == -1)
589 {
590 nis_freeresult (ent->result);
591 ent->result = saved_res;
592 ent->first = saved_first;
593 *errnop = ERANGE;
594 return NSS_STATUS_TRYAGAIN;
595 }
596 else
597 {
598 if (!saved_first)
599 nis_freeresult (saved_res);
600 }
601
602 if (parse_res &&
603 in_blacklist (result->pw_name, strlen (result->pw_name), ent))
604 parse_res = 0; /* if result->pw_name in blacklist,search next entry */
605 }
606 while (!parse_res);
607
608 copy_pwd_changes (result, &ent->pwd, p2, p2len);
609
610 return NSS_STATUS_SUCCESS;
611 }
612
613 static enum nss_status
614 getpwent_next_nis (struct passwd *result, ent_t *ent, char *buffer,
615 size_t buflen, int *errnop)
616 {
617 struct parser_data *data = (void *) buffer;
618 char *domain, *outkey, *outval, *p, *p2;
619 int outkeylen, outvallen, parse_res;
620 size_t p2len;
621
622 if (yp_get_default_domain (&domain) != YPERR_SUCCESS)
623 {
624 ent->nis = 0;
625 give_pwd_free (&ent->pwd);
626 return NSS_STATUS_UNAVAIL;
627 }
628
629 p2len = pwd_need_buflen (&ent->pwd);
630 if (p2len > buflen)
631 {
632 *errnop = ERANGE;
633 return NSS_STATUS_TRYAGAIN;
634 }
635 p2 = buffer + (buflen - p2len);
636 buflen -= p2len;
637 do
638 {
639 bool_t saved_first;
640 char *saved_oldkey;
641 int saved_oldlen;
642
643 if (ent->first)
644 {
645 if (yp_first (domain, "passwd.byname", &outkey, &outkeylen,
646 &outval, &outvallen) != YPERR_SUCCESS)
647 {
648 ent->nis = 0;
649 give_pwd_free (&ent->pwd);
650 return NSS_STATUS_UNAVAIL;
651 }
652
653 saved_first = TRUE;
654 saved_oldkey = ent->oldkey;
655 saved_oldlen = ent->oldkeylen;
656 ent->oldkey = outkey;
657 ent->oldkeylen = outkeylen;
658 ent->first = FALSE;
659 }
660 else
661 {
662 if (yp_next (domain, "passwd.byname", ent->oldkey, ent->oldkeylen,
663 &outkey, &outkeylen, &outval, &outvallen)
664 != YPERR_SUCCESS)
665 {
666 ent->nis = 0;
667 give_pwd_free (&ent->pwd);
668 return NSS_STATUS_NOTFOUND;
669 }
670
671 saved_first = FALSE;
672 saved_oldkey = ent->oldkey;
673 saved_oldlen = ent->oldkeylen;
674 ent->oldkey = outkey;
675 ent->oldkeylen = outkeylen;
676 }
677
678 /* Copy the found data to our buffer */
679 p = strncpy (buffer, outval, buflen);
680
681 /* ...and free the data. */
682 free (outval);
683
684 while (isspace (*p))
685 ++p;
686 parse_res = _nss_files_parse_pwent (p, result, data, buflen, errnop);
687 if (parse_res == -1)
688 {
689 free (ent->oldkey);
690 ent->oldkey = saved_oldkey;
691 ent->oldkeylen = saved_oldlen;
692 ent->first = saved_first;
693 *errnop = ERANGE;
694 return NSS_STATUS_TRYAGAIN;
695 }
696 else
697 {
698 if (!saved_first)
699 free (saved_oldkey);
700 }
701 if (parse_res
702 && in_blacklist (result->pw_name, strlen (result->pw_name), ent))
703 parse_res = 0;
704 }
705 while (!parse_res);
706
707 copy_pwd_changes (result, &ent->pwd, p2, p2len);
708
709 return NSS_STATUS_SUCCESS;
710 }
711
712 /* This function handle the +user entrys in /etc/passwd */
713 static enum nss_status
714 getpwnam_plususer (const char *name, struct passwd *result, char *buffer,
715 size_t buflen, int *errnop)
716 {
717 struct parser_data *data = (void *) buffer;
718 struct passwd pwd;
719 int parse_res;
720 char *p;
721 size_t plen;
722
723 memset (&pwd, '\0', sizeof (struct passwd));
724
725 copy_pwd_changes (&pwd, result, NULL, 0);
726
727 plen = pwd_need_buflen (&pwd);
728 if (plen > buflen)
729 {
730 *errnop = ERANGE;
731 return NSS_STATUS_TRYAGAIN;
732 }
733 p = buffer + (buflen - plen);
734 buflen -= plen;
735
736 if (use_nisplus) /* Do the NIS+ query here */
737 {
738 nis_result *res;
739 char buf[strlen (name) + 24 + pwdtablelen];
740
741 sprintf(buf, "[name=%s],%s", name, pwdtable);
742 res = nis_list(buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
743 if (niserr2nss (res->status) != NSS_STATUS_SUCCESS)
744 {
745 enum nss_status status = niserr2nss (res->status);
746
747 nis_freeresult (res);
748 return status;
749 }
750 parse_res = _nss_nisplus_parse_pwent (res, result, buffer,
751 buflen, errnop);
752 if (parse_res == -1)
753 {
754 nis_freeresult (res);
755 *errnop = ERANGE;
756 return NSS_STATUS_TRYAGAIN;
757 }
758 nis_freeresult (res);
759 }
760 else /* Use NIS */
761 {
762 char *domain, *outval, *ptr;
763 int outvallen;
764
765 if (yp_get_default_domain (&domain) != YPERR_SUCCESS)
766 return NSS_STATUS_NOTFOUND;
767
768 if (yp_match (domain, "passwd.byname", name, strlen (name),
769 &outval, &outvallen) != YPERR_SUCCESS)
770 return NSS_STATUS_NOTFOUND;
771
772 ptr = strncpy (buffer, outval, buflen < (size_t) outvallen ?
773 buflen : (size_t) outvallen);
774 buffer[buflen < (size_t) outvallen ? buflen : (size_t) outvallen] = '\0';
775 free (outval);
776 while (isspace (*ptr))
777 ptr++;
778 parse_res = _nss_files_parse_pwent (ptr, result, data, buflen, errnop);
779 if (parse_res == -1)
780 return NSS_STATUS_TRYAGAIN;
781 }
782
783 if (parse_res > 0)
784 {
785 copy_pwd_changes (result, &pwd, p, plen);
786 give_pwd_free (&pwd);
787 /* We found the entry. */
788 return NSS_STATUS_SUCCESS;
789 }
790 else
791 {
792 /* Give buffer the old len back */
793 buflen += plen;
794 give_pwd_free (&pwd);
795 }
796 return NSS_STATUS_RETURN;
797 }
798
799 static enum nss_status
800 getpwent_next_file (struct passwd *result, ent_t *ent,
801 char *buffer, size_t buflen, int *errnop)
802 {
803 struct parser_data *data = (void *) buffer;
804 while (1)
805 {
806 fpos_t pos;
807 char *p;
808 int parse_res;
809
810 do
811 {
812 fgetpos (ent->stream, &pos);
813 buffer[buflen - 1] = '\xff';
814 p = fgets (buffer, buflen, ent->stream);
815 if (p == NULL && feof (ent->stream))
816 return NSS_STATUS_NOTFOUND;
817 if (p == NULL || buffer[buflen - 1] != '\xff')
818 {
819 fsetpos (ent->stream, &pos);
820 *errnop = ERANGE;
821 return NSS_STATUS_TRYAGAIN;
822 }
823
824 /* Terminate the line for any case. */
825 buffer[buflen - 1] = '\0';
826
827 /* Skip leading blanks. */
828 while (isspace (*p))
829 ++p;
830 }
831 while (*p == '\0' || *p == '#' || /* Ignore empty and comment lines. */
832 /* Parse the line. If it is invalid, loop to
833 get the next line of the file to parse. */
834 !(parse_res = _nss_files_parse_pwent (p, result, data, buflen,
835 errnop)));
836
837 if (parse_res == -1)
838 {
839 /* The parser ran out of space. */
840 fsetpos (ent->stream, &pos);
841 *errnop = ERANGE;
842 return NSS_STATUS_TRYAGAIN;
843 }
844
845 if (result->pw_name[0] != '+' && result->pw_name[0] != '-')
846 /* This is a real entry. */
847 break;
848
849 /* -@netgroup */
850 if (result->pw_name[0] == '-' && result->pw_name[1] == '@'
851 && result->pw_name[2] != '\0')
852 {
853 /* XXX Do not use fixed length buffer. */
854 char buf2[1024];
855 char *user, *host, *domain;
856 struct __netgrent netgrdata;
857
858 bzero (&netgrdata, sizeof (struct __netgrent));
859 __internal_setnetgrent (&result->pw_name[2], &netgrdata);
860 while (__internal_getnetgrent_r (&host, &user, &domain, &netgrdata,
861 buf2, sizeof (buf2), errnop))
862 {
863 if (user != NULL && user[0] != '-')
864 blacklist_store_name (user, ent);
865 }
866 __internal_endnetgrent (&netgrdata);
867 continue;
868 }
869
870 /* +@netgroup */
871 if (result->pw_name[0] == '+' && result->pw_name[1] == '@'
872 && result->pw_name[2] != '\0')
873 {
874 int status;
875
876 ent->netgroup = TRUE;
877 ent->first = TRUE;
878 copy_pwd_changes (&ent->pwd, result, NULL, 0);
879
880 if (use_nisplus)
881 status = getpwent_next_nisplus_netgr (NULL, result, ent,
882 &result->pw_name[2],
883 buffer, buflen, errnop);
884 else
885 status = getpwent_next_nis_netgr (NULL, result, ent,
886 &result->pw_name[2],
887 buffer, buflen, errnop);
888 if (status == NSS_STATUS_RETURN)
889 continue;
890 else
891 return status;
892 }
893
894 /* -user */
895 if (result->pw_name[0] == '-' && result->pw_name[1] != '\0'
896 && result->pw_name[1] != '@')
897 {
898 blacklist_store_name (&result->pw_name[1], ent);
899 continue;
900 }
901
902 /* +user */
903 if (result->pw_name[0] == '+' && result->pw_name[1] != '\0'
904 && result->pw_name[1] != '@')
905 {
906 enum nss_status status;
907
908 /* Store the User in the blacklist for the "+" at the end of
909 /etc/passwd */
910 blacklist_store_name (&result->pw_name[1], ent);
911 status = getpwnam_plususer (&result->pw_name[1], result, buffer,
912 buflen, errnop);
913 if (status == NSS_STATUS_SUCCESS) /* We found the entry. */
914 break;
915 else
916 if (status == NSS_STATUS_RETURN /* We couldn't parse the entry */
917 || status == NSS_STATUS_NOTFOUND) /* entry doesn't exist */
918 continue;
919 else
920 {
921 if (status == NSS_STATUS_TRYAGAIN)
922 {
923 /* The parser ran out of space */
924 fsetpos (ent->stream, &pos);
925 *errnop = ERANGE;
926 }
927 return status;
928 }
929 }
930
931 /* +:... */
932 if (result->pw_name[0] == '+' && result->pw_name[1] == '\0')
933 {
934 ent->nis = TRUE;
935 ent->first = TRUE;
936 copy_pwd_changes (&ent->pwd, result, NULL, 0);
937
938 if (use_nisplus)
939 return getpwent_next_nisplus (result, ent, buffer, buflen, errnop);
940 else
941 return getpwent_next_nis (result, ent, buffer, buflen, errnop);
942 }
943 }
944
945 return NSS_STATUS_SUCCESS;
946 }
947
948
949 static enum nss_status
950 internal_getpwent_r (struct passwd *pw, ent_t *ent, char *buffer,
951 size_t buflen, int *errnop)
952 {
953 if (ent->netgroup)
954 {
955 int status;
956
957 /* We are searching members in a netgroup */
958 /* Since this is not the first call, we don't need the group name */
959 if (use_nisplus)
960 status = getpwent_next_nisplus_netgr (NULL, pw, ent, NULL, buffer,
961 buflen, errnop);
962 else
963 status = getpwent_next_nis_netgr (NULL, pw, ent, NULL, buffer, buflen,
964 errnop);
965 if (status == NSS_STATUS_RETURN)
966 return getpwent_next_file (pw, ent, buffer, buflen, errnop);
967 else
968 return status;
969 }
970 else
971 if (ent->nis)
972 {
973 if (use_nisplus)
974 return getpwent_next_nisplus (pw, ent, buffer, buflen, errnop);
975 else
976 return getpwent_next_nis (pw, ent, buffer, buflen, errnop);
977 }
978 else
979 return getpwent_next_file (pw, ent, buffer, buflen, errnop);
980 }
981
982 enum nss_status
983 _nss_compat_getpwent_r (struct passwd *pwd, char *buffer, size_t buflen,
984 int *errnop)
985 {
986 enum nss_status status = NSS_STATUS_SUCCESS;
987
988 __libc_lock_lock (lock);
989
990 if (ni == NULL)
991 {
992 __nss_database_lookup ("passwd_compat", NULL, "nis", &ni);
993 use_nisplus = (strcmp (ni->name, "nisplus") == 0);
994 }
995
996 /* Be prepared that the setpwent function was not called before. */
997 if (ext_ent.stream == NULL)
998 status = internal_setpwent (&ext_ent);
999
1000 if (status == NSS_STATUS_SUCCESS)
1001 status = internal_getpwent_r (pwd, &ext_ent, buffer, buflen, errnop);
1002
1003 __libc_lock_unlock (lock);
1004
1005 return status;
1006 }
1007
1008 /* Searches in /etc/passwd and the NIS/NIS+ map for a special user */
1009 static enum nss_status
1010 internal_getpwnam_r (const char *name, struct passwd *result, ent_t *ent,
1011 char *buffer, size_t buflen, int *errnop)
1012 {
1013 struct parser_data *data = (void *) buffer;
1014
1015 while (1)
1016 {
1017 fpos_t pos;
1018 char *p;
1019 int parse_res;
1020
1021 do
1022 {
1023 fgetpos (ent->stream, &pos);
1024 buffer[buflen - 1] = '\xff';
1025 p = fgets (buffer, buflen, ent->stream);
1026 if (p == NULL && feof (ent->stream))
1027 return NSS_STATUS_NOTFOUND;
1028 if (p == NULL || buffer[buflen - 1] != '\xff')
1029 {
1030 fsetpos (ent->stream, &pos);
1031 *errnop = ERANGE;
1032 return NSS_STATUS_TRYAGAIN;
1033 }
1034
1035 /* Terminate the line for any case. */
1036 buffer[buflen - 1] = '\0';
1037
1038 /* Skip leading blanks. */
1039 while (isspace (*p))
1040 ++p;
1041 }
1042 while (*p == '\0' || *p == '#' || /* Ignore empty and comment lines. */
1043 /* Parse the line. If it is invalid, loop to
1044 get the next line of the file to parse. */
1045 !(parse_res = _nss_files_parse_pwent (p, result, data, buflen,
1046 errnop)));
1047
1048 if (parse_res == -1)
1049 {
1050 /* The parser ran out of space. */
1051 fsetpos (ent->stream, &pos);
1052 *errnop = ERANGE;
1053 return NSS_STATUS_TRYAGAIN;
1054 }
1055
1056 /* This is a real entry. */
1057 if (result->pw_name[0] != '+' && result->pw_name[0] != '-')
1058 {
1059 if (strcmp (result->pw_name, name) == 0)
1060 return NSS_STATUS_SUCCESS;
1061 else
1062 continue;
1063 }
1064
1065 /* -@netgroup */
1066 if (result->pw_name[0] == '-' && result->pw_name[1] == '@'
1067 && result->pw_name[2] != '\0')
1068 {
1069 /* XXX Do not use fixed length buffers. */
1070 char buf2[1024];
1071 char *user, *host, *domain;
1072 struct __netgrent netgrdata;
1073
1074 bzero (&netgrdata, sizeof (struct __netgrent));
1075 __internal_setnetgrent (&result->pw_name[2], &netgrdata);
1076 while (__internal_getnetgrent_r (&host, &user, &domain, &netgrdata,
1077 buf2, sizeof (buf2), errnop))
1078 {
1079 if (user != NULL && user[0] != '-')
1080 if (strcmp (user, name) == 0)
1081 return NSS_STATUS_NOTFOUND;
1082 }
1083 __internal_endnetgrent (&netgrdata);
1084 continue;
1085 }
1086
1087 /* +@netgroup */
1088 if (result->pw_name[0] == '+' && result->pw_name[1] == '@'
1089 && result->pw_name[2] != '\0')
1090 {
1091 char buf[strlen (result->pw_name)];
1092 int status;
1093
1094 strcpy (buf, &result->pw_name[2]);
1095 ent->netgroup = TRUE;
1096 ent->first = TRUE;
1097 copy_pwd_changes (&ent->pwd, result, NULL, 0);
1098
1099 do
1100 {
1101 if (use_nisplus)
1102 status = getpwent_next_nisplus_netgr (name, result, ent, buf,
1103 buffer, buflen, errnop);
1104 else
1105 status = getpwent_next_nis_netgr (name, result, ent, buf,
1106 buffer, buflen, errnop);
1107 if (status == NSS_STATUS_RETURN)
1108 continue;
1109
1110 if (status == NSS_STATUS_SUCCESS &&
1111 strcmp (result->pw_name, name) == 0)
1112 return NSS_STATUS_SUCCESS;
1113 } while (status == NSS_STATUS_SUCCESS);
1114 continue;
1115 }
1116
1117 /* -user */
1118 if (result->pw_name[0] == '-' && result->pw_name[1] != '\0'
1119 && result->pw_name[1] != '@')
1120 {
1121 if (strcmp (&result->pw_name[1], name) == 0)
1122 return NSS_STATUS_NOTFOUND;
1123 else
1124 continue;
1125 }
1126
1127 /* +user */
1128 if (result->pw_name[0] == '+' && result->pw_name[1] != '\0'
1129 && result->pw_name[1] != '@')
1130 {
1131 if (strcmp (name, &result->pw_name[1]) == 0)
1132 {
1133 enum nss_status status;
1134
1135 status = getpwnam_plususer (name, result, buffer, buflen,
1136 errnop);
1137 if (status == NSS_STATUS_RETURN)
1138 /* We couldn't parse the entry */
1139 return NSS_STATUS_NOTFOUND;
1140 else
1141 return status;
1142 }
1143 }
1144
1145 /* +:... */
1146 if (result->pw_name[0] == '+' && result->pw_name[1] == '\0')
1147 {
1148 enum nss_status status;
1149
1150 status = getpwnam_plususer (name, result, buffer, buflen, errnop);
1151 if (status == NSS_STATUS_SUCCESS) /* We found the entry. */
1152 break;
1153 else
1154 if (status == NSS_STATUS_RETURN) /* We couldn't parse the entry */
1155 return NSS_STATUS_NOTFOUND;
1156 else
1157 return status;
1158 }
1159 }
1160 return NSS_STATUS_SUCCESS;
1161 }
1162
1163 enum nss_status
1164 _nss_compat_getpwnam_r (const char *name, struct passwd *pwd,
1165 char *buffer, size_t buflen, int *errnop)
1166 {
1167 ent_t ent = {0, 0, 0, NULL, 0, NULL, NULL, {NULL, 0, 0},
1168 {NULL, NULL, 0, 0, NULL, NULL, NULL}};
1169 enum nss_status status;
1170
1171 if (name[0] == '-' || name[0] == '+')
1172 return NSS_STATUS_NOTFOUND;
1173
1174 __libc_lock_lock (lock);
1175
1176 if (ni == NULL)
1177 {
1178 __nss_database_lookup ("passwd_compat", NULL, "nis", &ni);
1179 use_nisplus = (strcmp (ni->name, "nisplus") == 0);
1180 }
1181
1182 __libc_lock_unlock (lock);
1183
1184 status = internal_setpwent (&ent);
1185 if (status != NSS_STATUS_SUCCESS)
1186 return status;
1187
1188 status = internal_getpwnam_r (name, pwd, &ent, buffer, buflen, errnop);
1189
1190 internal_endpwent (&ent);
1191
1192 return status;
1193 }
1194
1195 /* This function handle the + entry in /etc/passwd for getpwuid */
1196 static enum nss_status
1197 getpwuid_plususer (uid_t uid, struct passwd *result, char *buffer,
1198 size_t buflen, int *errnop)
1199 {
1200 struct parser_data *data = (void *) buffer;
1201 struct passwd pwd;
1202 int parse_res;
1203 char *p;
1204 size_t plen;
1205
1206 memset (&pwd, '\0', sizeof (struct passwd));
1207
1208 copy_pwd_changes (&pwd, result, NULL, 0);
1209
1210 plen = pwd_need_buflen (&pwd);
1211 if (plen > buflen)
1212 {
1213 *errnop = ERANGE;
1214 return NSS_STATUS_TRYAGAIN;
1215 }
1216 p = buffer + (buflen - plen);
1217 buflen -= plen;
1218
1219 if (use_nisplus) /* Do the NIS+ query here */
1220 {
1221 nis_result *res;
1222 char buf[1024 + pwdtablelen];
1223
1224 snprintf(buf, sizeof (buf), "[uid=%d],%s", uid, pwdtable);
1225 res = nis_list(buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
1226 if (niserr2nss (res->status) != NSS_STATUS_SUCCESS)
1227 {
1228 enum nss_status status = niserr2nss (res->status);
1229
1230 nis_freeresult (res);
1231 return status;
1232 }
1233 if ((parse_res = _nss_nisplus_parse_pwent (res, result, buffer,
1234 buflen, errnop)) == -1)
1235 {
1236 nis_freeresult (res);
1237 *errnop = ERANGE;
1238 return NSS_STATUS_TRYAGAIN;
1239 }
1240 nis_freeresult (res);
1241 }
1242 else /* Use NIS */
1243 {
1244 char buf[1024];
1245 char *domain, *outval, *ptr;
1246 int outvallen;
1247
1248 if (yp_get_default_domain (&domain) != YPERR_SUCCESS)
1249 {
1250 *errnop = errno;
1251 return NSS_STATUS_TRYAGAIN;
1252 }
1253
1254 sprintf (buf, "%d", uid);
1255 if (yp_match (domain, "passwd.byuid", buf, strlen (buf),
1256 &outval, &outvallen)
1257 != YPERR_SUCCESS)
1258 {
1259 *errnop = errno;
1260 return NSS_STATUS_TRYAGAIN;
1261 }
1262 ptr = strncpy (buffer, outval, buflen < (size_t) outvallen ?
1263 buflen : (size_t) outvallen);
1264 buffer[buflen < (size_t) outvallen ? buflen : (size_t) outvallen] = '\0';
1265 free (outval);
1266 while (isspace (*ptr))
1267 ptr++;
1268 parse_res = _nss_files_parse_pwent (ptr, result, data, buflen, errnop);
1269 if (parse_res == -1)
1270 return NSS_STATUS_TRYAGAIN;
1271 }
1272
1273 if (parse_res > 0)
1274 {
1275 copy_pwd_changes (result, &pwd, p, plen);
1276 give_pwd_free (&pwd);
1277 /* We found the entry. */
1278 return NSS_STATUS_SUCCESS;
1279 }
1280 else
1281 {
1282 /* Give buffer the old len back */
1283 buflen += plen;
1284 give_pwd_free (&pwd);
1285 }
1286 return NSS_STATUS_RETURN;
1287 }
1288
1289 /* Searches in /etc/passwd and the NIS/NIS+ map for a special user id */
1290 static enum nss_status
1291 internal_getpwuid_r (uid_t uid, struct passwd *result, ent_t *ent,
1292 char *buffer, size_t buflen, int *errnop)
1293 {
1294 struct parser_data *data = (void *) buffer;
1295
1296 while (1)
1297 {
1298 fpos_t pos;
1299 char *p;
1300 int parse_res;
1301
1302 do
1303 {
1304 fgetpos (ent->stream, &pos);
1305 buffer[buflen - 1] = '\xff';
1306 p = fgets (buffer, buflen, ent->stream);
1307 if (p == NULL && feof (ent->stream))
1308 return NSS_STATUS_NOTFOUND;
1309 if (p == NULL || buffer[buflen - 1] != '\xff')
1310 {
1311 fsetpos (ent->stream, &pos);
1312 *errnop = ERANGE;
1313 return NSS_STATUS_TRYAGAIN;
1314 }
1315
1316 /* Terminate the line for any case. */
1317 buffer[buflen - 1] = '\0';
1318
1319 /* Skip leading blanks. */
1320 while (isspace (*p))
1321 ++p;
1322 }
1323 while (*p == '\0' || *p == '#' || /* Ignore empty and comment lines. */
1324 /* Parse the line. If it is invalid, loop to
1325 get the next line of the file to parse. */
1326 !(parse_res = _nss_files_parse_pwent (p, result, data, buflen,
1327 errnop)));
1328
1329 if (parse_res == -1)
1330 {
1331 /* The parser ran out of space. */
1332 fsetpos (ent->stream, &pos);
1333 *errnop = ERANGE;
1334 return NSS_STATUS_TRYAGAIN;
1335 }
1336
1337 /* This is a real entry. */
1338 if (result->pw_name[0] != '+' && result->pw_name[0] != '-')
1339 {
1340 if (result->pw_uid == uid)
1341 return NSS_STATUS_SUCCESS;
1342 else
1343 continue;
1344 }
1345
1346 /* -@netgroup */
1347 if (result->pw_name[0] == '-' && result->pw_name[1] == '@'
1348 && result->pw_name[2] != '\0')
1349 {
1350 /* XXX Do not use fixed length buffers. */
1351 char buf2[1024];
1352 char *user, *host, *domain;
1353 struct __netgrent netgrdata;
1354
1355 bzero (&netgrdata, sizeof (struct __netgrent));
1356 __internal_setnetgrent (&result->pw_name[2], &netgrdata);
1357 while (__internal_getnetgrent_r (&host, &user, &domain, &netgrdata,
1358 buf2, sizeof (buf2), errnop))
1359 {
1360 if (user != NULL && user[0] != '-')
1361 blacklist_store_name (user, ent);
1362 }
1363 __internal_endnetgrent (&netgrdata);
1364 continue;
1365 }
1366
1367 /* +@netgroup */
1368 if (result->pw_name[0] == '+' && result->pw_name[1] == '@'
1369 && result->pw_name[2] != '\0')
1370 {
1371 char buf[strlen (result->pw_name)];
1372 int status;
1373
1374 strcpy (buf, &result->pw_name[2]);
1375 ent->netgroup = TRUE;
1376 ent->first = TRUE;
1377 copy_pwd_changes (&ent->pwd, result, NULL, 0);
1378
1379 do
1380 {
1381 if (use_nisplus)
1382 status = getpwent_next_nisplus_netgr (NULL, result, ent, buf,
1383 buffer, buflen, errnop);
1384 else
1385 status = getpwent_next_nis_netgr (NULL, result, ent, buf,
1386 buffer, buflen, errnop);
1387 if (status == NSS_STATUS_RETURN)
1388 continue;
1389
1390 if (status == NSS_STATUS_SUCCESS && uid == result->pw_uid)
1391 return NSS_STATUS_SUCCESS;
1392 } while (status == NSS_STATUS_SUCCESS);
1393 continue;
1394 }
1395
1396 /* -user */
1397 if (result->pw_name[0] == '-' && result->pw_name[1] != '\0'
1398 && result->pw_name[1] != '@')
1399 {
1400 blacklist_store_name (&result->pw_name[1], ent);
1401 continue;
1402 }
1403
1404 /* +user */
1405 if (result->pw_name[0] == '+' && result->pw_name[1] != '\0'
1406 && result->pw_name[1] != '@')
1407 {
1408 enum nss_status status;
1409
1410 /* Store the User in the blacklist for the "+" at the end of
1411 /etc/passwd */
1412 blacklist_store_name (&result->pw_name[1], ent);
1413 status = getpwnam_plususer (&result->pw_name[1], result, buffer,
1414 buflen, errnop);
1415 if (status == NSS_STATUS_SUCCESS && result->pw_uid == uid)
1416 break;
1417 else
1418 continue;
1419 }
1420
1421 /* +:... */
1422 if (result->pw_name[0] == '+' && result->pw_name[1] == '\0')
1423 {
1424 enum nss_status status;
1425
1426 status = getpwuid_plususer (uid, result, buffer, buflen, errnop);
1427 if (status == NSS_STATUS_SUCCESS) /* We found the entry. */
1428 break;
1429 else
1430 if (status == NSS_STATUS_RETURN) /* We couldn't parse the entry */
1431 return NSS_STATUS_NOTFOUND;
1432 else
1433 return status;
1434 }
1435 }
1436 return NSS_STATUS_SUCCESS;
1437 }
1438
1439 enum nss_status
1440 _nss_compat_getpwuid_r (uid_t uid, struct passwd *pwd,
1441 char *buffer, size_t buflen, int *errnop)
1442 {
1443 ent_t ent = {0, 0, 0, NULL, 0, NULL, NULL, {NULL, 0, 0},
1444 {NULL, NULL, 0, 0, NULL, NULL, NULL}};
1445 enum nss_status status;
1446
1447 __libc_lock_lock (lock);
1448
1449 if (ni == NULL)
1450 {
1451 __nss_database_lookup ("passwd_compat", NULL, "nis", &ni);
1452 use_nisplus = (strcmp (ni->name, "nisplus") == 0);
1453 }
1454
1455 __libc_lock_unlock (lock);
1456
1457 status = internal_setpwent (&ent);
1458 if (status != NSS_STATUS_SUCCESS)
1459 return status;
1460
1461 status = internal_getpwuid_r (uid, pwd, &ent, buffer, buflen, errnop);
1462
1463 internal_endpwent (&ent);
1464
1465 return status;
1466 }
1467
1468
1469 /* Support routines for remembering -@netgroup and -user entries.
1470 The names are stored in a single string with `|' as separator. */
1471 static void
1472 blacklist_store_name (const char *name, ent_t *ent)
1473 {
1474 int namelen = strlen (name);
1475 char *tmp;
1476
1477 /* first call, setup cache */
1478 if (ent->blacklist.size == 0)
1479 {
1480 ent->blacklist.size = MAX (BLACKLIST_INITIAL_SIZE, 2 * namelen);
1481 ent->blacklist.data = malloc (ent->blacklist.size);
1482 if (ent->blacklist.data == NULL)
1483 return;
1484 ent->blacklist.data[0] = '|';
1485 ent->blacklist.data[1] = '\0';
1486 ent->blacklist.current = 1;
1487 }
1488 else
1489 {
1490 if (in_blacklist (name, namelen, ent))
1491 return; /* no duplicates */
1492
1493 if (ent->blacklist.current + namelen + 1 >= ent->blacklist.size)
1494 {
1495 ent->blacklist.size += MAX (BLACKLIST_INCREMENT, 2 * namelen);
1496 tmp = realloc (ent->blacklist.data, ent->blacklist.size);
1497 if (tmp == NULL)
1498 {
1499 free (ent->blacklist.data);
1500 ent->blacklist.size = 0;
1501 return;
1502 }
1503 ent->blacklist.data = tmp;
1504 }
1505 }
1506
1507 tmp = stpcpy (ent->blacklist.data + ent->blacklist.current, name);
1508 *tmp++ = '|';
1509 *tmp = '\0';
1510 ent->blacklist.current += namelen + 1;
1511
1512 return;
1513 }
1514
1515 /* returns TRUE if ent->blacklist contains name, else FALSE */
1516 static bool_t
1517 in_blacklist (const char *name, int namelen, ent_t *ent)
1518 {
1519 char buf[namelen + 3];
1520 char *cp;
1521
1522 if (ent->blacklist.data == NULL)
1523 return FALSE;
1524
1525 buf[0] = '|';
1526 cp = stpcpy (&buf[1], name);
1527 *cp++= '|';
1528 *cp = '\0';
1529 return strstr (ent->blacklist.data, buf) != NULL;
1530 }
This page took 0.109992 seconds and 6 git commands to generate.