source: rtems/cpukit/libcsupport/src/getpwent.c @ ed8c513

4.104.114.84.95
Last change on this file since ed8c513 was ed8c513, checked in by Joel Sherrill <joel.sherrill@…>, on 10/02/02 at 17:33:17

2002-10-02 Eric Norum <eric.norum@…>

  • src/getpwent.c: Per PR283, reimplement to address reentrancy problems.
  • src/getgrent.c: Removed as functionality is now just a wrapper for common routines in src/getpwent.c.
  • Makefile.am: Reflect file removal.
  • Property mode set to 100644
File size: 8.7 KB
Line 
1/*
2 *  POSIX 1003.1b - 9.2.2 - User Database Access Routines
3 *
4 *  The license and distribution terms for this file may be
5 *  found in the file LICENSE in this distribution or at
6 *  http://www.OARcorp.com/rtems/license.html.
7 *
8 *  $Id$
9 */
10
11#if HAVE_CONFIG_H
12#include "config.h"
13#endif
14
15#include <stdio.h>
16#include <sys/types.h>
17#include <pwd.h>
18#include <grp.h>
19#include <errno.h>
20#include <unistd.h>
21#include <stdlib.h>
22#include <string.h>
23#include <limits.h>
24#include <ctype.h>
25
26#include <rtems/libio_.h>
27
28/*
29 * Static, thread-unsafe, buffers
30 */
31static FILE *passwd_fp;
32static char pwbuf[200];
33static struct passwd pwent;
34static FILE *group_fp;
35static char grbuf[200];
36static struct group grent;
37
38/*
39 * Initialize useable but dummy databases
40 */
41void init_etc_passwd_group(void)
42{
43  FILE *fp;
44  static char etc_passwd_initted = 0;
45
46  if (etc_passwd_initted)
47    return;
48  etc_passwd_initted = 1;
49  mkdir("/etc", 0777);
50
51  /*
52   *  Initialize /etc/passwd
53   */
54  if ((fp = fopen("/etc/passwd", "r")) != NULL) {
55    fclose(fp);
56  }
57  else if ((fp = fopen("/etc/passwd", "w")) != NULL) {
58    fprintf(fp, "root:*:0:0:root::/:/bin/sh\n"
59                 "rtems:*:1:1:RTEMS Application::/:/bin/sh\n"
60                 "tty:!:2:2:tty owner::/:/bin/false\n" );
61    fclose(fp);
62  }
63
64  /*
65   *  Initialize /etc/group
66   */
67  if ((fp = fopen("/etc/group", "r")) != NULL) {
68    fclose(fp);
69  }
70  else if ((fp = fopen("/etc/group", "w")) != NULL) {
71    fprintf( fp, "root:x:0:root\n"
72                 "rtems:x:1:rtems\n"
73                 "tty:x:2:tty\n" );
74    fclose(fp);
75  }
76}
77
78/*
79 * Extract a string value from the database
80 */
81static int
82scanString(FILE *fp, char **name, char **bufp, size_t *nleft, int nlFlag)
83{
84  int c;
85
86  *name = *bufp;
87  for (;;) {
88    c = getc(fp);
89    if (c == ':') {
90        if (nlFlag)
91            return 0;
92        break;
93    }
94    if (c == '\n') {
95        if (!nlFlag)
96            return 0;
97        break;
98    }
99    if (c == EOF)
100      return 0;
101    if (*nleft < 2)
102      return 0;
103    **bufp = c;
104    ++(*bufp);
105    --(*nleft);
106  }
107  **bufp = '\0';
108  ++(*bufp);
109  --(*nleft);
110  return 1;
111}
112
113/*
114 * Extract an integer value from the database
115 */
116static int
117scanInt(FILE *fp, int *val)
118{
119  int c;
120  unsigned int i = 0;
121  unsigned int limit = INT_MAX;
122  int sign = 0;
123  int d;
124
125  for (;;) {
126    c = getc(fp);
127    if (c == ':')
128      break;
129    if (sign == 0) {
130      if (c == '-') {
131        sign = -1;
132        limit++;
133        continue;
134      }
135      sign = 1;
136    }
137    if (!isdigit(c))
138      return 0;
139    d = c - '0';
140    if ((i > (limit / 10))
141     || ((i == (limit / 10)) && (d > (limit % 10))))
142      return 0;
143    i = i * 10 + d;
144  }
145  if (sign == 0)
146    return 0;
147  *val = i * sign;
148  return 1;
149}
150
151/*
152 * Extract a single password record from the database
153 */
154static int scanpw(
155  FILE *fp,
156  struct passwd *pwd,
157  char *buffer,
158  size_t bufsize
159)
160{
161  int pwuid, pwgid;
162
163  if (!scanString(fp, &pwd->pw_name, &buffer, &bufsize, 0)
164   || !scanString(fp, &pwd->pw_passwd, &buffer, &bufsize, 0)
165   || !scanInt(fp, &pwuid)
166   || !scanInt(fp, &pwgid)
167   || !scanString(fp, &pwd->pw_comment, &buffer, &bufsize, 0)
168   || !scanString(fp, &pwd->pw_gecos, &buffer, &bufsize, 0)
169   || !scanString(fp, &pwd->pw_dir, &buffer, &bufsize, 0)
170   || !scanString(fp, &pwd->pw_shell, &buffer, &bufsize, 1))
171    return 0;
172  pwd->pw_uid = pwuid;
173  pwd->pw_gid = pwgid;
174  return 1;
175}
176
177static int getpw_r(
178  const char     *name,
179  int             uid,
180  struct passwd  *pwd,
181  char           *buffer,
182  size_t          bufsize,
183  struct passwd **result
184)
185{
186  FILE *fp;
187  int match;
188  rtems_user_env_t * aux=rtems_current_user_env; /* save */
189
190  init_etc_passwd_group();
191  rtems_current_user_env=&rtems_global_user_env; /* set root */
192
193  if ((fp = fopen("/etc/passwd", "r")) == NULL) {
194    errno = EINVAL;
195    rtems_current_user_env=aux; /* restore */
196    return -1;
197  }
198  for(;;) {
199    if (!scanpw(fp, pwd, buffer, bufsize)) {
200      errno = EINVAL;
201      fclose(fp);
202      rtems_current_user_env=aux; /* restore */
203      return -1;
204    }
205    if (name) {
206      match = (strcmp(pwd->pw_name, name) == 0);
207    }
208    else {
209      match = (pwd->pw_uid == uid);
210    }
211    if (match) {
212      fclose(fp);
213      *result = pwd;
214      rtems_current_user_env=aux; /* restore */
215      return 0;
216    }
217  }
218  fclose(fp);
219  errno = EINVAL;
220  rtems_current_user_env=aux; /* restore */
221  return -1;
222}
223
224int getpwnam_r(
225  const char     *name,
226  struct passwd  *pwd,
227  char           *buffer,
228  size_t          bufsize,
229  struct passwd **result
230)
231{
232  return getpw_r(name, 0, pwd, buffer, bufsize, result);
233}
234
235struct passwd *getpwnam(
236  const char *name
237)
238{
239  struct passwd *p;
240
241  if(getpwnam_r(name, &pwent, pwbuf, sizeof pwbuf, &p))
242    return NULL;
243  return p;
244}
245
246int getpwuid_r(
247  uid_t           uid,
248  struct passwd  *pwd,
249  char           *buffer,
250  size_t          bufsize,
251  struct passwd **result
252)
253{
254  return getpw_r(NULL, uid, pwd, buffer, bufsize, result);
255}
256
257struct passwd *getpwuid(
258  uid_t uid
259)
260{
261  struct passwd *p;
262
263  if(getpwuid_r(uid, &pwent, pwbuf, sizeof pwbuf, &p))
264    return NULL;
265  return p;
266}
267
268struct passwd *getpwent()
269{
270  if (passwd_fp == NULL)
271    return NULL;
272  if (!scanpw(passwd_fp, &pwent, pwbuf, sizeof pwbuf))
273    return NULL;
274  return &pwent;
275}
276
277void setpwent(void)
278{
279  rtems_user_env_t * aux=rtems_current_user_env; /* save */
280  init_etc_passwd_group();
281  rtems_current_user_env=&rtems_global_user_env; /* set root */
282
283  if (passwd_fp != NULL)
284    fclose(passwd_fp);
285  passwd_fp = fopen("/etc/passwd", "r");
286  rtems_current_user_env=aux; /* restore */
287}
288
289void endpwent(void)
290{
291  if (passwd_fp != NULL)
292    fclose(passwd_fp);
293}
294
295/*
296 * Extract a single group record from the database
297 */
298static int scangr(
299  FILE *fp,
300  struct group *grp,
301  char *buffer,
302  size_t bufsize
303)
304{
305  int grgid;
306  char *grmem, *cp;
307  int memcount;
308
309  if (!scanString(fp, &grp->gr_name, &buffer, &bufsize, 0)
310   || !scanString(fp, &grp->gr_passwd, &buffer, &bufsize, 0)
311   || !scanInt(fp, &grgid)
312   || !scanString(fp, &grmem, &buffer, &bufsize, 1))
313    return 0;
314  grp->gr_gid = grgid;
315
316  /*
317   * Determine number of members
318   */
319  for (cp = grmem, memcount = 1 ; *cp != 0 ; cp++) {
320    if(*cp == ',')
321      memcount++;
322  }
323
324  /*
325   * Hack to produce (hopefully) a suitably-aligned array of pointers
326   */
327  if (bufsize < (((memcount+1)*sizeof(char *)) + 15))
328    return 0;
329  grp->gr_mem = (char **)(((unsigned long)buffer + 15) & ~15);
330
331  /*
332   * Fill in pointer array
333   */
334  grp->gr_mem[0] = grmem;
335  for (cp = grmem, memcount = 1 ; *cp != 0 ; cp++) {
336    if(*cp == ',') {
337      *cp = '\0';
338      grp->gr_mem[memcount++] = cp + 1;
339    }
340  }
341  grp->gr_mem[memcount] = NULL;
342  return 1;
343}
344
345static int getgr_r(
346  const char     *name,
347  int             gid,
348  struct group   *grp,
349  char           *buffer,
350  size_t          bufsize,
351  struct group  **result
352)
353{
354  FILE *fp;
355  int match;
356  rtems_user_env_t * aux=rtems_current_user_env; /* save */
357
358  init_etc_passwd_group();
359  rtems_current_user_env=&rtems_global_user_env; /* set root */
360
361  if ((fp = fopen("/etc/group", "r")) == NULL) {
362    errno = EINVAL;
363    rtems_current_user_env=aux; /* restore */
364    return -1;
365  }
366  for(;;) {
367    if (!scangr(fp, grp, buffer, bufsize)) {
368      errno = EINVAL;
369      fclose(fp);
370      rtems_current_user_env=aux; /* restore */
371      return -1;
372    }
373    if (name) {
374      match = (strcmp(grp->gr_name, name) == 0);
375    }
376    else {
377      match = (grp->gr_gid == gid);
378    }
379    if (match) {
380      fclose(fp);
381      *result = grp;
382      rtems_current_user_env=aux; /* restore */
383      return 0;
384    }
385  }
386  fclose(fp);
387  errno = EINVAL;
388  rtems_current_user_env=aux; /* restore */
389  return -1;
390}
391
392int getgrnam_r(
393  const char     *name,
394  struct group   *grp,
395  char           *buffer,
396  size_t          bufsize,
397  struct group  **result
398)
399{
400  return getgr_r(name, 0, grp, buffer, bufsize, result);
401}
402
403struct group *getgrnam(
404  const char *name
405)
406{
407  struct group *p;
408
409  if(getgrnam_r(name, &grent, grbuf, sizeof grbuf, &p))
410    return NULL;
411  return p;
412}
413
414int getgrgid_r(
415  gid_t           gid,
416  struct group   *grp,
417  char           *buffer,
418  size_t          bufsize,
419  struct group  **result
420)
421{
422  return getgr_r(NULL, gid, grp, buffer, bufsize, result);
423}
424
425struct group *getgrgid(
426  gid_t gid
427)
428{
429  struct group *p;
430
431  if(getgrgid_r(gid, &grent, grbuf, sizeof grbuf, &p))
432    return NULL;
433  return p;
434}
435
436struct group *getgrent()
437{
438  if (group_fp == NULL)
439    return NULL;
440  if (!scangr(group_fp, &grent, grbuf, sizeof grbuf))
441    return NULL;
442  return &grent;
443}
444
445void setgrent(void)
446{
447  rtems_user_env_t * aux=rtems_current_user_env; /* save */
448  init_etc_passwd_group();
449  rtems_current_user_env=&rtems_global_user_env; /* set root */
450
451  if (group_fp != NULL)
452    fclose(group_fp);
453  group_fp = fopen("/etc/group", "r");
454  rtems_current_user_env=aux; /* restore */
455}
456
457void endgrent(void)
458{
459  if (group_fp != NULL)
460    fclose(group_fp);
461}
Note: See TracBrowser for help on using the repository browser.