OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [newlib-1.17.0/] [newlib/] [libc/] [sys/] [linux/] [net/] [getnetgrent_r.c] - Blame information for rev 148

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 148 jeremybenn
/* Copyright (C) 1996,1997,1998,1999,2002,2004 Free Software Foundation, Inc.
2
   This file is part of the GNU C Library.
3
 
4
   The GNU C Library is free software; you can redistribute it and/or
5
   modify it under the terms of the GNU Lesser General Public
6
   License as published by the Free Software Foundation; either
7
   version 2.1 of the License, or (at your option) any later version.
8
 
9
   The GNU C Library is distributed in the hope that it will be useful,
10
   but WITHOUT ANY WARRANTY; without even the implied warranty of
11
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
   Lesser General Public License for more details.
13
 
14
   You should have received a copy of the GNU Lesser General Public
15
   License along with the GNU C Library; if not, write to the Free
16
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17
   02111-1307 USA.  */
18
 
19
#define _IO_MTSAFE_IO
20
#include <bits/libc-lock.h>
21
#include <errno.h>
22
#include <netdb.h>
23
#include <stdlib.h>
24
#include <string.h>
25
#include "netgroup.h"
26
#include "nsswitch.h"
27
#include "libc-symbols.h"
28
 
29
 
30
/* Protect above variable against multiple uses at the same time.  */
31
__libc_lock_define_initialized (static, lock)
32
 
33
/* The whole information for the set/get/endnetgrent functions are
34
   kept in this structure.  */
35
static struct __netgrent dataset;
36
 
37
/* The lookup function for the first entry of this service.  */
38
extern int __nss_netgroup_lookup (service_user **nip, const char *name,
39
                                  void **fctp) internal_function;
40
 
41
 
42
/* Set up NIP to run through the services.  If ALL is zero, use NIP's
43
   current location if it's not nil.  Return nonzero if there are no
44
   services (left).  */
45
static enum nss_status
46
setup (void **fctp, const char *func_name, int all, service_user **nipp)
47
{
48
  /* Remember the first service_entry, it's always the same.  */
49
  static service_user *startp;
50
  int no_more;
51
 
52
  if (startp == NULL)
53
    {
54
      /* Executing this more than once at the same time must yield the
55
         same result every time.  So we need no locking.  */
56
      no_more = __nss_netgroup_lookup (nipp, func_name, fctp);
57
      startp = no_more ? (service_user *) -1 : *nipp;
58
    }
59
  else if (startp == (service_user *) -1)
60
    /* No services at all.  */
61
    return 1;
62
  else
63
    {
64
      if (all || *nipp == NULL)
65
        /* Reset to the beginning of the service list.  */
66
        *nipp = startp;
67
      /* Look up the first function.  */
68
      no_more = __nss_lookup (nipp, func_name, fctp);
69
    }
70
  return no_more;
71
}
72
 
73
/* Free used memory.  */
74
static void
75
free_memory (struct __netgrent *data)
76
{
77
  while (data->known_groups != NULL)
78
    {
79
      struct name_list *tmp = data->known_groups;
80
      data->known_groups = data->known_groups->next;
81
      free (tmp);
82
    }
83
 
84
  while (data->needed_groups != NULL)
85
    {
86
      struct name_list *tmp = data->needed_groups;
87
      data->needed_groups = data->needed_groups->next;
88
      free (tmp);
89
    }
90
}
91
 
92
static int
93
internal_function
94
__internal_setnetgrent_reuse (const char *group, struct __netgrent *datap,
95
                              int *errnop)
