Merge branch 'vendor/GDB'
[dragonfly.git] / usr.sbin / mtree / getid.c
1 /*      $NetBSD: getid.c,v 1.10 2014/10/27 21:46:45 christos Exp $      */
2 /*      from: NetBSD: getpwent.c,v 1.48 2000/10/03 03:22:26 enami Exp */
3 /*      from: NetBSD: getgrent.c,v 1.41 2002/01/12 23:51:30 lukem Exp */
4
5 /*
6  * Copyright (c) 1987, 1988, 1989, 1993, 1994, 1995
7  *      The Regents of the University of California.  All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33
34 /*-
35  * Copyright (c) 2002 The NetBSD Foundation, Inc.
36  * All rights reserved.
37  *
38  * This code is derived from software contributed to The NetBSD Foundation
39  * by Luke Mewburn of Wasabi Systems.
40  *
41  * Redistribution and use in source and binary forms, with or without
42  * modification, are permitted provided that the following conditions
43  * are met:
44  * 1. Redistributions of source code must retain the above copyright
45  *    notice, this list of conditions and the following disclaimer.
46  * 2. Redistributions in binary form must reproduce the above copyright
47  *    notice, this list of conditions and the following disclaimer in the
48  *    documentation and/or other materials provided with the distribution.
49  *
50  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
51  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
52  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
53  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
54  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
55  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
56  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
57  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
58  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
59  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
60  * POSSIBILITY OF SUCH DAMAGE.
61  */
62
63 #include <sys/param.h>
64
65 #include <grp.h>
66 #include <limits.h>
67 #include <pwd.h>
68 #include <stdlib.h>
69 #include <stdio.h>
70 #include <string.h>
71 #include <time.h>
72 #include <unistd.h>
73
74 #include "extern.h"
75
76 static  struct group *  gi_getgrnam(const char *);
77 static  struct group *  gi_getgrgid(gid_t);
78 static  int             gi_setgroupent(int);
79 static  void            gi_endgrent(void);
80 static  int             grstart(void);
81 static  int             grscan(int, gid_t, const char *);
82 static  int             grmatchline(int, gid_t, const char *);
83
84 static  struct passwd * gi_getpwnam(const char *);
85 static  struct passwd * gi_getpwuid(uid_t);
86 static  int             gi_setpassent(int);
87 static  void            gi_endpwent(void);
88 static  int             pwstart(void);
89 static  int             pwscan(int, uid_t, const char *);
90 static  int             pwmatchline(int, uid_t, const char *);
91
92 #define MAXGRP          200
93 #define MAXLINELENGTH   1024
94
95 static  FILE            *_gr_fp;
96 static  struct group    _gr_group;
97 static  int             _gr_stayopen;
98 static  int             _gr_filesdone;
99 static  FILE            *_pw_fp;
100 static  struct passwd   _pw_passwd;     /* password structure */
101 static  int             _pw_stayopen;   /* keep fd's open */
102 static  int             _pw_filesdone;
103
104 static  char            grfile[MAXPATHLEN];
105 static  char            pwfile[MAXPATHLEN];
106
107 static  char            *members[MAXGRP];
108 static  char            grline[MAXLINELENGTH];
109 static  char            pwline[MAXLINELENGTH];
110
111 int
112 setup_getid(const char *dir)
113 {
114         if (dir == NULL)
115                 return (0);
116
117                                 /* close existing databases */
118         gi_endgrent();
119         gi_endpwent();
120
121                                 /* build paths to new databases */
122         snprintf(grfile, sizeof(grfile), "%s/group", dir);
123         snprintf(pwfile, sizeof(pwfile), "%s/master.passwd", dir);
124
125                                 /* try to open new databases */
126         if (!grstart() || !pwstart())
127                 return (0);
128
129                                 /* switch pwcache(3) lookup functions */
130         if (pwcache_groupdb(gi_setgroupent, gi_endgrent,
131                             gi_getgrnam, gi_getgrgid) == -1
132             || pwcache_userdb(gi_setpassent, gi_endpwent,
133                             gi_getpwnam, gi_getpwuid) == -1)
134                 return (0);
135
136         return (1);
137 }
138
139
140 /*
141  * group lookup functions
142  */
143
144 static struct group *
145 gi_getgrnam(const char *name)
146 {
147         int rval;
148
149         if (!grstart())
150                 return NULL;
151         rval = grscan(1, 0, name);
152         if (!_gr_stayopen)
153                 endgrent();
154         return (rval) ? &_gr_group : NULL;
155 }
156
157 static struct group *
158 gi_getgrgid(gid_t gid)
159 {
160         int rval;
161
162         if (!grstart())
163                 return NULL;
164         rval = grscan(1, gid, NULL);
165         if (!_gr_stayopen)
166                 endgrent();
167         return (rval) ? &_gr_group : NULL;
168 }
169
170 static int
171 gi_setgroupent(int stayopen)
172 {
173
174         if (!grstart())
175                 return 0;
176         _gr_stayopen = stayopen;
177         return 1;
178 }
179
180 static void
181 gi_endgrent(void)
182 {
183
184         _gr_filesdone = 0;
185         if (_gr_fp) {
186                 (void)fclose(_gr_fp);
187                 _gr_fp = NULL;
188         }
189 }
190
191 static int
192 grstart(void)
193 {
194
195         _gr_filesdone = 0;
196         if (_gr_fp) {
197                 rewind(_gr_fp);
198                 return 1;
199         }
200         if (grfile[0] == '\0')                  /* sanity check */
201                 return 0;
202
203         _gr_fp = fopen(grfile, "r");
204         if (_gr_fp != NULL)
205                 return 1;
206         warn("Can't open `%s'", grfile);
207         return 0;
208 }
209
210
211 static int
212 grscan(int search, gid_t gid, const char *name)
213 {
214
215         if (_gr_filesdone)
216                 return 0;
217         for (;;) {
218                 if (!fgets(grline, sizeof(grline), _gr_fp)) {
219                         if (!search)
220                                 _gr_filesdone = 1;
221                         return 0;
222                 }
223                 /* skip lines that are too big */
224                 if (!strchr(grline, '\n')) {
225                         int ch;
226
227                         while ((ch = getc(_gr_fp)) != '\n' && ch != EOF)
228                                 ;
229                         continue;
230                 }
231                 /* skip comments */
232                 if (grline[0] == '#')
233                         continue;
234                 if (grmatchline(search, gid, name))
235                         return 1;
236         }
237         /* NOTREACHED */
238 }
239
240 static int
241 grmatchline(int search, gid_t gid, const char *name)
242 {
243         unsigned long   id;
244         char            **m;
245         char            *cp, *bp, *ep;
246
247         /* name may be NULL if search is nonzero */
248
249         bp = grline;
250         memset(&_gr_group, 0, sizeof(_gr_group));
251         _gr_group.gr_name = strsep(&bp, ":\n");
252         if (search && name && strcmp(_gr_group.gr_name, name))
253                 return 0;
254         _gr_group.gr_passwd = strsep(&bp, ":\n");
255         if (!(cp = strsep(&bp, ":\n")))
256                 return 0;
257         id = strtoul(cp, &ep, 10);
258         if (id > GID_MAX || *ep != '\0')
259                 return 0;
260         _gr_group.gr_gid = (gid_t)id;
261         if (search && name == NULL && _gr_group.gr_gid != gid)
262                 return 0;
263         cp = NULL;
264         if (bp == NULL)
265                 return 0;
266         for (_gr_group.gr_mem = m = members;; bp++) {
267                 if (m == &members[MAXGRP - 1])
268                         break;
269                 if (*bp == ',') {
270                         if (cp) {
271                                 *bp = '\0';
272                                 *m++ = cp;
273                                 cp = NULL;
274                         }
275                 } else if (*bp == '\0' || *bp == '\n' || *bp == ' ') {
276                         if (cp) {
277                                 *bp = '\0';
278                                 *m++ = cp;
279                         }
280                         break;
281                 } else if (cp == NULL)
282                         cp = bp;
283         }
284         *m = NULL;
285         return 1;
286 }
287
288
289 /*
290  * user lookup functions
291  */
292
293 static struct passwd *
294 gi_getpwnam(const char *name)
295 {
296         int rval;
297
298         if (!pwstart())
299                 return NULL;
300         rval = pwscan(1, 0, name);
301         if (!_pw_stayopen)
302                 endpwent();
303         return (rval) ? &_pw_passwd : NULL;
304 }
305
306 static struct passwd *
307 gi_getpwuid(uid_t uid)
308 {
309         int rval;
310
311         if (!pwstart())
312                 return NULL;
313         rval = pwscan(1, uid, NULL);
314         if (!_pw_stayopen)
315                 endpwent();
316         return (rval) ? &_pw_passwd : NULL;
317 }
318
319 static int
320 gi_setpassent(int stayopen)
321 {
322
323         if (!pwstart())
324                 return 0;
325         _pw_stayopen = stayopen;
326         return 1;
327 }
328
329 static void
330 gi_endpwent(void)
331 {
332
333         _pw_filesdone = 0;
334         if (_pw_fp) {
335                 (void)fclose(_pw_fp);
336                 _pw_fp = NULL;
337         }
338 }
339
340 static int
341 pwstart(void)
342 {
343
344         _pw_filesdone = 0;
345         if (_pw_fp) {
346                 rewind(_pw_fp);
347                 return 1;
348         }
349         if (pwfile[0] == '\0')                  /* sanity check */
350                 return 0;
351         _pw_fp = fopen(pwfile, "r");
352         if (_pw_fp != NULL)
353                 return 1;
354         warn("Can't open `%s'", pwfile);
355         return 0;
356 }
357
358
359 static int
360 pwscan(int search, uid_t uid, const char *name)
361 {
362
363         if (_pw_filesdone)
364                 return 0;
365         for (;;) {
366                 if (!fgets(pwline, sizeof(pwline), _pw_fp)) {
367                         if (!search)
368                                 _pw_filesdone = 1;
369                         return 0;
370                 }
371                 /* skip lines that are too big */
372                 if (!strchr(pwline, '\n')) {
373                         int ch;
374
375                         while ((ch = getc(_pw_fp)) != '\n' && ch != EOF)
376                                 ;
377                         continue;
378                 }
379                 /* skip comments */
380                 if (pwline[0] == '#')
381                         continue;
382                 if (pwmatchline(search, uid, name))
383                         return 1;
384         }
385         /* NOTREACHED */
386 }
387
388 static int
389 pwmatchline(int search, uid_t uid, const char *name)
390 {
391         unsigned long   id;
392         char            *cp, *bp, *ep;
393
394         /* name may be NULL if search is nonzero */
395
396         bp = pwline;
397         memset(&_pw_passwd, 0, sizeof(_pw_passwd));
398         _pw_passwd.pw_name = strsep(&bp, ":\n");                /* name */
399         if (search && name && strcmp(_pw_passwd.pw_name, name))
400                 return 0;
401
402         _pw_passwd.pw_passwd = strsep(&bp, ":\n");              /* passwd */
403
404         if (!(cp = strsep(&bp, ":\n")))                         /* uid */
405                 return 0;
406         id = strtoul(cp, &ep, 10);
407         if (id > UID_MAX || *ep != '\0')
408                 return 0;
409         _pw_passwd.pw_uid = (uid_t)id;
410         if (search && name == NULL && _pw_passwd.pw_uid != uid)
411                 return 0;
412
413         if (!(cp = strsep(&bp, ":\n")))                         /* gid */
414                 return 0;
415         id = strtoul(cp, &ep, 10);
416         if (id > GID_MAX || *ep != '\0')
417                 return 0;
418         _pw_passwd.pw_gid = (gid_t)id;
419
420         if (!(ep = strsep(&bp, ":")))                           /* class */
421                 return 0;
422         if (!(ep = strsep(&bp, ":")))                           /* change */
423                 return 0;
424         if (!(ep = strsep(&bp, ":")))                           /* expire */
425                 return 0;
426
427         if (!(_pw_passwd.pw_gecos = strsep(&bp, ":\n")))        /* gecos */
428                 return 0;
429         if (!(_pw_passwd.pw_dir = strsep(&bp, ":\n")))          /* directory */
430                 return 0;
431         if (!(_pw_passwd.pw_shell = strsep(&bp, ":\n")))        /* shell */
432                 return 0;
433
434         if (strchr(bp, ':') != NULL)
435                 return 0;
436
437         return 1;
438 }
439