Formerly ../grp/grpread.c.~4~
[kopensolaris-gnu/glibc.git] / grp / grpread.c
1 /* Copyright (C) 1991 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
8
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public
15 License along with the GNU C Library; see the file COPYING.LIB.  If
16 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
17 Cambridge, MA 02139, USA.  */
18
19 #include <ansidecl.h>
20 #include <errno.h>
21 #include <stddef.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/types.h>
26 #include <grp.h>
27
28 /* This is the function that all the others are based on.
29    The format of the group file is known only here.  */
30
31 /* Structure containing info kept by each __grpread caller.  */
32 typedef struct
33   {
34 #define NAME_SIZE       8
35 #define PASSWD_SIZE     20
36 #define MEMLIST_SIZE    1000
37     char buf[NAME_SIZE + 1 + PASSWD_SIZE + 1 + 20 + 1 + 20 + MEMLIST_SIZE + 1];
38     size_t max_members;
39     char **members;
40     struct group g;
41   } grpread_info;
42
43
44 /* Return a chunk of memory containing a pre-initialized `grpread_info'.  */
45 PTR
46 DEFUN_VOID(__grpalloc)
47 {
48   grpread_info *info = (PTR) malloc(sizeof(grpread_info));
49   if (info == NULL)
50     return NULL;
51
52   info->max_members = 5;
53   info->members = (char **) malloc(5 * sizeof(char *));
54   if (info->members == NULL)
55     {
56       free((PTR) info);
57       return NULL;
58     }
59
60   return info;
61 }
62
63 /* Read a group entry from STREAM, filling in G.  */
64 struct group *
65 DEFUN(__grpread, (stream, g), FILE *stream AND PTR CONST g)
66 {
67   register grpread_info *CONST info = (grpread_info *) g;
68   char *start, *end;
69   register size_t i;
70
71   /* Idiocy checks.  */
72   if (stream == NULL)
73     {
74       errno = EINVAL;
75       return NULL;
76     }
77
78   if (fgets (info->buf, sizeof(info->buf), stream) == NULL)
79     return NULL;
80
81   start = info->buf;
82   end = strchr (start, ':');
83   if (end == NULL)
84     return NULL;
85   *end = '\0';
86   info->g.gr_name = start;
87
88   start = end + 1;
89   end = strchr (start, ':');
90   if (end == NULL)
91     return NULL;
92   *end = '\0';
93   info->g.gr_passwd = start;
94
95   info->g.gr_gid = (gid_t) strtol (end + 1, &end, 10);
96   if (*end != ':')
97     return NULL;
98
99   i = 0;
100   do
101     {
102       start = end + 1;
103       end = strchr (start, ',');
104       if (end == NULL)
105         {
106           end = strchr (start, '\n');
107           if (end == start)
108             break;
109           if (end == NULL)
110             return NULL;
111           *end = '\0';
112           end = NULL;
113         }
114       else
115         *end = '\0';
116
117       if (i == info->max_members - 2)
118         {
119           info->max_members += 5;
120           info->members = (char **)
121             realloc ((PTR) info->members, info->max_members * sizeof (char *));
122           if (info->members == NULL)
123             return NULL;
124         }
125
126       info->members[i++] = start;
127     } while (end != NULL);
128   info->members[i] = NULL;
129   info->g.gr_mem = info->members;
130
131   return &info->g;
132 }