96
{
97
  union
98
  {
99
    enum nss_status (*f) (const char *, struct __netgrent *);
100
    void *ptr;
101
  } fct;
102
  enum nss_status status = NSS_STATUS_UNAVAIL;
103
  struct name_list *new_elem;
104
 
105
  /* Cycle through all the services and run their setnetgrent functions.  */
106
  int no_more = setup (&fct.ptr, "setnetgrent", 1, &datap->nip);
107
  while (! no_more)
108
    {
109
      /* Ignore status, we force check in `__nss_next'.  */
110
      status = (*fct.f) (group, datap);
111
 
112
      no_more = __nss_next (&datap->nip, "setnetgrent", &fct.ptr, status, 0);
113
    }
114
 
115
  /* Add the current group to the list of known groups.  */
116
  size_t group_len = strlen (group) + 1;
117
  new_elem = (struct name_list *) malloc (sizeof (struct name_list)
118
                                          + group_len);
119
  if (new_elem == NULL)
120
    {
121
      *errnop = errno;
122
      status = NSS_STATUS_TRYAGAIN;
123
    }
124
  else
125
    {
126
      new_elem->next = datap->known_groups;
127
      memcpy (new_elem->name, group, group_len);
128
      datap->known_groups = new_elem;
129
    }
130
 
131
  return status == NSS_STATUS_SUCCESS;
132
}
133
 
134
int internal_setnetgrent (const char *group, struct __netgrent *datap);
135
libc_hidden_proto (internal_setnetgrent)
136
 
137
int
138
internal_setnetgrent (const char *group, struct __netgrent *datap)
139
{
140
  /* Free list of all netgroup names from last run.  */
141
  free_memory (datap);
142
 
143
  return __internal_setnetgrent_reuse (group, datap, &errno);
144
}
145
libc_hidden_def (internal_setnetgrent)
146
strong_alias (internal_setnetgrent, __internal_setnetgrent)
147
 
148
int
149
setnetgrent (const char *group)
150
{
151
  int result;
152
 
153
  __libc_lock_lock (lock);
154
 
155
  result = internal_setnetgrent (group, &dataset);
156
 
157
  __libc_lock_unlock (lock);
158
 
159
  return result;
160
}
161
 
162
 
163
void internal_endnetgrent (struct __netgrent *datap);
164
libc_hidden_proto (internal_endnetgrent)
165
 
166
void
167
internal_endnetgrent (struct __netgrent *datap)
168
{
169
  service_user *old_nip;
170
  union
171
  {
172
    enum nss_status (*f) (struct __netgrent *);
173
    void *ptr;
174
  } fct;
175
 
176
  /* Remember which was the last used service.  */
177
  old_nip = datap->nip;
178
 
179
  /* Cycle through all the services and run their endnetgrent functions.  */
180
  int no_more = setup (&fct.ptr, "endnetgrent", 1, &datap->nip);
181
  while (! no_more)
182
    {
183
      /* Ignore status, we force check in `__nss_next'.  */
184
      (void) (*fct.f) (datap);
185
 
186
      no_more = (datap->nip == old_nip
187
                 || __nss_next (&datap->nip, "endnetgrent", &fct.ptr, 0, 1));
188
    }
189
 
190
  /* Now free list of all netgroup names from last run.  */
191
  free_memory (datap);
192
}
193
libc_hidden_def (internal_endnetgrent)
194
strong_alias (internal_endnetgrent, __internal_endnetgrent)
195
 
196
 
197
void
198
endnetgrent (void)
199
{
200
  __libc_lock_lock (lock);
201
 
202
  internal_endnetgrent (&dataset);
203
 
204
  __libc_lock_unlock (lock);
205
}
206
 
207
 
208
int internal_getnetgrent_r (char **hostp, char **userp, char **domainp,
209
                            struct __netgrent *datap,
210
                            char *buffer, size_t buflen, int *errnop);
211
libc_hidden_proto (internal_getnetgrent_r)
212
 
213
int
214
internal_getnetgrent_r (char **hostp, char **userp, char **domainp,
215
                          struct __netgrent *datap,
216
                          char *buffer, size_t buflen, int *errnop)
