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/] [nsswitch.c] - Blame information for rev 158

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 148 jeremybenn
/* Copyright (C) 1996, 1997, 1998, 1999, 2001, 2002, 2003, 2004
2
   Free Software Foundation, Inc.
3
   This file is part of the GNU C Library.
4
   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
5
 
6
   The GNU C Library is free software; you can redistribute it and/or
7
   modify it under the terms of the GNU Lesser General Public
8
   License as published by the Free Software Foundation; either
9
   version 2.1 of the License, or (at your option) any later version.
10
 
11
   The GNU C Library is distributed in the hope that it will be useful,
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
   Lesser General Public License for more details.
15
 
16
   You should have received a copy of the GNU Lesser General Public
17
   License along with the GNU C Library; if not, write to the Free
18
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19
   02111-1307 USA.  */
20
 
21
#include <ctype.h>
22
#include <dlfcn.h>
23
#include <errno.h>
24
#include <netdb.h>
25
#include <bits/libc-lock.h>
26
#include <search.h>
27
#include <stdio.h>
28
#include <stdio_ext.h>
29
#include <stdlib.h>
30
#include <string.h>
31
 
32
#include <aliases.h>
33
#include <grp.h>
34
#include <netinet/ether.h>
35
#include <pwd.h>
36
#include <shadow.h>
37
 
38
#include "local.h"
39
 
40
#if !defined DO_STATIC_NSS || defined SHARED
41
# include <gnu/lib-names.h>
42
#endif
43
 
44
#include "nsswitch.h"
45
#include "nscd/nscd_proto.h"
46
 
47
/* Prototypes for the local functions.  */
48
static name_database *nss_parse_file (const char *fname) internal_function;
49
static name_database_entry *nss_getline (char *line) internal_function;
50
static service_user *nss_parse_service_list (const char *line)
51
     internal_function;
52
static service_library *nss_new_service (name_database *database,
53
                                         const char *name) internal_function;
54
 
55
 
56
/* Declare external database variables.  */
57
#define DEFINE_DATABASE(name)                                                 \
58
  extern service_user *__nss_##name##_database attribute_hidden;              \
