]> git.ipfire.org Git - thirdparty/glibc.git/blame - nis/nss_compat/compat-grp.c
(CFLAGS-tst-align.c): Add -mpreferred-stack-boundary=4.
[thirdparty/glibc.git] / nis / nss_compat / compat-grp.c
CommitLineData
a334319f 1/* Copyright (C) 1996-1999,2001,2002,2003,2004 Free Software Foundation, Inc.
6259ec0d 2 This file is part of the GNU C Library.
b85697f6 3 Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996.
6259ec0d
UD
4
5 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
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.
6259ec0d
UD
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
41bdb6e2 13 Lesser General Public License for more details.
6259ec0d 14
41bdb6e2
AJ
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. */
6259ec0d 19
1aa43890 20#include <ctype.h>
6259ec0d 21#include <errno.h>
3996f34b 22#include <fcntl.h>
6259ec0d 23#include <grp.h>
1aa43890
UD
24#include <nss.h>
25#include <nsswitch.h>
b4431a72 26#include <stdio_ext.h>
6259ec0d 27#include <string.h>
1e2e27fd 28#include <rpc/types.h>
1aa43890 29#include <bits/libc-lock.h>
26dee9c4 30
fc9f33e3 31static service_user *ni;
1e2e27fd
UD
32static enum nss_status (*nss_setgrent) (int stayopen);
33static enum nss_status (*nss_getgrnam_r) (const char *name,
34 struct group * grp, char *buffer,
35 size_t buflen, int *errnop);
36static enum nss_status (*nss_getgrgid_r) (gid_t gid, struct group * grp,
37 char *buffer, size_t buflen,
38 int *errnop);
39static enum nss_status (*nss_getgrent_r) (struct group * grp, char *buffer,
40 size_t buflen, int *errnop);
41static enum nss_status (*nss_endgrent) (void);
6259ec0d 42
7e3be507
UD
43/* Get the declaration of the parser function. */
44#define ENTNAME grent
45#define STRUCTURE group
46#define EXTERN_PARSER
cc3fa755 47#include <nss/nss_files/files-parse.c>
7e3be507 48
26dee9c4 49/* Structure for remembering -group members ... */
6259ec0d
UD
50#define BLACKLIST_INITIAL_SIZE 512
51#define BLACKLIST_INCREMENT 256
52struct blacklist_t
1e2e27fd
UD
53{
54 char *data;
55 int current;
56 int size;
57};
6259ec0d
UD
58
59struct ent_t
1e2e27fd 60{
1e2e27fd
UD
61 bool_t files;
62 FILE *stream;
63 struct blacklist_t blacklist;
26dee9c4 64};
6259ec0d
UD
65typedef struct ent_t ent_t;
66
a334319f 67static ent_t ext_ent = {TRUE, NULL, {NULL, 0, 0}};
6259ec0d
UD
68
69/* Protect global state against multiple changers. */
70__libc_lock_define_initialized (static, lock)
71
72/* Prototypes for local functions. */
73static void blacklist_store_name (const char *, ent_t *);
74static int in_blacklist (const char *, int, ent_t *);
2d7da676 75
1e2e27fd
UD
76/* Initialize the NSS interface/functions. The calling function must
77 hold the lock. */
78static void
79init_nss_interface (void)
2d7da676 80{
1e2e27fd 81 if (__nss_database_lookup ("group_compat", NULL, "nis", &ni) >= 0)
2d7da676 82 {
1e2e27fd
UD
83 nss_setgrent = __nss_lookup_function (ni, "setgrent");
84 nss_getgrnam_r = __nss_lookup_function (ni, "getgrnam_r");
85 nss_getgrgid_r = __nss_lookup_function (ni, "getgrgid_r");
86 nss_getgrent_r = __nss_lookup_function (ni, "getgrent_r");
87 nss_endgrent = __nss_lookup_function (ni, "endgrent");
2d7da676 88 }
2d7da676 89}
6259ec0d
UD
90
91static enum nss_status
a334319f 92internal_setgrent (ent_t *ent, int stayopen)
6259ec0d
UD
93{
94 enum nss_status status = NSS_STATUS_SUCCESS;
95
1e2e27fd 96 ent->files = TRUE;
c131718c 97
6259ec0d 98 if (ent->blacklist.data != NULL)
bd355af0
UD
99 {
100 ent->blacklist.current = 1;
101 ent->blacklist.data[0] = '|';
102 ent->blacklist.data[1] = '\0';
103 }
104 else
105 ent->blacklist.current = 0;
c131718c 106
6259ec0d
UD
107 if (ent->stream == NULL)
108 {
1aa43890 109 ent->stream = fopen ("/etc/group", "rm");
c131718c 110
6259ec0d
UD
111 if (ent->stream == NULL)
112 status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
3996f34b
UD
113 else
114 {
115 /* We have to make sure the file is `closed on exec'. */
116 int result, flags;
117
1aa43890 118 result = flags = fcntl (fileno_unlocked (ent->stream), F_GETFD, 0);
3996f34b
UD
119 if (result >= 0)
120 {
121 flags |= FD_CLOEXEC;
1aa43890 122 result = fcntl (fileno_unlocked (ent->stream), F_SETFD, flags);
3996f34b
UD
123 }
124 if (result < 0)
125 {
126 /* Something went wrong. Close the stream and return a
1e2e27fd 127 failure. */
3996f34b
UD
128 fclose (ent->stream);
129 ent->stream = NULL;
130 status = NSS_STATUS_UNAVAIL;
131 }
1aa43890
UD
132 else
133 /* We take care of locking ourself. */
134 __fsetlocking (ent->stream, FSETLOCKING_BYCALLER);
3996f34b 135 }
6259ec0d
UD
136 }
137 else
138 rewind (ent->stream);
139
a334319f
UD
140 if (status == NSS_STATUS_SUCCESS && nss_setgrent)
141 return nss_setgrent (stayopen);
1e2e27fd 142
6259ec0d
UD
143 return status;
144}
145
146
147enum nss_status
51eecc4a 148_nss_compat_setgrent (int stayopen)
6259ec0d
UD
149{
150 enum nss_status result;
151
152 __libc_lock_lock (lock);
153
1e2e27fd
UD
154 if (ni == NULL)
155 init_nss_interface ();
156
a334319f 157 result = internal_setgrent (&ext_ent, stayopen);
6259ec0d
UD
158
159 __libc_lock_unlock (lock);
160
161 return result;
162}
163
164
165static enum nss_status
166internal_endgrent (ent_t *ent)
167{
1e2e27fd
UD
168 if (nss_endgrent)
169 nss_endgrent ();
170
6259ec0d
UD
171 if (ent->stream != NULL)
172 {
173 fclose (ent->stream);
174 ent->stream = NULL;
175 }
176
6259ec0d 177 if (ent->blacklist.data != NULL)
bd355af0
UD
178 {
179 ent->blacklist.current = 1;
180 ent->blacklist.data[0] = '|';
181 ent->blacklist.data[1] = '\0';
182 }
183 else
184 ent->blacklist.current = 0;
6259ec0d
UD
185
186 return NSS_STATUS_SUCCESS;
187}
188
189enum nss_status
190_nss_compat_endgrent (void)
191{
192 enum nss_status result;
193
194 __libc_lock_lock (lock);
195
196 result = internal_endgrent (&ext_ent);
197
198 __libc_lock_unlock (lock);
199
200 return result;
201}
202
1e2e27fd 203/* get the next group from NSS (+ entry) */
6259ec0d 204static enum nss_status
1e2e27fd 205getgrent_next_nss (struct group *result, ent_t *ent, char *buffer,
d71b808a 206 size_t buflen, int *errnop)
6259ec0d 207{
1e2e27fd
UD
208 if (!nss_getgrent_r)
209 return NSS_STATUS_UNAVAIL;
c131718c 210
26dee9c4
UD
211 do
212 {
1e2e27fd 213 enum nss_status status;
60c96635 214
1e2e27fd
UD
215 if ((status = nss_getgrent_r (result, buffer, buflen, errnop)) !=
216 NSS_STATUS_SUCCESS)
217 return status;
26dee9c4 218 }
1e2e27fd 219 while (in_blacklist (result->gr_name, strlen (result->gr_name), ent));
c131718c 220
26dee9c4
UD
221 return NSS_STATUS_SUCCESS;
222}
6259ec0d 223
26dee9c4
UD
224/* This function handle the +group entrys in /etc/group */
225static enum nss_status
1e2e27fd
UD
226getgrnam_plusgroup (const char *name, struct group *result, ent_t *ent,
227 char *buffer, size_t buflen, int *errnop)
26dee9c4 228{
1e2e27fd
UD
229 if (!nss_getgrnam_r)
230 return NSS_STATUS_UNAVAIL;
6591c335 231
a334319f
UD
232 if (nss_getgrnam_r (name, result, buffer, buflen, errnop) !=
233 NSS_STATUS_SUCCESS)
234 return NSS_STATUS_NOTFOUND;
6591c335 235
1e2e27fd
UD
236 if (in_blacklist (result->gr_name, strlen (result->gr_name), ent))
237 return NSS_STATUS_NOTFOUND;
26dee9c4 238
1e2e27fd
UD
239 /* We found the entry. */
240 return NSS_STATUS_SUCCESS;
6259ec0d
UD
241}
242
6259ec0d
UD
243static enum nss_status
244getgrent_next_file (struct group *result, ent_t *ent,
d71b808a 245 char *buffer, size_t buflen, int *errnop)
6259ec0d 246{
7e3be507 247 struct parser_data *data = (void *) buffer;
6259ec0d
UD
248 while (1)
249 {
60c96635
UD
250 fpos_t pos;
251 int parse_res = 0;
6259ec0d
UD
252 char *p;
253
254 do
255 {
20f8e666
UD
256 /* We need at least 3 characters for one line. */
257 if (__builtin_expect (buflen < 3, 0))
258 {
259 erange:
260 *errnop = ERANGE;
261 return NSS_STATUS_TRYAGAIN;
262 }
263
60c96635 264 fgetpos (ent->stream, &pos);
af69217f 265 buffer[buflen - 1] = '\xff';
1aa43890
UD
266 p = fgets_unlocked (buffer, buflen, ent->stream);
267 if (p == NULL && feof_unlocked (ent->stream))
34816665
UD
268 return NSS_STATUS_NOTFOUND;
269
20f8e666 270 if (p == NULL || __builtin_expect (buffer[buflen - 1] != '\xff', 0))
60c96635 271 {
20f8e666 272 erange_reset:
af69217f 273 fsetpos (ent->stream, &pos);
20f8e666 274 goto erange;
60c96635 275 }
6259ec0d
UD
276
277 /* Terminate the line for any case. */
278 buffer[buflen - 1] = '\0';
279
280 /* Skip leading blanks. */
281 while (isspace (*p))
282 ++p;
283 }
1e2e27fd
UD
284 while (*p == '\0' || *p == '#' || /* Ignore empty and comment lines. */
285 /* Parse the line. If it is invalid, loop to
286 get the next line of the file to parse. */
d71b808a
UD
287 !(parse_res = _nss_files_parse_grent (p, result, data, buflen,
288 errnop)));
60c96635 289
20f8e666
UD
290 if (__builtin_expect (parse_res == -1, 0))
291 /* The parser ran out of space. */
292 goto erange_reset;
6259ec0d
UD
293
294 if (result->gr_name[0] != '+' && result->gr_name[0] != '-')
295 /* This is a real entry. */
296 break;
297
298 /* -group */
299 if (result->gr_name[0] == '-' && result->gr_name[1] != '\0'
300 && result->gr_name[1] != '@')
301 {
302 blacklist_store_name (&result->gr_name[1], ent);
303 continue;
304 }
305
306 /* +group */
307 if (result->gr_name[0] == '+' && result->gr_name[1] != '\0'
308 && result->gr_name[1] != '@')
309 {
bbca27a4
UD
310 size_t len = strlen (result->gr_name);
311 char buf[len];
1e2e27fd 312 enum nss_status status;
c131718c 313
51eecc4a 314 /* Store the group in the blacklist for the "+" at the end of
cc3fa755 315 /etc/group */
bbca27a4 316 memcpy (buf, &result->gr_name[1], len);
1e2e27fd
UD
317 status = getgrnam_plusgroup (&result->gr_name[1], result, ent,
318 buffer, buflen, errnop);
bbca27a4 319 blacklist_store_name (buf, ent);
1e2e27fd
UD
320 if (status == NSS_STATUS_SUCCESS) /* We found the entry. */
321 break;
20f8e666 322 else if (status == NSS_STATUS_RETURN /* We couldn't parse the entry*/
1e2e27fd
UD
323 || status == NSS_STATUS_NOTFOUND) /* No group in NIS */
324 continue;
325 else
326 {
327 if (status == NSS_STATUS_TRYAGAIN)
20f8e666
UD
328 /* The parser ran out of space. */
329 goto erange_reset;
330
1e2e27fd
UD
331 return status;
332 }
6259ec0d
UD
333 }
334
335 /* +:... */
336 if (result->gr_name[0] == '+' && result->gr_name[1] == '\0')
337 {
1e2e27fd 338 ent->files = FALSE;
6259ec0d 339
1e2e27fd 340 return getgrent_next_nss (result, ent, buffer, buflen, errnop);
6259ec0d
UD
341 }
342 }
343
344 return NSS_STATUS_SUCCESS;
345}
346
347
6259ec0d 348enum nss_status
d71b808a
UD
349_nss_compat_getgrent_r (struct group *grp, char *buffer, size_t buflen,
350 int *errnop)
6259ec0d 351{
1e2e27fd 352 enum nss_status result = NSS_STATUS_SUCCESS;
6259ec0d
UD
353
354 __libc_lock_lock (lock);
355
356 /* Be prepared that the setgrent function was not called before. */
1e2e27fd
UD
357 if (ni == NULL)
358 init_nss_interface ();
6259ec0d 359
1e2e27fd 360 if (ext_ent.stream == NULL)
a334319f 361 result = internal_setgrent (&ext_ent, 1);
6259ec0d 362
1e2e27fd
UD
363 if (result == NSS_STATUS_SUCCESS)
364 {
365 if (ext_ent.files)
366 result = getgrent_next_file (grp, &ext_ent, buffer, buflen, errnop);
367 else
368 result = getgrent_next_nss (grp, &ext_ent, buffer, buflen, errnop);
369 }
6259ec0d
UD
370 __libc_lock_unlock (lock);
371
1e2e27fd 372 return result;
6259ec0d
UD
373}
374
cc3fa755
UD
375/* Searches in /etc/group and the NIS/NIS+ map for a special group */
376static enum nss_status
377internal_getgrnam_r (const char *name, struct group *result, ent_t *ent,
d71b808a 378 char *buffer, size_t buflen, int *errnop)
cc3fa755
UD
379{
380 struct parser_data *data = (void *) buffer;
381 while (1)
382 {
383 fpos_t pos;
384 int parse_res = 0;
385 char *p;
386
387 do
388 {
20f8e666
UD
389 /* We need at least 3 characters for one line. */
390 if (__builtin_expect (buflen < 3, 0))
391 {
392 erange:
393 *errnop = ERANGE;
394 return NSS_STATUS_TRYAGAIN;
395 }
396
cc3fa755 397 fgetpos (ent->stream, &pos);
af69217f 398 buffer[buflen - 1] = '\xff';
1aa43890
UD
399 p = fgets_unlocked (buffer, buflen, ent->stream);
400 if (p == NULL && feof_unlocked (ent->stream))
1e2e27fd 401 return NSS_STATUS_NOTFOUND;
34816665 402
20f8e666 403 if (p == NULL || __builtin_expect (buffer[buflen - 1] != '\xff', 0))
cc3fa755 404 {
20f8e666 405 erange_reset:
af69217f 406 fsetpos (ent->stream, &pos);
20f8e666 407 goto erange;
cc3fa755
UD
408 }
409
410 /* Terminate the line for any case. */
411 buffer[buflen - 1] = '\0';
412
413 /* Skip leading blanks. */
414 while (isspace (*p))
415 ++p;
416 }
1e2e27fd
UD
417 while (*p == '\0' || *p == '#' || /* Ignore empty and comment lines. */
418 /* Parse the line. If it is invalid, loop to
419 get the next line of the file to parse. */
d71b808a
UD
420 !(parse_res = _nss_files_parse_grent (p, result, data, buflen,
421 errnop)));
cc3fa755 422
20f8e666
UD
423 if (__builtin_expect (parse_res == -1, 0))
424 /* The parser ran out of space. */
425 goto erange_reset;
cc3fa755
UD
426
427 /* This is a real entry. */
428 if (result->gr_name[0] != '+' && result->gr_name[0] != '-')
429 {
430 if (strcmp (result->gr_name, name) == 0)
431 return NSS_STATUS_SUCCESS;
432 else
433 continue;
434 }
435
436 /* -group */
d71b808a 437 if (result->gr_name[0] == '-' && result->gr_name[1] != '\0')
cc3fa755
UD
438 {
439 if (strcmp (&result->gr_name[1], name) == 0)
34816665 440 return NSS_STATUS_NOTFOUND;
cc3fa755
UD
441 else
442 continue;
443 }
444
445 /* +group */
d71b808a 446 if (result->gr_name[0] == '+' && result->gr_name[1] != '\0')
cc3fa755
UD
447 {
448 if (strcmp (name, &result->gr_name[1]) == 0)
449 {
450 enum nss_status status;
451
1e2e27fd
UD
452 status = getgrnam_plusgroup (name, result, ent,
453 buffer, buflen, errnop);
cc3fa755
UD
454 if (status == NSS_STATUS_RETURN)
455 /* We couldn't parse the entry */
456 continue;
457 else
458 return status;
459 }
460 }
461 /* +:... */
462 if (result->gr_name[0] == '+' && result->gr_name[1] == '\0')
463 {
464 enum nss_status status;
465
1e2e27fd
UD
466 status = getgrnam_plusgroup (name, result, ent,
467 buffer, buflen, errnop);
cc3fa755
UD
468 if (status == NSS_STATUS_RETURN)
469 /* We couldn't parse the entry */
470 continue;
471 else
472 return status;
473 }
474 }
475
476 return NSS_STATUS_SUCCESS;
477}
6259ec0d
UD
478
479enum nss_status
480_nss_compat_getgrnam_r (const char *name, struct group *grp,
d71b808a 481 char *buffer, size_t buflen, int *errnop)
6259ec0d 482{
a334319f 483 ent_t ent = {TRUE, NULL, {NULL, 0, 0}};
1e2e27fd 484 enum nss_status result;
6259ec0d
UD
485
486 if (name[0] == '-' || name[0] == '+')
34816665 487 return NSS_STATUS_NOTFOUND;
6259ec0d 488
26dee9c4
UD
489 __libc_lock_lock (lock);
490
1e2e27fd
UD
491 if (ni == NULL)
492 init_nss_interface ();
c131718c 493
26dee9c4 494 __libc_lock_unlock (lock);
6259ec0d 495
a334319f 496 result = internal_setgrent (&ent, 0);
6259ec0d 497
1e2e27fd
UD
498 if (result == NSS_STATUS_SUCCESS)
499 result = internal_getgrnam_r (name, grp, &ent, buffer, buflen, errnop);
6259ec0d
UD
500
501 internal_endgrent (&ent);
cc3fa755 502
1e2e27fd 503 return result;
cc3fa755
UD
504}
505
506/* Searches in /etc/group and the NIS/NIS+ map for a special group id */
507static enum nss_status
508internal_getgrgid_r (gid_t gid, struct group *result, ent_t *ent,
d71b808a 509 char *buffer, size_t buflen, int *errnop)
cc3fa755
UD
510{
511 struct parser_data *data = (void *) buffer;
512 while (1)
513 {
514 fpos_t pos;
515 int parse_res = 0;
516 char *p;
517
518 do
519 {
20f8e666
UD
520 /* We need at least 3 characters for one line. */
521 if (__builtin_expect (buflen < 3, 0))
522 {
523 erange:
524 *errnop = ERANGE;
525 return NSS_STATUS_TRYAGAIN;
526 }
527
cc3fa755 528 fgetpos (ent->stream, &pos);
af69217f 529 buffer[buflen - 1] = '\xff';
1aa43890
UD
530 p = fgets_unlocked (buffer, buflen, ent->stream);
531 if (p == NULL && feof_unlocked (ent->stream))
34816665
UD
532 return NSS_STATUS_NOTFOUND;
533
20f8e666 534 if (p == NULL || __builtin_expect (buffer[buflen - 1] != '\xff', 0))
cc3fa755 535 {
20f8e666 536 erange_reset:
af69217f 537 fsetpos (ent->stream, &pos);
20f8e666 538 goto erange;
cc3fa755
UD
539 }
540
541 /* Terminate the line for any case. */
542 buffer[buflen - 1] = '\0';
543
544 /* Skip leading blanks. */
545 while (isspace (*p))
546 ++p;
547 }
1e2e27fd
UD
548 while (*p == '\0' || *p == '#' || /* Ignore empty and comment lines. */
549 /* Parse the line. If it is invalid, loop to
550 get the next line of the file to parse. */
d71b808a
UD
551 !(parse_res = _nss_files_parse_grent (p, result, data, buflen,
552 errnop)));
cc3fa755 553
a334319f 554 if (parse_res == -1)
20f8e666
UD
555 /* The parser ran out of space. */
556 goto erange_reset;
cc3fa755
UD
557
558 /* This is a real entry. */
559 if (result->gr_name[0] != '+' && result->gr_name[0] != '-')
560 {
561 if (result->gr_gid == gid)
562 return NSS_STATUS_SUCCESS;
563 else
564 continue;
565 }
566
567 /* -group */
d71b808a 568 if (result->gr_name[0] == '-' && result->gr_name[1] != '\0')
cc3fa755 569 {
1e2e27fd
UD
570 blacklist_store_name (&result->gr_name[1], ent);
571 continue;
cc3fa755
UD
572 }
573
574 /* +group */
d71b808a 575 if (result->gr_name[0] == '+' && result->gr_name[1] != '\0')
cc3fa755
UD
576 {
577 enum nss_status status;
578
579 /* Store the group in the blacklist for the "+" at the end of
1e2e27fd 580 /etc/group */
a334319f 581 blacklist_store_name (&result->gr_name[1], ent);
1e2e27fd
UD
582 status = getgrnam_plusgroup (&result->gr_name[1], result, ent,
583 buffer, buflen, errnop);
cc3fa755
UD
584 if (status == NSS_STATUS_SUCCESS && result->gr_gid == gid)
585 break;
586 else
587 continue;
588 }
589 /* +:... */
590 if (result->gr_name[0] == '+' && result->gr_name[1] == '\0')
591 {
a334319f 592 enum nss_status status;
cc3fa755 593
a334319f 594 status = nss_getgrgid_r (gid, result, buffer, buflen, errnop);
cc3fa755 595 if (status == NSS_STATUS_RETURN) /* We couldn't parse the entry */
34816665 596 return NSS_STATUS_NOTFOUND;
cc3fa755
UD
597 else
598 return status;
599 }
600 }
601
602 return NSS_STATUS_SUCCESS;
603}
6259ec0d
UD
604
605enum nss_status
606_nss_compat_getgrgid_r (gid_t gid, struct group *grp,
d71b808a 607 char *buffer, size_t buflen, int *errnop)
6259ec0d 608{
a334319f 609 ent_t ent = {TRUE, NULL, {NULL, 0, 0}};
1e2e27fd 610 enum nss_status result;
6259ec0d 611
26dee9c4 612 __libc_lock_lock (lock);
c131718c 613
1e2e27fd
UD
614 if (ni == NULL)
615 init_nss_interface ();
c131718c 616
26dee9c4
UD
617 __libc_lock_unlock (lock);
618
a334319f 619 result = internal_setgrent (&ent, 0);
6259ec0d 620
1e2e27fd
UD
621 if (result == NSS_STATUS_SUCCESS)
622 result = internal_getgrgid_r (gid, grp, &ent, buffer, buflen, errnop);
6259ec0d
UD
623
624 internal_endgrent (&ent);
cc3fa755 625
1e2e27fd 626 return result;
6259ec0d
UD
627}
628
629
630/* Support routines for remembering -@netgroup and -user entries.
631 The names are stored in a single string with `|' as separator. */
632static void
633blacklist_store_name (const char *name, ent_t *ent)
634{
635 int namelen = strlen (name);
636 char *tmp;
637
638 /* first call, setup cache */
639 if (ent->blacklist.size == 0)
640 {
641 ent->blacklist.size = MAX (BLACKLIST_INITIAL_SIZE, 2 * namelen);
642 ent->blacklist.data = malloc (ent->blacklist.size);
643 if (ent->blacklist.data == NULL)
644 return;
645 ent->blacklist.data[0] = '|';
646 ent->blacklist.data[1] = '\0';
647 ent->blacklist.current = 1;
648 }
649 else
650 {
651 if (in_blacklist (name, namelen, ent))
652 return; /* no duplicates */
653
654 if (ent->blacklist.current + namelen + 1 >= ent->blacklist.size)
655 {
656 ent->blacklist.size += MAX (BLACKLIST_INCREMENT, 2 * namelen);
657 tmp = realloc (ent->blacklist.data, ent->blacklist.size);
658 if (tmp == NULL)
659 {
660 free (ent->blacklist.data);
661 ent->blacklist.size = 0;
662 return;
663 }
664 ent->blacklist.data = tmp;
665 }
666 }
667
668 tmp = stpcpy (ent->blacklist.data + ent->blacklist.current, name);
669 *tmp++ = '|';
670 *tmp = '\0';
671 ent->blacklist.current += namelen + 1;
672
673 return;
674}
675
676/* returns TRUE if ent->blacklist contains name, else FALSE */
677static bool_t
678in_blacklist (const char *name, int namelen, ent_t *ent)
679{
680 char buf[namelen + 3];
c131718c 681 char *cp;
6259ec0d
UD
682
683 if (ent->blacklist.data == NULL)
684 return FALSE;
685
c131718c
UD
686 buf[0] = '|';
687 cp = stpcpy (&buf[1], name);
1e2e27fd 688 *cp++ = '|';
c131718c 689 *cp = '\0';
6259ec0d
UD
690 return strstr (ent->blacklist.data, buf) != NULL;
691}