217
{
218
  union
219
  {
220
    enum nss_status (*f) (struct __netgrent *, char *, size_t, int *);
221
    void *ptr;
222
  } fct;
223
 
224
  /* Initialize status to return if no more functions are found.  */
225
  enum nss_status status = NSS_STATUS_NOTFOUND;
226
 
227
  /* Run through available functions, starting with the same function last
228
     run.  We will repeat each function as long as it succeeds, and then go
229
     on to the next service action.  */
230
  int no_more = setup (&fct.ptr, "getnetgrent_r", 0, &datap->nip);
231
  while (! no_more)
232
    {
233
      status = (*fct.f) (datap, buffer, buflen, &errno);
234
 
235
      if (status == NSS_STATUS_RETURN)
236
        {
237
          /* This was the last one for this group.  Look at next group
238
             if available.  */
239
          int found = 0;
240
          while (datap->needed_groups != NULL && ! found)
241
            {
242
              struct name_list *tmp = datap->needed_groups;
243
              datap->needed_groups = datap->needed_groups->next;
244
              tmp->next = datap->known_groups;
245
              datap->known_groups = tmp;
246
 
247
              found = __internal_setnetgrent_reuse (datap->known_groups->name,
248
                                                    datap, errnop);
249
            }
250
 
251
          if (found)
252
            continue;
253
        }
254
      else if (status == NSS_STATUS_SUCCESS && datap->type == group_val)
255
        {
256
          /* The last entry was a name of another netgroup.  */
257
          struct name_list *namep;
258
 
259
          /* Ignore if we've seen the name before.  */
260
          for (namep = datap->known_groups; namep != NULL;
261
               namep = namep->next)
262
            if (strcmp (datap->val.group, namep->name) == 0)
263
              break;
264
          if (namep != NULL)
265
            /* Really ignore.  */
266
            continue;
267
 
268
          size_t group_len = strlen (datap->val.group) + 1;
269
          namep = (struct name_list *) malloc (sizeof (struct name_list)
270
                                               + group_len);
271
          if (namep == NULL)
272
            /* We are out of memory.  */
273
            status = NSS_STATUS_RETURN;
274
          else
275
            {
276
              namep->next = datap->needed_groups;
277
              memcpy (namep->name, datap->val.group, group_len);
278
              datap->needed_groups = namep;
279
              /* And get the next entry.  */
280
              continue;
281
            }
282
        }
283
 
284
      no_more = __nss_next (&datap->nip, "getnetgrent_r", &fct.ptr, status, 0);
285
    }
286
 
287
  if (status == NSS_STATUS_SUCCESS)
288
    {
289
      *hostp = (char *) datap->val.triple.host;
290
      *userp = (char *) datap->val.triple.user;
291
      *domainp = (char *) datap->val.triple.domain;
292
    }
293
 
294
  return status == NSS_STATUS_SUCCESS ? 1 : 0;
295
}
296
libc_hidden_def (internal_getnetgrent_r)
297
strong_alias (internal_getnetgrent_r, __internal_getnetgrent_r)
298
 
299
/* The real entry point.  */
300
int
301
__getnetgrent_r (char **hostp, char **userp, char **domainp,
302
                 char *buffer, size_t buflen)
303
{
304
  enum nss_status status;
305
 
306
  __libc_lock_lock (lock);
307
 
308
  status = internal_getnetgrent_r (hostp, userp, domainp, &dataset,
309
                                   buffer, buflen, &errno);
310
 
311
  __libc_lock_unlock (lock);
312
 
313
  return status;
314
}
315
weak_alias (__getnetgrent_r, getnetgrent_r)
316
 
317
/* Test whether given (host,user,domain) triple is in NETGROUP.  */
318
int
319
innetgr (const char *netgroup, const char *host, const char *user,
320
         const char *domain)
