Initial commit for Tizen
[profile/extras/shadow-utils.git] / lib / sgetgrent.c
1 /*
2  * Copyright (c) 1990 - 1994, Julianne Frances Haugh
3  * Copyright (c) 1996 - 1998, Marek Michałkiewicz
4  * Copyright (c) 2005       , Tomasz Kłoczko
5  * Copyright (c) 2008       , Nicolas François
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. The name of the copyright holders or contributors may not be used to
17  *    endorse or promote products derived from this software without
18  *    specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23  * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
24  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 #include <config.h>
34
35 #ident "$Id: sgetgrent.c 2579 2009-03-21 20:29:58Z nekral-guest $"
36
37 #include <stdio.h>
38 #include <sys/types.h>
39 #include <grp.h>
40 #include "defines.h"
41 #include "prototypes.h"
42
43 #define NFIELDS 4
44
45 /*
46  * list - turn a comma-separated string into an array of (char *)'s
47  *
48  *      list() converts the comma-separated list of member names into
49  *      an array of character pointers.
50  *
51  *      WARNING: I profiled this once with and without strchr() calls
52  *      and found that using a register variable and an explicit loop
53  *      works best.  For large /etc/group files, this is a major win.
54  *
55  * FINALLY added dynamic allocation.  Still need to fix sgetsgent().
56  *  --marekm
57  */
58 static char **list (char *s)
59 {
60         static char **members = 0;
61         static int size = 0;    /* max members + 1 */
62         int i;
63         char **rbuf;
64
65         i = 0;
66         for (;;) {
67                 /* check if there is room for another pointer (to a group
68                    member name, or terminating NULL).  */
69                 if (i >= size) {
70                         size = i + 100; /* at least: i + 1 */
71                         if (members) {
72                                 rbuf =
73                                     realloc (members, size * sizeof (char *));
74                         } else {
75                                 /* for old (before ANSI C) implementations of
76                                    realloc() that don't handle NULL properly */
77                                 rbuf = malloc (size * sizeof (char *));
78                         }
79                         if (!rbuf) {
80                                 if (members)
81                                         free (members);
82                                 members = 0;
83                                 size = 0;
84                                 return (char **) 0;
85                         }
86                         members = rbuf;
87                 }
88                 if (!s || s[0] == '\0')
89                         break;
90                 members[i++] = s;
91                 while (('\0' != *s) && (',' != *s)) {
92                         s++;
93                 }
94                 if ('\0' != *s) {
95                         *s++ = '\0';
96                 }
97         }
98         members[i] = (char *) 0;
99         return members;
100 }
101
102
103 struct group *sgetgrent (const char *buf)
104 {
105         static char *grpbuf = 0;
106         static size_t size = 0;
107         static char *grpfields[NFIELDS];
108         static struct group grent;
109         int i;
110         char *cp;
111
112         if (strlen (buf) + 1 > size) {
113                 /* no need to use realloc() here - just free it and
114                    allocate a larger block */
115                 if (grpbuf)
116                         free (grpbuf);
117                 size = strlen (buf) + 1000;     /* at least: strlen(buf) + 1 */
118                 grpbuf = malloc (size);
119                 if (!grpbuf) {
120                         size = 0;
121                         return 0;
122                 }
123         }
124         strcpy (grpbuf, buf);
125
126         cp = strrchr (grpbuf, '\n');
127         if (NULL != cp) {
128                 *cp = '\0';
129         }
130
131         for (cp = grpbuf, i = 0; (i < NFIELDS) && (NULL != cp); i++) {
132                 grpfields[i] = cp;
133                 cp = strchr (cp, ':');
134                 if (NULL != cp) {
135                         *cp = '\0';
136                         cp++;
137                 }
138         }
139         if (i < (NFIELDS - 1) || *grpfields[2] == '\0') {
140                 return (struct group *) 0;
141         }
142         grent.gr_name = grpfields[0];
143         grent.gr_passwd = grpfields[1];
144         if (get_gid (grpfields[2], &grent.gr_gid) == 0) {
145                 return (struct group *) 0;
146         }
147         grent.gr_mem = list (grpfields[3]);
148         if (NULL == grent.gr_mem) {
149                 return (struct group *) 0;      /* out of memory */
150         }
151
152         return &grent;
153 }
154