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

4.115
Last change on this file since c499856 was c499856, checked in by Chris Johns <chrisj@…>, on 03/20/14 at 21:10:47

Change all references of rtems.com to rtems.org.

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