source: rtems/cpukit/libcsupport/src/pwdgrp.c @ 80055514

4.115
Last change on this file since 80055514 was 80055514, checked in by Sebastian Huber <sebastian.huber@…>, on 11/14/14 at 10:09:39

libcsupport: Use pthread_once()

  • Property mode set to 100644
File size: 6.8 KB
Line 
1/**
2 *  @file
3 *
4 *  @brief User Database Access Routines
5 *  @ingroup libcsupport
6 */
7
8/*
9 *  Copyright (c) 1999-2009 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
10 *  Copyright (c) 1999-2013 Joel Sherrill <joel.sherrill@OARcorp.com>
11 *  Copyright (c) 2000-2001 Fernando Ruiz Casas <fernando.ruiz@ctv.es>
12 *  Copyright (c) 2002 Eric Norum <eric.norum@usask.ca>
13 *  Copyright (c) 2003 Till Straumann <strauman@slac.stanford.edu>
14 *  Copyright (c) 2012 Alex Ivanov <alexivanov97@gmail.com>
15 *
16 *  The license and distribution terms for this file may be
17 *  found in the file LICENSE in this distribution or at
18 *  http://www.rtems.org/license/LICENSE.
19 */
20
21#if HAVE_CONFIG_H
22#include "config.h"
23#endif
24
25#include <sys/stat.h>
26#include <pwd.h>
27#include <grp.h>
28#include <errno.h>
29#include <unistd.h>
30#include <stdlib.h>
31#include <string.h>
32#include <limits.h>
33#include <ctype.h>
34#include <pthread.h>
35
36#include <rtems/seterr.h>
37
38#include "pwdgrp.h"
39
40static pthread_once_t pwdgrp_once = PTHREAD_ONCE_INIT;
41
42/**
43 *  Initialize useable but dummy databases
44 */
45static void pwdgrp_init(void)
46{
47  FILE *fp;
48
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
78void _libcsupport_pwdgrp_init(void)
79{
80  pthread_once(&pwdgrp_once, pwdgrp_init);
81}
82
83/**
84 *  Extract a string value from the database
85 */
86static int
87scanString(FILE *fp, char **name, char **bufp, size_t *nleft, int nlFlag)
88{
89  int c;
90
91  *name = *bufp;
92  for (;;) {
93    c = getc(fp);
94    if (c == ':') {
95        if (nlFlag)
96            return 0;
97        break;
98    }
99    if (c == '\n') {
100        if (!nlFlag)
101            return 0;
102        break;
103    }
104    if (c == EOF)
105      return 0;
106    if (*nleft < 2)
107      return 0;
108    **bufp = c;
109    ++(*bufp);
110    --(*nleft);
111  }
112  **bufp = '\0';
113  ++(*bufp);
114  --(*nleft);
115  return 1;
116}
117
118/**
119 *  Extract an integer value from the database
120 */
121static int
122scanInt(FILE *fp, int *val)
123{
124  int c;
125  unsigned int i = 0;
126  unsigned int limit = INT_MAX;
127  int sign = 0;
128  int d;
129
130  for (;;) {
131    c = getc(fp);
132    if (c == ':')
133      break;
134    if (sign == 0) {
135      if (c == '-') {
136        sign = -1;
137        limit++;
138        continue;
139      }
140      sign = 1;
141    }
142    if (!isdigit(c))
143      return 0;
144    d = c - '0';
145    if ((i > (limit / 10))
146     || ((i == (limit / 10)) && (d > (limit % 10))))
147      return 0;
148    i = i * 10 + d;
149  }
150  if (sign == 0)
151    return 0;
152  *val = i * sign;
153  return 1;
154}
155
156/*
157 * Extract a single password record from the database
158 */
159int _libcsupport_scanpw(
160  FILE *fp,
161  struct passwd *pwd,
162  char *buffer,
163  size_t bufsize
164)
165{
166  int pwuid, pwgid;
167
168  if (!scanString(fp, &pwd->pw_name, &buffer, &bufsize, 0)
169   || !scanString(fp, &pwd->pw_passwd, &buffer, &bufsize, 0)
170   || !scanInt(fp, &pwuid)
171   || !scanInt(fp, &pwgid)
172   || !scanString(fp, &pwd->pw_comment, &buffer, &bufsize, 0)
173   || !scanString(fp, &pwd->pw_gecos, &buffer, &bufsize, 0)
174   || !scanString(fp, &pwd->pw_dir, &buffer, &bufsize, 0)
175   || !scanString(fp, &pwd->pw_shell, &buffer, &bufsize, 1))
176    return 0;
177  pwd->pw_uid = pwuid;
178  pwd->pw_gid = pwgid;
179  return 1;
180}
181
182static int getpw_r(
183  const char     *name,
184  int             uid,
185  struct passwd  *pwd,
186  char           *buffer,
187  size_t          bufsize,
188  struct passwd **result
189)
190{
191  FILE *fp;
192  int match;
193
194  _libcsupport_pwdgrp_init();
195
196  if ((fp = fopen("/etc/passwd", "r")) == NULL)
197    rtems_set_errno_and_return_minus_one( EINVAL );
198
199  for(;;) {
200    if (!_libcsupport_scanpw(fp, pwd, buffer, bufsize))
201      goto error_einval;
202
203    if (name) {
204      match = (strcmp(pwd->pw_name, name) == 0);
205    } else {
206      match = (pwd->pw_uid == uid);
207    }
208
209    if (match) {
210      fclose(fp);
211      *result = pwd;
212      return 0;
213    }
214  }
215error_einval:
216  fclose(fp);
217  rtems_set_errno_and_return_minus_one( EINVAL );
218}
219
220int getpwnam_r(
221  const char     *name,
222  struct passwd  *pwd,
223  char           *buffer,
224  size_t          bufsize,
225  struct passwd **result
226)
227{
228  return getpw_r(name, 0, pwd, buffer, bufsize, result);
229}
230
231int getpwuid_r(
232  uid_t           uid,
233  struct passwd  *pwd,
234  char           *buffer,
235  size_t          bufsize,
236  struct passwd **result
237)
238{
239  return getpw_r(NULL, uid, pwd, buffer, bufsize, result);
240}
241
242/**
243 *  Extract a single group record from the database
244 */
245int _libcsupport_scangr(
246  FILE *fp,
247  struct group *grp,
248  char *buffer,
249  size_t bufsize
250)
251{
252  int grgid;
253  char *grmem, *cp;
254  int memcount;
255
256  if (!scanString(fp, &grp->gr_name, &buffer, &bufsize, 0)
257   || !scanString(fp, &grp->gr_passwd, &buffer, &bufsize, 0)
258   || !scanInt(fp, &grgid)
259   || !scanString(fp, &grmem, &buffer, &bufsize, 1))
260    return 0;
261  grp->gr_gid = grgid;
262
263  /*
264   * Determine number of members
265   */
266  for (cp = grmem, memcount = 1 ; *cp != 0 ; cp++) {
267    if(*cp == ',')
268      memcount++;
269  }
270
271  /*
272   * Hack to produce (hopefully) a suitably-aligned array of pointers
273   */
274  if (bufsize < (((memcount+1)*sizeof(char *)) + 15))
275    return 0;
276  grp->gr_mem = (char **)(((uintptr_t)buffer + 15) & ~15);
277
278  /*
279   * Fill in pointer array
280   */
281  grp->gr_mem[0] = grmem;
282  for (cp = grmem, memcount = 1 ; *cp != 0 ; cp++) {
283    if(*cp == ',') {
284      *cp = '\0';
285      grp->gr_mem[memcount++] = cp + 1;
286    }
287  }
288  grp->gr_mem[memcount] = NULL;
289  return 1;
290}
291
292static int getgr_r(
293  const char     *name,
294  int             gid,
295  struct group   *grp,
296  char           *buffer,
297  size_t          bufsize,
298  struct group  **result
299)
300{
301  FILE *fp;
302  int match;
303
304  _libcsupport_pwdgrp_init();
305
306  if ((fp = fopen("/etc/group", "r")) == NULL)
307    rtems_set_errno_and_return_minus_one( EINVAL );
308
309  for(;;) {
310    if (!_libcsupport_scangr(fp, grp, buffer, bufsize))
311      goto error_einval;
312
313    if (name) {
314      match = (strcmp(grp->gr_name, name) == 0);
315    } else {
316      match = (grp->gr_gid == gid);
317    }
318
319    if (match) {
320      fclose(fp);
321      *result = grp;
322      return 0;
323    }
324  }
325error_einval:
326  fclose(fp);
327  rtems_set_errno_and_return_minus_one( EINVAL );
328}
329
330int getgrnam_r(
331  const char     *name,
332  struct group   *grp,
333  char           *buffer,
334  size_t          bufsize,
335  struct group  **result
336)
337{
338  return getgr_r(name, 0, grp, buffer, bufsize, result);
339}
340
341int getgrgid_r(
342  gid_t           gid,
343  struct group   *grp,
344  char           *buffer,
345  size_t          bufsize,
346  struct group  **result
347)
348{
349  return getgr_r(NULL, gid, grp, buffer, bufsize, result);
350}
Note: See TracBrowser for help on using the repository browser.