Imported Upstream version 1.8.6p8
[debian/sudo] / plugins / sample_group / getgrent.c
1 /*
2  * Copyright (c) 2005,2008,2010-2011 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 <sys/param.h>
25 #include <stdio.h>
26 #ifdef STDC_HEADERS
27 # include <stdlib.h>
28 # include <stddef.h>
29 #else
30 # ifdef HAVE_STDLIB_H
31 #  include <stdlib.h>
32 # endif
33 #endif /* STDC_HEADERS */
34 #ifdef HAVE_STRING_H
35 # if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS)
36 #  include <memory.h>
37 # endif
38 # include <string.h>
39 #endif /* HAVE_STRING_H */
40 #ifdef HAVE_STRINGS_H
41 # include <strings.h>
42 #endif /* HAVE_STRINGS_H */
43 #include <fcntl.h>
44 #include <limits.h>
45 #include <pwd.h>
46 #include <grp.h>
47
48 #include "missing.h"
49
50 #ifndef LINE_MAX
51 # define LINE_MAX 2048
52 #endif
53
54 #undef GRMEM_MAX
55 #define GRMEM_MAX 200
56
57 static FILE *grf;
58 static const char *grfile = "/etc/group";
59 static int gr_stayopen;
60
61 void mysetgrfile(const char *);
62 void mysetgrent(void);
63 void myendgrent(void);
64 struct group *mygetgrent(void);
65 struct group *mygetgrnam(const char *);
66 struct group *mygetgrgid(gid_t);
67
68 void
69 mysetgrfile(const char *file)
70 {
71     grfile = file;
72     if (grf != NULL)
73         myendgrent();
74 }
75
76 void
77 mysetgrent(void)
78 {
79     if (grf == NULL) {
80         grf = fopen(grfile, "r");
81         if (grf != NULL)
82             fcntl(fileno(grf), F_SETFD, FD_CLOEXEC);
83     } else {
84         rewind(grf);
85     }
86     gr_stayopen = 1;
87 }
88
89 void
90 myendgrent(void)
91 {
92     if (grf != NULL) {
93         fclose(grf);
94         grf = NULL;
95     }
96     gr_stayopen = 0;
97 }
98
99 struct group *
100 mygetgrent(void)
101 {
102     static struct group gr;
103     static char grbuf[LINE_MAX], *gr_mem[GRMEM_MAX+1];
104     size_t len;
105     char *cp, *colon;
106     int n;
107
108     if ((colon = fgets(grbuf, sizeof(grbuf), grf)) == NULL)
109         return NULL;
110
111     memset(&gr, 0, sizeof(gr));
112     if ((colon = strchr(cp = colon, ':')) == NULL)
113         return NULL;
114     *colon++ = '\0';
115     gr.gr_name = cp;
116     if ((colon = strchr(cp = colon, ':')) == NULL)
117         return NULL;
118     *colon++ = '\0';
119     gr.gr_passwd = cp;
120     if ((colon = strchr(cp = colon, ':')) == NULL)
121         return NULL;
122     *colon++ = '\0';
123     gr.gr_gid = atoi(cp);
124     len = strlen(colon);
125     if (len > 0 && colon[len - 1] == '\n')
126         colon[len - 1] = '\0';
127     if (*colon != '\0') {
128         gr.gr_mem = gr_mem;
129         cp = strtok(colon, ",");
130         for (n = 0; cp != NULL && n < GRMEM_MAX; n++) {
131             gr.gr_mem[n] = cp;
132             cp = strtok(NULL, ",");
133         }
134         gr.gr_mem[n++] = NULL;
135     } else
136         gr.gr_mem = NULL;
137     return &gr;
138 }
139
140 struct group *
141 mygetgrnam(const char *name)
142 {
143     struct group *gr;
144
145     if (grf == NULL) {
146         if ((grf = fopen(grfile, "r")) == NULL)
147             return NULL;
148         fcntl(fileno(grf), F_SETFD, FD_CLOEXEC);
149     } else {
150         rewind(grf);
151     }
152     while ((gr = mygetgrent()) != NULL) {
153         if (strcmp(gr->gr_name, name) == 0)
154             break;
155     }
156     if (!gr_stayopen) {
157         fclose(grf);
158         grf = NULL;
159     }
160     return gr;
161 }
162
163 struct group *
164 mygetgrgid(gid_t gid)
165 {
166     struct group *gr;
167
168     if (grf == NULL) {
169         if ((grf = fopen(grfile, "r")) == NULL)
170             return NULL;
171         fcntl(fileno(grf), F_SETFD, FD_CLOEXEC);
172     } else {
173         rewind(grf);
174     }
175     while ((gr = mygetgrent()) != NULL) {
176         if (gr->gr_gid == gid)
177             break;
178     }
179     if (!gr_stayopen) {
180         fclose(grf);
181         grf = NULL;
182     }
183     return gr;
184 }