59
  weak_extern (__nss_##name##_database)
60
#include "databases.def"
61
#undef DEFINE_DATABASE
62
 
63
/* Structure to map database name to variable.  */
64
static struct
65
{
66
  const char *name;
67
  service_user **dbp;
68
} databases[] =
69
{
70
#define DEFINE_DATABASE(name)                                                 \
71
  { #name, &__nss_##name##_database },
72
#include "databases.def"
73
#undef DEFINE_DATABASE
74
};
75
 
76
 
77
__libc_lock_define_initialized (static, lock)
78
 
79
#if !defined DO_STATIC_NSS || defined SHARED
80
/* String with revision number of the shared object files.  */
81
static const char *const __nss_shlib_revision = LIBNSS_FILES_SO + 15;
82
#endif
83
 
84
/* The root of the whole data base.  */
85
static name_database *service_table;
86
 
87
 
88
/* -1 == database not found
89
 
90
int
91
__nss_database_lookup (const char *database, const char *alternate_name,
92
                       const char *defconfig, service_user **ni)
93
{
94
  /* Prevent multiple threads to change the service table.  */
95
  __libc_lock_lock (lock);
96
 
97
  /* Reconsider database variable in case some other thread called
98
     `__nss_configure_lookup' while we waited for the lock.  */
99
  if (*ni != NULL)
100
    {
101
      __libc_lock_unlock (lock);
102
      return 0;
103
    }
104
 
105
  /* Are we initialized yet?  */
106
  if (service_table == NULL)
107
    /* Read config file.  */
108
    service_table = nss_parse_file (_PATH_NSSWITCH_CONF);
109
 
110
  /* Test whether configuration data is available.  */
111
  if (service_table != NULL)
112
    {
113
      /* Return first `service_user' entry for DATABASE.  */
114
      name_database_entry *entry;
115
 
116
      /* XXX Could use some faster mechanism here.  But each database is
117
         only requested once and so this might not be critical.  */
118
      for (entry = service_table->entry; entry != NULL; entry = entry->next)
119
        if (strcmp (database, entry->name) == 0)
120
          *ni = entry->service;
121
 
122
      if (*ni == NULL && alternate_name != NULL)
123
        /* We haven't found an entry so far.  Try to find it with the
124
           alternative name.  */
125
        for (entry = service_table->entry; entry != NULL; entry = entry->next)
126
          if (strcmp (alternate_name, entry->name) == 0)
127
            *ni = entry->service;
128
    }
129
 
130
  /* No configuration data is available, either because nsswitch.conf
131
     doesn't exist or because it doesn't has a line for this database.
132
 
133
     DEFCONFIG specifies the default service list for this database,
134
     or null to use the most common default.  */
135
  if (*ni == NULL)
136
    *ni = nss_parse_service_list (defconfig
137
                                  ?: "nis [NOTFOUND=return] files");
138
 
139
  __libc_lock_unlock (lock);
140
 
141
  return 0;
142
}
143
libc_hidden_def (__nss_database_lookup)
144
 
145
 
146
/* -1 == not found
147
 
148
    1 == finished */
149
int
150
__nss_lookup (service_user **ni, const char *fct_name, void **fctp)
151
{
152
  *fctp = __nss_lookup_function (*ni, fct_name);
153
 
154
  while (*fctp == NULL
155
         && nss_next_action (*ni, NSS_STATUS_UNAVAIL) == NSS_ACTION_CONTINUE
156
         && (*ni)->next != NULL)
157
    {
158
      *ni = (*ni)->next;
159
 
160
      *fctp = __nss_lookup_function (*ni, fct_name);
161
    }
162
 
163
  return *fctp != NULL ? 0 : (*ni)->next == NULL ? 1 : -1;
164
}
165
 
166
 
167
/* -1 == not found
168
 
169
    1 == finished */
170
int
171
__nss_next (service_user **ni, const char *fct_name, void **fctp, int status,
172
            int all_values)
173
{
174
  if (all_values)
175
    {
176
      if (nss_next_action (*ni, NSS_STATUS_TRYAGAIN) == NSS_ACTION_RETURN
177
          && nss_next_action (*ni, NSS_STATUS_UNAVAIL) == NSS_ACTION_RETURN
178
          && nss_next_action (*ni, NSS_STATUS_NOTFOUND) == NSS_ACTION_RETURN
179
          && nss_next_action (*ni, NSS_STATUS_SUCCESS) == NSS_ACTION_RETURN)
180
        return 1;
181
    }
182
  else
183
    {
184
      /* This is really only for debugging.  */
185
       if (NSS_STATUS_TRYAGAIN > status || status > NSS_STATUS_RETURN)
186
         {
187
            fprintf (stderr, "illegal status in __nss_next");
188
            abort();
189
         }
190
 
191
       if (nss_next_action (*ni, status) == NSS_ACTION_RETURN)
192
         return 1;
193
    }
194
 
195
  if ((*ni)->next == NULL)
196
    return -1;
197
 
198
  do
199
    {
200
      *ni = (*ni)->next;
201
 
202
      *fctp = __nss_lookup_function (*ni, fct_name);
203
    }
204
  while (*fctp == NULL
205
         && nss_next_action (*ni, NSS_STATUS_UNAVAIL) == NSS_ACTION_CONTINUE
206
         && (*ni)->next != NULL);
207
 
208
  return *fctp != NULL ? 0 : -1;
209
}
210
libc_hidden_def (__nss_next)
211
 
212
 
213
int
214
__nss_configure_lookup (const char *dbname, const char *service_line)
215
{
216
  service_user *new_db;
217
  size_t cnt;
218
 
219
  for (cnt = 0; cnt < sizeof databases; ++cnt)
220
    {
221
      int cmp = strcmp (dbname, databases[cnt].name);
222
      if (cmp == 0)
223
        break;
224
      if (cmp < 0)
225
        {
226
          __set_errno (EINVAL);
227
          return -1;
228
        }
229
    }
230
 
231
  if (cnt == sizeof databases)
232
    {
233
      __set_errno (EINVAL);
234
      return -1;
235
    }
236
 
237
  /* Test whether it is really used.  */
238
  if (databases[cnt].dbp == NULL)
239
    /* Nothing to do, but we could do.  */
240
    return 0;
241
 
242
  /* Try to generate new data.  */
243
  new_db = nss_parse_service_list (service_line);
244
  if (new_db == NULL)
245
    {
246
      /* Illegal service specification.  */
247
      __set_errno (EINVAL);
248
      return -1;
249
    }
250
 
251
  /* Prevent multiple threads to change the service table.  */
252
  __libc_lock_lock (lock);
253
 
254
  /* Install new rules.  */
255
  *databases[cnt].dbp = new_db;
256
 
257
  __libc_lock_unlock (lock);
258
 
259
  return 0;
260
}
261
 
262
 
263
/* Comparison function for searching NI->known tree.  */
264
static int
265
known_compare (const void *p1, const void *p2)
266
{
267
  return p1 == p2 ? 0 : strcmp (*(const char *const *) p1,
268
                                *(const char *const *) p2);
269
}
270
 
271
 
272
void *
273
__nss_lookup_function (service_user *ni, const char *fct_name)
274
{
275
  void **found, *result;
276
 
277
  /* We now modify global data.  Protect it.  */
278
  __libc_lock_lock (lock);
279
 
280
  /* Search the tree of functions previously requested.  Data in the
281
     tree are `known_function' structures, whose first member is a
282
     `const char *', the lookup key.  The search returns a pointer to
283
     the tree node structure; the first member of the is a pointer to
284
     our structure (i.e. what will be a `known_function'); since the
285
     first member of that is the lookup key string, &FCT_NAME is close
286
     enough to a pointer to our structure to use as a lookup key that
287
     will be passed to `known_compare' (above).  */
288
 
289
  found = tsearch (&fct_name, (void **) &ni->known, &known_compare);
290
  if (*found != &fct_name)
291
    /* The search found an existing structure in the tree.  */
292
    result = ((known_function *) *found)->fct_ptr;
293
  else
294
    {
295
      /* This name was not known before.  Now we have a node in the tree
296
         (in the proper sorted position for FCT_NAME) that points to
297
         &FCT_NAME instead of any real `known_function' structure.
298
         Allocate a new structure and fill it in.  */
299
 
300
      known_function *known = malloc (sizeof *known);
301
      if (! known)
302
        {
303
        remove_from_tree:
304
          /* Oops.  We can't instantiate this node properly.
305
             Remove it from the tree.  */
306
          tdelete (&fct_name, (void **) &ni->known, &known_compare);
307
          result = NULL;
308
        }
309
      else
310
        {
311
          /* Point the tree node at this new structure.  */
312
          *found = known;
313
          known->fct_name = fct_name;
314
 
315
          if (ni->library == NULL)
316
            {
317
              /* This service has not yet been used.  Fetch the service
318
                 library for it, creating a new one if need be.  If there
319
                 is no service table from the file, this static variable
320
                 holds the head of the service_library list made from the
321
                 default configuration.  */
322
              static name_database default_table;
323
              ni->library = nss_new_service (service_table ?: &default_table,
324
                                             ni->name);
325
              if (ni->library == NULL)
326
                {
327
                  /* This only happens when out of memory.  */
328
                  free (known);
329
                  goto remove_from_tree;
330
                }
331
            }
332
 
333
#if !defined DO_STATIC_NSS || defined SHARED
334
          if (ni->library->lib_handle == NULL)
335
            {
336
              /* Load the shared library.  */
337
              size_t shlen = (7 + strlen (ni->library->name) + 3
338
                              + strlen (__nss_shlib_revision) + 1);
339
              int saved_errno = errno;
340
              char shlib_name[shlen];
341
 
342
              /* Construct shared object name.  */
343
              stpcpy (stpcpy (stpcpy (stpcpy (shlib_name,
344
                                                      "libnss_"),
345
                                            ni->library->name),
346
                                  ".so"),
347
                        __nss_shlib_revision);
348
 
349
              ni->library->lib_handle = __libc_dlopen (shlib_name);
350
              if (ni->library->lib_handle == NULL)
351
                {
352
                  /* Failed to load the library.  */
353
                  ni->library->lib_handle = (void *) -1l;
354
                  __set_errno (saved_errno);
355
                }
356
            }
357
 
358
          if (ni->library->lib_handle == (void *) -1l)
359
            /* Library not found => function not found.  */
360
            result = NULL;
361
          else
362
            {
363
              /* Get the desired function.  */
364
              size_t namlen = (5 + strlen (ni->library->name) + 1
365
                               + strlen (fct_name) + 1);
366
              char name[namlen];
367
 
368
              /* Construct the function name.  */
369
              stpcpy (stpcpy (stpcpy (stpcpy (name, "_nss_"),
370
                                            ni->library->name),
371
                                  "_"),
372
                        fct_name);
373
 
374
              /* Look up the symbol.  */
375
              result = __libc_dlsym (ni->library->lib_handle, name);
376
            }
377
#else
378
          /* We can't get function address dynamically in static linking. */
379
          {
380
# define DEFINE_ENT(h,nm)                                                     \
381
            { #h"_get"#nm"ent_r", _nss_##h##_get##nm##ent_r },                \
382
            { #h"_end"#nm"ent", _nss_##h##_end##nm##ent },                    \
383
            { #h"_set"#nm"ent", _nss_##h##_set##nm##ent },
384
# define DEFINE_GET(h,nm)                                                     \
385
            { #h"_get"#nm"_r", _nss_##h##_get##nm##_r },
386
# define DEFINE_GETBY(h,nm,ky)                                                \
387
            { #h"_get"#nm"by"#ky"_r", _nss_##h##_get##nm##by##ky##_r },
388
            static struct fct_tbl { const char *fname; void *fp; } *tp, tbl[] =
389
              {
390
# include "function.def"
391
                { NULL, NULL }
392
              };
393
            size_t namlen = (5 + strlen (ni->library->name) + 1
394
                             + strlen (fct_name) + 1);
395
            char name[namlen];
396
 
397
            /* Construct the function name.  */
398
            stpcpy (stpcpy (stpcpy (name, ni->library->name),
399
                                "_"),
400
                      fct_name);
401
 
402
            result = NULL;
403
            for (tp = &tbl[0]; tp->fname; tp++)
404
              if (strcmp (tp->fname, name) == 0)
405
                {
406
                  result = tp->fp;
407
                  break;
408
                }
409
          }
410
#endif
411
 
412
          /* Remember function pointer for later calls.  Even if null, we
413
             record it so a second try needn't search the library again.  */
414
          known->fct_ptr = result;
415
        }
416
    }
417
 
418
  /* Remove the lock.  */
419
  __libc_lock_unlock (lock);
420
 
421
  return result;
422
}
423
libc_hidden_def (__nss_lookup_function)
424
 
425
 
426
static name_database *
427
internal_function
428
nss_parse_file (const char *fname)
429
{
430
  FILE *fp;
431
  name_database *result;
432
  name_database_entry *last;
433
  char *line;
434
  size_t len;
435
 
436
  /* Open the configuration file.  */
437
  fp = fopen (fname, "rc");
438
  if (fp == NULL)
439
    return NULL;
440
 
441
  /* No threads use this stream.  */
442
  __fsetlocking (fp, FSETLOCKING_BYCALLER);
443
 
444
  result = (name_database *) malloc (sizeof (name_database));
445
  if (result == NULL)
446
    return NULL;
447
 
448
  result->entry = NULL;
449
  result->library = NULL;
450
  last = NULL;
451
  line = NULL;
452
  len = 0;
453
  do
454
    {
455
      name_database_entry *this;
456
      ssize_t n;
457
      char *tmp;
458
 
459
      n = __getline (&line, &len, fp);
460
      if (n < 0)
461
        break;
462
      if (line[n - 1] == '\n')
463
        line[n - 1] = '\0';
464
 
465
      /* Because the file format does not know any form of quoting we
466
         can search forward for the next '#' character and if found
467
         make it terminating the line.  */
468
      tmp = strchr (line, '#');
469
      if (tmp == NULL)
470
        tmp = line + strlen (line);
471
      *tmp = '\0';
472
 
473
      /* If the line is blank it is ignored.  */
474
      if (line[0] == '\0')
475
        continue;
476
 
477
      /* Each line completely specifies the actions for a database.  */
478
      this = nss_getline (line);
479
      if (this != NULL)
480
        {
481
          if (last != NULL)
482
            last->next = this;
483
          else
484
            result->entry = this;
485
 
486
          last = this;
487
        }
488
    }
489
  while (!feof (fp));
490
 
491
  /* Free the buffer.  */
492
  free (line);
493
  /* Close configuration file.  */
494
  fclose (fp);
495
 
496
  return result;
497
}
498
 
499
 
500
/* Read the source names:
501
        `( <source> ( "[" "!"? (<status> "=" <action> )+ "]" )? )*'
502
   */
503
static service_user *
504
internal_function
505
nss_parse_service_list (const char *line)
506
{
507
  service_user *result = NULL, **nextp = &result;
508
 
509
  while (1)
510
    {
511
      service_user *new_service;
512
      const char *name;
513
 
514
      while (isspace (line[0]))
515
        ++line;
516
      if (line[0] == '\0')
517
        /* No source specified.  */
518
        return result;
519
 
520
      /* Read <source> identifier.  */
521
      name = line;
522
      while (line[0] != '\0' && !isspace (line[0]) && line[0] != '[')
523
        ++line;
524
      if (name == line)
525
        return result;
526
 
527
 
528
      new_service = (service_user *) malloc (sizeof (service_user)
529
                                             + (line - name + 1));
530
      if (new_service == NULL)
531
        return result;
532
 
533
      *((char *) mempcpy (new_service->name, name, line - name)) = '\0';
534
 
535
      /* Set default actions.  */
536
      new_service->actions[2 + NSS_STATUS_TRYAGAIN] = NSS_ACTION_CONTINUE;
537
      new_service->actions[2 + NSS_STATUS_UNAVAIL] = NSS_ACTION_CONTINUE;
538
      new_service->actions[2 + NSS_STATUS_NOTFOUND] = NSS_ACTION_CONTINUE;
539
      new_service->actions[2 + NSS_STATUS_SUCCESS] = NSS_ACTION_RETURN;
540
      new_service->actions[2 + NSS_STATUS_RETURN] = NSS_ACTION_RETURN;
541
      new_service->library = NULL;
542
      new_service->known = NULL;
543
      new_service->next = NULL;
544
 
545
      while (isspace (line[0]))
546
        ++line;
547
 
548
      if (line[0] == '[')
549
        {
550
          /* Read criterions.  */
551
          do
552
            ++line;
553
          while (line[0] != '\0' && isspace (line[0]));
554
 
555
          do
556
            {
557
              int not;
558
              enum nss_status status;
559
              lookup_actions action;
560
 
561
              /* Grok ! before name to mean all statii but that one.  */
562
              not = line[0] == '!';
563
              if (not)
564
                ++line;
565
 
566
              /* Read status name.  */
567
              name = line;
568
              while (line[0] != '\0' && !isspace (line[0]) && line[0] != '='
569
                     && line[0] != ']')
570
                ++line;
571
 
572
              /* Compare with known statii.  */
573
              if (line - name == 7)
574
                {
575
                  if (strncasecmp (name, "SUCCESS", 7) == 0)
576
                    status = NSS_STATUS_SUCCESS;
577
                  else if (strncasecmp (name, "UNAVAIL", 7) == 0)
578
                    status = NSS_STATUS_UNAVAIL;
579
                  else
580
                    return result;
581
                }
582
              else if (line - name == 8)
583
                {
584
                  if (strncasecmp (name, "NOTFOUND", 8) == 0)
585
                    status = NSS_STATUS_NOTFOUND;
586
                  else if (strncasecmp (name, "TRYAGAIN", 8) == 0)
587
                    status = NSS_STATUS_TRYAGAIN;
588
                  else
589
                    return result;
590
                }
591
              else
592
                return result;
593
 
594
              while (isspace (line[0]))
595
                ++line;
596
              if (line[0] != '=')
597
                return result;
598
              do
599
                ++line;
600
              while (isspace (line[0]));
601
 
602
              name = line;
603
              while (line[0] != '\0' && !isspace (line[0]) && line[0] != '='
604
                     && line[0] != ']')
605
                ++line;
606
 
607
              if (line - name == 6 && strncasecmp (name, "RETURN", 6) == 0)
608
                action = NSS_ACTION_RETURN;
609
              else if (line - name == 8
610
                       && strncasecmp (name, "CONTINUE", 8) == 0)
611
                action = NSS_ACTION_CONTINUE;
612
              else
613
                return result;
614
 
615
              if (not)
616
                {
617
                  /* Save the current action setting for this status,
618
                     set them all to the given action, and reset this one.  */
619
                  const lookup_actions save = new_service->actions[2 + status];
620
                  new_service->actions[2 + NSS_STATUS_TRYAGAIN] = action;
621
                  new_service->actions[2 + NSS_STATUS_UNAVAIL] = action;
622
                  new_service->actions[2 + NSS_STATUS_NOTFOUND] = action;
623
                  new_service->actions[2 + NSS_STATUS_SUCCESS] = action;
624
                  new_service->actions[2 + status] = save;
625
                }
626
              else
627
                new_service->actions[2 + status] = action;
628
 
629
              /* Skip white spaces.  */
630
              while (isspace (line[0]))
631
                ++line;
632
            }
633
          while (line[0] != ']');
634
 
635
          /* Skip the ']'.  */
636
          ++line;
637
        }
638
 
639
      *nextp = new_service;
640
      nextp = &new_service->next;
641
    }
642
}
643
 
644
static name_database_entry *
645
internal_function
646
nss_getline (char *line)
647
{
648
  const char *name;
649
  name_database_entry *result;
650
  size_t len;
651
 
652
  /* Ignore leading white spaces.  ATTENTION: this is different from
653
     what is implemented in Solaris.  The Solaris man page says a line
654
     beginning with a white space character is ignored.  We regard
655
     this as just another misfeature in Solaris.  */
656
  while (isspace (line[0]))
657
    ++line;
658
 
659
  /* Recognize `<database> ":"'.  */
660
  name = line;
661
  while (line[0] != '\0' && !isspace (line[0]) && line[0] != ':')
662
    ++line;
663
  if (line[0] == '\0' || name == line)
664
    /* Syntax error.  */
665
    return NULL;
666
  *line++ = '\0';
667
 
668
  len = strlen (name) + 1;
669
 
670
  result = (name_database_entry *) malloc (sizeof (name_database_entry) + len);
671
  if (result == NULL)
672
    return NULL;
673
 
674
  /* Save the database name.  */
675
  memcpy (result->name, name, len);
676
 
677
  /* Parse the list of services.  */
678
  result->service = nss_parse_service_list (line);
679
 
680
  result->next = NULL;
681
  return result;
682
}
683
 
684
 
685
static service_library *
686
internal_function
687
nss_new_service (name_database *database, const char *name)
688
{
689
  service_library **currentp = &database->library;
690
 
691
  while (*currentp != NULL)
692
    {
693
      if (strcmp ((*currentp)->name, name) == 0)
694
        return *currentp;
695
      currentp = &(*currentp)->next;
696
    }
697
 
698
  /* We have to add the new service.  */
699
  *currentp = (service_library *) malloc (sizeof (service_library));
700
  if (*currentp == NULL)
701
    return NULL;
702
 
703
  (*currentp)->name = name;
704
  (*currentp)->lib_handle = NULL;
705
  (*currentp)->next = NULL;
706
 
707
  return *currentp;
708
}
709
 
710
 
711
#ifdef USE_NSCD
712
/* Called by nscd and nscd alone.  */
713
void
714
__nss_disable_nscd (void)
715
{
716
  /* Disable all uses of NSCD.  */
717
  __nss_not_use_nscd_passwd = -1;
718
  __nss_not_use_nscd_group = -1;
719
  __nss_not_use_nscd_hosts = -1;
720
}
721
#endif
722
 
723
 
724
/* Free all resources if necessary.  */
725
libc_freeres_fn (free_mem)
726
{
727
  name_database *top = service_table;
728
  name_database_entry *entry;
729
  service_library *library;
730
 
731
  if (top == NULL)
732
    /* Maybe we have not read the nsswitch.conf file.  */
733
    return;
734
 
735
  /* Don't disturb ongoing other threads (if there are any).  */
736
  service_table = NULL;
737
 
738
  entry = top->entry;
739
  while (entry != NULL)
740
    {
741
      name_database_entry *olde = entry;
742
      service_user *service = entry->service;
743
 
744
      while (service != NULL)
745
        {
746
          service_user *olds = service;
747
 
748
          if (service->known != NULL)
749
            tdestroy (service->known, free);
750
 
751
          service = service->next;
752
          free (olds);
753
        }
754
 
755
      entry = entry->next;
756
      free (olde);
757
    }
758
 
759
  library = top->library;
760
  while (library != NULL)
761
    {
762
      service_library *oldl = library;
763
 
764
      if (library->lib_handle && library->lib_handle != (void *) -1l)
765
        __libc_dlclose (library->lib_handle);
766
 
767
      library = library->next;
768
      free (oldl);
769
    }
770
 
771
  free (top);
772
}

powered by: WebSVN 2.1.0

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