321
{
322
  union
323
  {
324
    int (*f) (const char *, struct __netgrent *);
325
    void *ptr;
326
  } setfct;
327
  union
328
  {
329
    void (*f) (struct __netgrent *);
330
    void *ptr;
331
  } endfct;
332
  union
333
  {
334
    int (*f) (struct __netgrent *, char *, size_t, int *);
335
    void *ptr;
336
  } getfct;
337
  struct __netgrent entry;
338
  int result = 0;
339
  const char *current_group = netgroup;
340
  int real_entry = 0;
341
 
342
  memset (&entry, '\0', sizeof (entry));
343
 
344
  /* Walk through the services until we found an answer or we shall
345
     not work further.  We can do some optimization here.  Since all
346
     services must provide the `setnetgrent' function we can do all
347
     the work during one walk through the service list.  */
348
  while (1)
349
    {
350
      int no_more = setup (&setfct.ptr, "setnetgrent", 1, &entry.nip);
351
      while (! no_more)
352
        {
353
          /* Open netgroup.  */
354
          enum nss_status status = (*setfct.f) (current_group, &entry);
355
 
356
          if (status == NSS_STATUS_SUCCESS
357
              && __nss_lookup (&entry.nip, "getnetgrent_r", &getfct.ptr) == 0)
358
            {
359
              char buffer[1024];
360
 
361
              while ((*getfct.f) (&entry, buffer, sizeof buffer, &errno)
362
                     == NSS_STATUS_SUCCESS)
363
                {
364
                  if (entry.type == group_val)
365
                    {
366
                      /* Make sure we haven't seen the name before.  */
367
                      struct name_list *namep;
368
 
369
                      for (namep = entry.known_groups; namep != NULL;
370
                           namep = namep->next)
371
                        if (strcmp (entry.val.group, namep->name) == 0)
372
                          break;
373
                      if (namep == NULL
374
                          && strcmp (netgroup, entry.val.group) != 0)
375
                        {
376
                          size_t group_len = strlen (entry.val.group) + 1;
377
                          namep =
378
                            (struct name_list *) malloc (sizeof (*namep)
379
                                                         + group_len);
380
                          if (namep == NULL)
381
                            {
382
                              /* Out of memory, simply return.  */
383
                              result = -1;
384
                              break;
385
                            }
386
 
387
                          namep->next = entry.needed_groups;
388
                          memcpy (namep->name, entry.val.group, group_len);
389
                          entry.needed_groups = namep;
390
                        }
391
                    }
392
                  else
393
                    {
394
                      real_entry = 1;
395
 
396
                      if ((entry.val.triple.host == NULL || host == NULL
397
                           || strcasecmp (entry.val.triple.host, host) == 0)
398
                          && (entry.val.triple.user == NULL || user == NULL
399
                              || strcmp (entry.val.triple.user, user) == 0)
400
                          && (entry.val.triple.domain == NULL || domain == NULL
401
                              || strcasecmp (entry.val.triple.domain,
402
                                               domain) == 0))
403
                        {
404
                          result = 1;
405
                          break;
406
                        }
407
                    }
408
                }
409
 
410
              if (result != 0)
411
                break;
412
 
413
              /* If we found one service which does know the given
414
                 netgroup we don't try further.  */
415
              status = NSS_STATUS_RETURN;
416
            }
417
 
418
          /* Free all resources of the service.  */
419
          if (__nss_lookup (&entry.nip, "endnetgrent", &endfct.ptr) == 0)
420
            (*endfct.f) (&entry);
421
 
422
          /* Look for the next service.  */
423
          no_more = __nss_next (&entry.nip, "setnetgrent",
424
                                &setfct.ptr, status, 0);
425
        }
426
 
427
      if (result == 0 && entry.needed_groups != NULL)
428
        {
429
          struct name_list *tmp = entry.needed_groups;
430
          entry.needed_groups = tmp->next;
431
          tmp->next = entry.known_groups;
432
          entry.known_groups = tmp;
433
          current_group = entry.known_groups->name;
434
          continue;
435
        }
436
 
437
      /* No way out.  */
438
      break;
439
    }
440
 
441
  /* Free the memory.  */
442
  free_memory (&entry);
443
 
444
  return result;
445
}
446
libc_hidden_def (innetgr)

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.