source: rtems/cpukit/libcsupport/src/getpwent.c @ 37008d0

4.104.11
Last change on this file since 37008d0 was 37008d0, checked in by Ralf Corsepius <ralf.corsepius@…>, on Sep 15, 2009 at 4:18:40 AM

2009-09-15 Ralf Corsépius <ralf.corsepius@…>

  • libcsupport/src/getpwent.c: Ansify.
  • Property mode set to 100644
File size: 7.8 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.rtems.com/license/LICENSE.
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
189  init_etc_passwd_group();
190
191  if ((fp = fopen("/etc/passwd", "r")) == NULL) {
192    errno = EINVAL;
193    return -1;
194  }
195  for(;;) {
196    if (!scanpw(fp, pwd, buffer, bufsize)) {
197      errno = EINVAL;
198      fclose(fp);
199      return -1;
200    }
201    if (name) {
202      match = (strcmp(pwd->pw_name, name) == 0);
203    }
204    else {
205      match = (pwd->pw_uid == uid);
206    }
207    if (match) {
208      fclose(fp);
209      *result = pwd;
210      return 0;
211    }
212  }
213  fclose(fp);
214  errno = EINVAL;
215  return -1;
216}
217
218int getpwnam_r(
219  const char     *name,
220  struct passwd  *pwd,
221  char           *buffer,
222  size_t          bufsize,
223  struct passwd **result
224)
225{
226  return getpw_r(name, 0, pwd, buffer, bufsize, result);
227}
228
229struct passwd *getpwnam(
230  const char *name
231)
232{
233  struct passwd *p;
234
235  if(getpwnam_r(name, &pwent, pwbuf, sizeof pwbuf, &p))
236    return NULL;
237  return p;
238}
239
240int getpwuid_r(
241  uid_t           uid,
242  struct passwd  *pwd,
243  char           *buffer,
244  size_t          bufsize,
245  struct passwd **result
246)
247{
248  return getpw_r(NULL, uid, pwd, buffer, bufsize, result);
249}
250
251struct passwd *getpwuid(
252  uid_t uid
253)
254{
255  struct passwd *p;
256
257  if(getpwuid_r(uid, &pwent, pwbuf, sizeof pwbuf, &p))
258    return NULL;
259  return p;
260}
261
262struct passwd *getpwent(void)
263{
264  if (passwd_fp == NULL)
265    return NULL;
266  if (!scanpw(passwd_fp, &pwent, pwbuf, sizeof pwbuf))
267    return NULL;
268  return &pwent;
269}
270
271void setpwent(void)
272{
273  init_etc_passwd_group();
274
275  if (passwd_fp != NULL)
276    fclose(passwd_fp);
277  passwd_fp = fopen("/etc/passwd", "r");
278}
279
280void endpwent(void)
281{
282  if (passwd_fp != NULL)
283    fclose(passwd_fp);
284}
285
286/*
287 * Extract a single group record from the database
288 */
289static int scangr(
290  FILE *fp,
291  struct group *grp,
292  char *buffer,
293  size_t bufsize
294)
295{
296  int grgid;
297  char *grmem, *cp;
298  int memcount;
299
300  if (!scanString(fp, &grp->gr_name, &buffer, &bufsize, 0)
301   || !scanString(fp, &grp->gr_passwd, &buffer, &bufsize, 0)
302   || !scanInt(fp, &grgid)
303   || !scanString(fp, &grmem, &buffer, &bufsize, 1))
304    return 0;
305  grp->gr_gid = grgid;
306
307  /*
308   * Determine number of members
309   */
310  for (cp = grmem, memcount = 1 ; *cp != 0 ; cp++) {
311    if(*cp == ',')
312      memcount++;
313  }
314
315  /*
316   * Hack to produce (hopefully) a suitably-aligned array of pointers
317   */
318  if (bufsize < (((memcount+1)*sizeof(char *)) + 15))
319    return 0;
320  grp->gr_mem = (char **)(((uintptr_t)buffer + 15) & ~15);
321
322  /*
323   * Fill in pointer array
324   */
325  grp->gr_mem[0] = grmem;
326  for (cp = grmem, memcount = 1 ; *cp != 0 ; cp++) {
327    if(*cp == ',') {
328      *cp = '\0';
329      grp->gr_mem[memcount++] = cp + 1;
330    }
331  }
332  grp->gr_mem[memcount] = NULL;
333  return 1;
334}
335
336static int getgr_r(
337  const char     *name,
338  int             gid,
339  struct group   *grp,
340  char           *buffer,
341  size_t          bufsize,
342  struct group  **result
343)
344{
345  FILE *fp;
346  int match;
347
348  init_etc_passwd_group();
349
350  if ((fp = fopen("/etc/group", "r")) == NULL) {
351    errno = EINVAL;
352    return -1;
353  }
354  for(;;) {
355    if (!scangr(fp, grp, buffer, bufsize)) {
356      errno = EINVAL;
357      fclose(fp);
358      return -1;
359    }
360    if (name) {
361      match = (strcmp(grp->gr_name, name) == 0);
362    }
363    else {
364      match = (grp->gr_gid == gid);
365    }
366    if (match) {
367      fclose(fp);
368      *result = grp;
369      return 0;
370    }
371  }
372  fclose(fp);
373  errno = EINVAL;
374  return -1;
375}
376
377int getgrnam_r(
378  const char     *name,
379  struct group   *grp,
380  char           *buffer,
381  size_t          bufsize,
382  struct group  **result
383)
384{
385  return getgr_r(name, 0, grp, buffer, bufsize, result);
386}
387
388struct group *getgrnam(
389  const char *name
390)
391{
392  struct group *p;
393
394  if(getgrnam_r(name, &grent, grbuf, sizeof grbuf, &p))
395    return NULL;
396  return p;
397}
398
399int getgrgid_r(
400  gid_t           gid,
401  struct group   *grp,
402  char           *buffer,
403  size_t          bufsize,
404  struct group  **result
405)
406{
407  return getgr_r(NULL, gid, grp, buffer, bufsize, result);
408}
409
410struct group *getgrgid(
411  gid_t gid
412)
413{
414  struct group *p;
415
416  if(getgrgid_r(gid, &grent, grbuf, sizeof grbuf, &p))
417    return NULL;
418  return p;
419}
420
421struct group *getgrent(void)
422{
423  if (group_fp == NULL)
424    return NULL;
425  if (!scangr(group_fp, &grent, grbuf, sizeof grbuf))
426    return NULL;
427  return &grent;
428}
429
430void setgrent(void)
431{
432  init_etc_passwd_group();
433
434  if (group_fp != NULL)
435    fclose(group_fp);
436  group_fp = fopen("/etc/group", "r");
437}
438
439void endgrent(void)
440{
441  if (group_fp != NULL)
442    fclose(group_fp);
443}
Note: See TracBrowser for help on using the repository browser.