Imported Upstream version 1.8.7
[debian/sudo] / plugins / group_file / getgrent.c
1 /*
2  * Copyright (c) 2005,2008,2010-2013 Todd C. Miller <Todd.Miller@courtesan.com>
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16
17 /*
18  * Trivial replacements for the libc getgr{uid,nam}() routines.
19  */
20
21 #include <config.h>
22
23 #include <sys/types.h>
24 #include <stdio.h>
25 #ifdef STDC_HEADERS
26 # include <stdlib.h>
27 # include <stddef.h>
28 #else
29 # ifdef HAVE_STDLIB_H
30 #  include <stdlib.h>
31 # endif
32 #endif /* STDC_HEADERS */
33 #ifdef HAVE_STRING_H
34 # if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS)
35 #  include <memory.h>
36 # endif
37 # include <string.h>
38 #endif /* HAVE_STRING_H */
39 #ifdef HAVE_STRINGS_H
40 # include <strings.h>
41 #endif /* HAVE_STRINGS_H */
42 #include <fcntl.h>
43 #include <limits.h>
44 #include <pwd.h>
45 #include <grp.h>
46
47 #include "missing.h"
48
49 #ifndef LINE_MAX
50 # define LINE_MAX 2048
51 #endif
52
53 #undef GRMEM_MAX
54 #define GRMEM_MAX 200
55
56 static FILE *grf;
57 static const char *grfile = "/etc/group";
58 static int gr_stayopen;
59
60 void mysetgrfile(const char *);
61 void mysetgrent(void);
62 void myendgrent(void);
63 struct group *mygetgrent(void);
64 struct group *mygetgrnam(const char *);
65 struct group *mygetgrgid(gid_t);
66
67 void
68 mysetgrfile(const char *file)
69 {
70     grfile = file;
71     if (grf != NULL)
72         myendgrent();
73 }
74
75 void
76 mysetgrent(void)
77 {
78     if (grf == NULL) {
79         grf = fopen(grfile, "r");
80         if (grf != NULL)
81             fcntl(fileno(grf), F_SETFD, FD_CLOEXEC);
82     } else {
83         rewind(grf);
84     }
85     gr_stayopen = 1;
86 }
87
88 void
89 myendgrent(void)
90 {
91     if (grf != NULL) {
92         fclose(grf);
93         grf = NULL;
94     }
95     gr_stayopen = 0;
96 }
97
98 struct group *
99 mygetgrent(void)
100 {
101     static struct group gr;
102     static char grbuf[LINE_MAX], *gr_mem[GRMEM_MAX+1];
103     size_t len;
104     char *cp, *colon;
105     int n;
106
107     if ((colon = fgets(grbuf, sizeof(grbuf), grf)) == NULL)
108         return NULL;
109
110     memset(&gr, 0, sizeof(gr));
111     if ((colon = strchr(cp = colon, ':')) == NULL)
112         return NULL;
113     *colon++ = '\0';
114     gr.gr_name = cp;
115     if ((colon = strchr(cp = colon, ':')) == NULL)
116         return NULL;
117     *colon++ = '\0';
118     gr.gr_passwd = cp;
119     if ((colon = strchr(cp = colon, ':')) == NULL)
120         return NULL;
121     *colon++ = '\0';
122     gr.gr_gid = atoi(cp);
123     len = strlen(colon);
124     if (len > 0 && colon[len - 1] == '\n')
125         colon[len - 1] = '\0';
126     if (*colon != '\0') {
127         gr.gr_mem = gr_mem;
128         cp = strtok(colon, ",");
129         for (n = 0; cp != NULL && n < GRMEM_MAX; n++) {
130             gr.gr_mem[n] = cp;
131             cp = strtok(NULL, ",");
132         }
133         gr.gr_mem[n++] = NULL;
134     } else
135         gr.gr_mem = NULL;
136     return &gr;
137 }
138
139 struct group *
140 mygetgrnam(const char *name)
141 {
142     struct group *gr;
143
144     if (grf == NULL) {
145         if ((grf = fopen(grfile, "r")) == NULL)
146             return NULL;
147         fcntl(fileno(grf), F_SETFD, FD_CLOEXEC);
148     } else {
149         rewind(grf);
150     }
151     while ((gr = mygetgrent()) != NULL) {
152         if (strcmp(gr->gr_name, name) == 0)
153             break;
154     }
155     if (!gr_stayopen) {
156         fclose(grf);
157         grf = NULL;
158     }
159     return gr;
160 }
161
162 struct group *
163 mygetgrgid(gid_t gid)
164 {
165     struct group *gr;
166
167     if (grf == NULL) {
168         if ((grf = fopen(grfile, "r")) == NULL)
169             return NULL;
170         fcntl(fileno(grf), F_SETFD, FD_CLOEXEC);
171     } else {
172         rewind(grf);
173     }
174     while ((gr = mygetgrent()) != NULL) {
175         if (gr->gr_gid == gid)
176             break;
177     }
178     if (!gr_stayopen) {
179         fclose(grf);
180         grf = NULL;
181     }
182     return gr;
183 }