home *** CD-ROM | disk | FTP | other *** search
/ Serving the Web / ServingTheWeb1995.disc1of1.iso / linux / slacksrce / d / libc / libc-4.6 / libc-4 / libc-linux / pwd / getpwent.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-17  |  9.0 KB  |  369 lines

  1. /* Copyright (C) 1991 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 Library General Public License as
  6. published by the Free Software Foundation; either version 2 of the
  7. 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. Library General Public License for more details.
  13.  
  14. You should have received a copy of the GNU Library General Public
  15. License along with the GNU C Library; see the file COPYING.LIB.  If
  16. not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  17. Cambridge, MA 02139, USA.  */
  18.  
  19. #include <ansidecl.h>
  20. #include <stddef.h>
  21. #include <stdio.h>
  22. #include <pwd.h>
  23.  
  24. #ifdef YP
  25. #include <time.h>
  26. #define USE_NETGROUP 1
  27. /* Don't define this if you're short of memory */
  28. #define USE_YP_ALL 1
  29. #include <rpcsvc/yp_prot.h>
  30. #include <rpcsvc/ypclnt.h>
  31. extern int __yp_check(char **);
  32. extern struct passwd * __nis_parsepwddata(char *, void *);
  33. extern struct passwd * __nis_getpwnam(const char *, void *);
  34. static struct passwd * __nis_getpwent(int, void *);
  35. #if USE_NETGROUP
  36. extern void setnetgrent(const char *);
  37. extern void endnetgrent(void);
  38. extern int getnetgrent(char **, char **, char **);
  39. extern int innetgr(const char *, char *, char *, char *);
  40. static struct passwd * __netgroup_getpwent(const char *, int, void *);
  41. #endif /* USE_NETGROUP */
  42. static int ypmode = 0;
  43. static int netgroupmode = 0;
  44. static int inkeylen;
  45. static char *inkey = NULL;
  46. #if USE_YP_ALL
  47. #define NIS_CACHE_TIMEOUT 60
  48. /*
  49.  * These values should be adjusted to the actual size of the password
  50.  * file to avoid unnessecary mallocs.
  51.  */
  52. #define NIS_CACHE_INITIAL_SIZE 64*1024
  53. #define NIS_CACHE_INCREMENT 16*1024
  54. struct _nis_cache 
  55. {
  56.   char *data;
  57.   int current;
  58.   int size;
  59.   time_t update;
  60. };
  61.  
  62. static struct _nis_cache nis_cache = { NULL, 0, 0, 0 };
  63. static int __nis_store_map(int, char *, int, char *, int, char *);
  64. static struct passwd *__nis_get_first_cached_entry(void *);
  65. static struct passwd *__nis_get_next_cached_entry(void *);
  66. #endif /* USE_YP_ALL */
  67. #endif /* YP */
  68.  
  69. static FILE *stream = NULL;
  70.  
  71. /* Rewind the stream.  */
  72. void
  73. DEFUN_VOID(setpwent)
  74. {
  75.   if (stream != NULL)
  76.     rewind(stream);
  77. #ifdef YP
  78.   ypmode = netgroupmode = 0;
  79.   if(NULL != inkey)
  80.     {
  81.       free (inkey);
  82.       inkey = NULL;
  83.     }
  84. #endif /* YP */
  85. }
  86.  
  87.  
  88. /* Close the stream.  */
  89. void
  90. DEFUN_VOID(endpwent)
  91. {
  92.   if (stream != NULL)
  93.     {
  94.       (void) fclose(stream);
  95.       stream = NULL;
  96.     }
  97. #ifdef YP
  98.   ypmode = netgroupmode = 0;
  99.   if(NULL != inkey)
  100.     {
  101.       free (inkey);
  102.       inkey = NULL;
  103.     }
  104. #endif /* YP */
  105. }
  106.  
  107.  
  108. /* Return one entry from the password file.  */
  109. struct passwd *
  110. DEFUN_VOID(getpwent)
  111. {
  112. #ifdef YP
  113.   struct passwd *pwtmp;
  114.   static void *info_nis = NULL;
  115. #endif /* YP */
  116.   static PTR info = NULL;
  117.   if (NULL == info)
  118.     {
  119.       info = __pwdalloc();
  120.       if (NULL == info)
  121.         return(NULL);
  122.     }
  123.   
  124.   if (NULL == stream)
  125.     {
  126.       stream = __pwdopen();
  127.       if (NULL == stream)
  128.         return(NULL);
  129.     }
  130. #ifdef YP
  131. #if USE_NETGROUP
  132.   if ( 1 == netgroupmode)
  133.     {
  134.       pwtmp = __netgroup_getpwent(NULL, 0, info);
  135.       if (NULL != pwtmp)
  136.         return pwtmp;
  137.     }
  138. #endif /* USE_NETGROUP */
  139.   if ( 1 == ypmode )
  140.     {
  141.       pwtmp = __nis_getpwent(0, info);
  142.       if (NULL != pwtmp)
  143.         return pwtmp;
  144.     }
  145.   
  146.   again:
  147.       /* disable -user entries */
  148.   do
  149.     {
  150.       pwtmp = __pwdread(stream, info);
  151.     }
  152.   while(NULL != pwtmp && '-' == pwtmp->pw_name[0]) ;
  153.   if (NULL == pwtmp)
  154.     return NULL;
  155. #if USE_NETGROUP
  156.       /* Handle +@netgroup entries */
  157.   if ('+' == pwtmp->pw_name[0]
  158.       && '@' == pwtmp->pw_name[1]
  159.       && '\0' != pwtmp->pw_name[2])
  160.     {
  161.       netgroupmode = 1;
  162.       pwtmp = __netgroup_getpwent(&pwtmp->pw_name[2], 1, info);
  163.       if (NULL == pwtmp) 
  164.         {
  165.           netgroupmode = 0;
  166.           goto again;
  167.         }
  168.     }
  169. #endif /* USE_NETGROUP */      
  170.       /*
  171.        * Handle +user entries.
  172.        * Bug: overwriting of pw_passwd field
  173.        *      not supported (yet). --Swen
  174.        */
  175.   if ('+' == pwtmp->pw_name[0] && '\0' != pwtmp->pw_name[1])
  176.     {
  177.       struct passwd *pwd = pwtmp;
  178.       if (NULL == info_nis)
  179.         {
  180.           info_nis = __pwdalloc();
  181.           if (NULL == info_nis)
  182.             return(NULL);
  183.         }
  184.       pwtmp = __nis_getpwnam(pwtmp->pw_name + 1, info_nis);
  185.       if (NULL == pwtmp)
  186.         goto again;
  187.       if (NULL != pwd->pw_gecos && '\0' != *pwd->pw_gecos)
  188.         pwtmp->pw_gecos = pwd->pw_gecos;
  189.       if (NULL != pwd->pw_dir && '\0' != *pwd->pw_dir)
  190.         pwtmp->pw_dir   = pwd->pw_dir  ;
  191.       if (NULL != pwd->pw_shell && '\0' != *pwd->pw_shell)
  192.         pwtmp->pw_shell = pwd->pw_shell;
  193.     }
  194.   
  195.   if (0 == strcmp(pwtmp->pw_name, "+"))
  196.     {
  197.       ypmode = 1;
  198.       pwtmp = __nis_getpwent(1, info);
  199.     }
  200.   
  201.   return(pwtmp);
  202. #else /* !YP */
  203.   return(__pwdread(stream, info));
  204. #endif /* YP */
  205. }
  206.  
  207. #ifdef YP
  208. static struct passwd *
  209. __nis_getpwent(int first, void *info)
  210. {
  211.   static char *nisdomain = NULL;
  212.   char *outkey, *outval;
  213.   int outkeylen, outvallen, status;
  214.   struct passwd *pwptr;
  215.   
  216.   if (1 == __yp_check(NULL))
  217.     {
  218.       if (NULL == nisdomain)
  219.         yp_get_default_domain(&nisdomain);
  220.       if (1 == first)
  221.         {
  222. #if USE_YP_ALL
  223.           if ((time(NULL) - nis_cache.update ) > NIS_CACHE_TIMEOUT )
  224.             {
  225.               struct ypall_callback ypcb;
  226.               ypcb.foreach = __nis_store_map;
  227.               ypcb.data = NULL;
  228.               status = yp_all(nisdomain, "passwd.byname", &ypcb);
  229.               if (0 != status)
  230.                 return NULL;
  231.               nis_cache.update = time(NULL);
  232.             }
  233.           pwptr = __nis_get_first_cached_entry(info);
  234.           return(pwptr);
  235. #endif /* USE_YP_ALL */
  236.           status = yp_first(nisdomain, "passwd.byname",
  237.                             &outkey, &outkeylen,
  238.                             &outval, &outvallen);
  239.           if (0 != status)
  240.             return NULL;
  241.           inkey = outkey;
  242.           inkeylen = outkeylen;
  243.               /* Assumption: No comment lines in NIS maps */
  244.           pwptr = __nis_parsepwddata(outval, info);
  245.           free (outval);
  246.           return (pwptr);
  247.         }
  248.       else
  249.         {
  250. #if USE_YP_ALL
  251.           pwptr = __nis_get_next_cached_entry(info);
  252.           return(pwptr);
  253. #endif /* USE_YP_ALL */
  254.           status = yp_next(nisdomain, "passwd.byname",
  255.                            inkey, inkeylen,
  256.                            &outkey, &outkeylen,
  257.                            &outval, &outvallen);
  258.           if (0 != status)
  259.             {
  260.               free(inkey);
  261.               inkey = NULL;
  262.               return NULL;
  263.             }
  264.           free (inkey);
  265.           inkey = outkey;
  266.           inkeylen = outkeylen;
  267.               /* Assumption: No comment lines in NIS maps */
  268.           pwptr = __nis_parsepwddata(outval, info);
  269.           free (outval);
  270.           return (pwptr);
  271.         }
  272.     }
  273.   return NULL;
  274. }
  275.  
  276. #if USE_NETGROUP
  277. static struct passwd *
  278. __netgroup_getpwent(const char *netgr, int first, void *info)
  279. {
  280.   static char *nisdomain = NULL;
  281.   char *host, *user, *domain;
  282.   int status;
  283.  
  284.   if (NULL == nisdomain)
  285.     yp_get_default_domain(&nisdomain);
  286.   
  287.   if (1 == first)
  288.       setnetgrent(netgr);
  289.   
  290.  
  291.   while (1 == (status = getnetgrent(&host, &user, &domain))
  292.          && NULL == user
  293.          && NULL != domain
  294.          && 0 != strcmp(domain, nisdomain))
  295.     ;
  296.   
  297.   if (0 == status || NULL == user)
  298.     {
  299.       endnetgrent();
  300.       netgroupmode = 0;
  301.       return NULL;
  302.     }
  303.   return __nis_getpwnam(user, info);
  304. }
  305. #endif /* USE_NETGROUP */
  306.  
  307. #if USE_YP_ALL
  308. static int
  309. __nis_store_map(int instatus, char *inkey, int inkeylen,
  310.                 char *inval, int invallen, char *indata)
  311. {
  312.   char *tmp;
  313.   if (YP_TRUE != instatus)
  314.     {
  315.       return 1;
  316.     }
  317.  
  318.       /* first call, setup cache */
  319.   if (0 == nis_cache.size)
  320.     {
  321.       nis_cache.data = malloc(NIS_CACHE_INITIAL_SIZE);
  322.       if (NULL == nis_cache.data)
  323.         return 1;
  324.       nis_cache.size = NIS_CACHE_INITIAL_SIZE;
  325.       nis_cache.current = 0;
  326.     }
  327.   
  328.   if (nis_cache.current + invallen + 2 >= nis_cache.size)
  329.     {
  330.       tmp = realloc(nis_cache.data, nis_cache.size + NIS_CACHE_INCREMENT);
  331.       if (NULL == tmp)
  332.         {
  333.           free(nis_cache.data);
  334.           nis_cache.size = 0;
  335.           return 1;
  336.         }
  337.       nis_cache.size += NIS_CACHE_INCREMENT;
  338.       nis_cache.data = tmp;
  339.     }
  340.  
  341.   strncpy(nis_cache.data + nis_cache.current, inval, invallen);
  342.   tmp = nis_cache.data + nis_cache.current + invallen;
  343.   *tmp++ = '\n';
  344.   *tmp++ = '\0';
  345.   nis_cache.current += invallen + 2 ;
  346.  
  347.   return 0;
  348. }
  349.  
  350. static struct passwd *
  351. __nis_get_first_cached_entry(void *info)
  352. {
  353.   struct passwd *pwd;
  354.   pwd = __nis_parsepwddata(nis_cache.data, info);
  355.   nis_cache.current = strlen(nis_cache.data) + 1;
  356.   return pwd;
  357. }
  358.  
  359. static struct passwd *
  360. __nis_get_next_cached_entry(void *info)
  361. {
  362.   struct passwd *pwd;
  363.   pwd = __nis_parsepwddata(nis_cache.data + nis_cache.current, info);
  364.   nis_cache.current += strlen(nis_cache.data + nis_cache.current) + 1;
  365.   return pwd;
  366. }
  367. #endif /* USE_YP_ALL */
  368. #endif /* YP */
  369.