source: trunk/third/findutils/lib/idcache.c @ 18890

Revision 18890, 5.5 KB checked in by zacheiss, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18889, which included commits to RCS files with non-trunk default branches.
Line 
1/* idcache.c -- map user and group IDs, cached for speed
2   Copyright (C) 1985, 1988, 1989, 1990, 1997, 1998 Free Software
3   Foundation, Inc.
4
5   This program is free software; you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published by
7   the Free Software Foundation; either version 2, or (at your option)
8   any later version.
9
10   This program 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
13   GNU General Public License for more details.
14
15   You should have received a copy of the GNU General Public License
16   along with this program; if not, write to the Free Software Foundation,
17   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
18
19#if HAVE_CONFIG_H
20# include <config.h>
21#endif
22
23#include <stdio.h>
24#include <sys/types.h>
25#include <pwd.h>
26#include <grp.h>
27
28#if STDC_HEADERS || HAVE_STRING_H
29# include <string.h>
30#else
31# include <strings.h>
32#endif
33
34#if HAVE_UNISTD_H
35# include <unistd.h>
36#endif
37
38#ifndef _POSIX_VERSION
39struct passwd *getpwuid ();
40struct passwd *getpwnam ();
41struct group *getgrgid ();
42struct group *getgrnam ();
43#endif
44
45char *xmalloc ();
46char *xstrdup ();
47
48#ifdef __DJGPP__
49static char digits[] = "0123456789";
50#endif
51
52struct userid
53{
54  union
55    {
56      uid_t u;
57      gid_t g;
58    } id;
59  char *name;
60  struct userid *next;
61};
62
63static struct userid *user_alist;
64
65/* The members of this list have names not in the local passwd file.  */
66static struct userid *nouser_alist;
67
68/* Translate UID to a login name, with cache, or NULL if unresolved.  */
69
70char *
71getuser (uid_t uid)
72{
73  register struct userid *tail;
74  struct passwd *pwent;
75
76  for (tail = user_alist; tail; tail = tail->next)
77    if (tail->id.u == uid)
78      return tail->name;
79
80  pwent = getpwuid (uid);
81  tail = (struct userid *) xmalloc (sizeof (struct userid));
82  tail->id.u = uid;
83  tail->name = pwent ? xstrdup (pwent->pw_name) : NULL;
84
85  /* Add to the head of the list, so most recently used is first.  */
86  tail->next = user_alist;
87  user_alist = tail;
88  return tail->name;
89}
90
91/* Translate USER to a UID, with cache.
92   Return NULL if there is no such user.
93   (We also cache which user names have no passwd entry,
94   so we don't keep looking them up.)  */
95
96uid_t *
97getuidbyname (const char *user)
98{
99  register struct userid *tail;
100  struct passwd *pwent;
101
102  for (tail = user_alist; tail; tail = tail->next)
103    /* Avoid a function call for the most common case.  */
104    if (*tail->name == *user && !strcmp (tail->name, user))
105      return &tail->id.u;
106
107  for (tail = nouser_alist; tail; tail = tail->next)
108    /* Avoid a function call for the most common case.  */
109    if (*tail->name == *user && !strcmp (tail->name, user))
110      return 0;
111
112  pwent = getpwnam (user);
113#ifdef __DJGPP__
114  /* We need to pretend to be the user USER, to make
115     pwd functions know about an arbitrary user name.  */
116  if (!pwent && strspn (user, digits) < strlen (user))
117    {
118      setenv ("USER", user, 1);
119      pwent = getpwnam (user);  /* now it will succeed */
120    }
121#endif
122
123  tail = (struct userid *) xmalloc (sizeof (struct userid));
124  tail->name = xstrdup (user);
125
126  /* Add to the head of the list, so most recently used is first.  */
127  if (pwent)
128    {
129      tail->id.u = pwent->pw_uid;
130      tail->next = user_alist;
131      user_alist = tail;
132      return &tail->id.u;
133    }
134
135  tail->next = nouser_alist;
136  nouser_alist = tail;
137  return 0;
138}
139
140/* Use the same struct as for userids.  */
141static struct userid *group_alist;
142static struct userid *nogroup_alist;
143
144/* Translate GID to a group name, with cache, or NULL if unresolved.  */
145
146char *
147getgroup (gid_t gid)
148{
149  register struct userid *tail;
150  struct group *grent;
151
152  for (tail = group_alist; tail; tail = tail->next)
153    if (tail->id.g == gid)
154      return tail->name;
155
156  grent = getgrgid (gid);
157  tail = (struct userid *) xmalloc (sizeof (struct userid));
158  tail->id.g = gid;
159  tail->name = grent ? xstrdup (grent->gr_name) : NULL;
160
161  /* Add to the head of the list, so most recently used is first.  */
162  tail->next = group_alist;
163  group_alist = tail;
164  return tail->name;
165}
166
167/* Translate GROUP to a GID, with cache.
168   Return NULL if there is no such group.
169   (We also cache which group names have no group entry,
170   so we don't keep looking them up.)  */
171
172gid_t *
173getgidbyname (const char *group)
174{
175  register struct userid *tail;
176  struct group *grent;
177
178  for (tail = group_alist; tail; tail = tail->next)
179    /* Avoid a function call for the most common case.  */
180    if (*tail->name == *group && !strcmp (tail->name, group))
181      return &tail->id.g;
182
183  for (tail = nogroup_alist; tail; tail = tail->next)
184    /* Avoid a function call for the most common case.  */
185    if (*tail->name == *group && !strcmp (tail->name, group))
186      return 0;
187
188  grent = getgrnam (group);
189#ifdef __DJGPP__
190  /* We need to pretend to belong to group GROUP, to make
191     grp functions know about any arbitrary group name.  */
192  if (!grent && strspn (group, digits) < strlen (group))
193    {
194      setenv ("GROUP", group, 1);
195      grent = getgrnam (group); /* now it will succeed */
196    }
197#endif
198
199  tail = (struct userid *) xmalloc (sizeof (struct userid));
200  tail->name = xstrdup (group);
201
202  /* Add to the head of the list, so most recently used is first.  */
203  if (grent)
204    {
205      tail->id.g = grent->gr_gid;
206      tail->next = group_alist;
207      group_alist = tail;
208      return &tail->id.g;
209    }
210
211  tail->next = nogroup_alist;
212  nogroup_alist = tail;
213  return 0;
214}
Note: See TracBrowser for help on using the repository browser.