pw_vpw.c revision 330449
1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (C) 1996
5 *	David L. Nugent.  All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY DAVID L. NUGENT AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED.  IN NO EVENT SHALL DAVID L. NUGENT OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 */
29
30#ifndef lint
31static const char rcsid[] =
32  "$FreeBSD: stable/11/usr.sbin/pw/pw_vpw.c 330449 2018-03-05 07:26:05Z eadler $";
33#endif /* not lint */
34
35#include <pwd.h>
36#include <grp.h>
37#include <libutil.h>
38#define _WITH_GETLINE
39#include <stdio.h>
40#include <string.h>
41#include <stdlib.h>
42#include <err.h>
43
44#include "pwupd.h"
45
46static FILE * pwd_fp = NULL;
47
48void
49vendpwent(void)
50{
51	if (pwd_fp != NULL) {
52		fclose(pwd_fp);
53		pwd_fp = NULL;
54	}
55}
56
57void
58vsetpwent(void)
59{
60	vendpwent();
61}
62
63static struct passwd *
64vnextpwent(char const *nam, uid_t uid, int doclose)
65{
66	struct passwd *pw;
67	char *line;
68	size_t linecap;
69	ssize_t linelen;
70
71	pw = NULL;
72	line = NULL;
73	linecap = 0;
74
75	if (pwd_fp != NULL || (pwd_fp = fopen(getpwpath(_MASTERPASSWD), "r")) != NULL) {
76		while ((linelen = getline(&line, &linecap, pwd_fp)) > 0) {
77			/* Skip comments and empty lines */
78			if (*line == '\n' || *line == '#')
79				continue;
80			/* trim latest \n */
81			if (line[linelen - 1 ] == '\n')
82				line[linelen - 1] = '\0';
83			pw = pw_scan(line, PWSCAN_MASTER);
84			if (pw == NULL)
85				errx(EXIT_FAILURE, "Invalid user entry in '%s':"
86				    " '%s'", getpwpath(_MASTERPASSWD), line);
87			if (uid != (uid_t)-1) {
88				if (uid == pw->pw_uid)
89					break;
90			} else if (nam != NULL) {
91				if (strcmp(nam, pw->pw_name) == 0)
92					break;
93			} else
94				break;
95			free(pw);
96			pw = NULL;
97		}
98		if (doclose)
99			vendpwent();
100	}
101	free(line);
102
103	return (pw);
104}
105
106struct passwd *
107vgetpwent(void)
108{
109  return vnextpwent(NULL, -1, 0);
110}
111
112struct passwd *
113vgetpwuid(uid_t uid)
114{
115  return vnextpwent(NULL, uid, 1);
116}
117
118struct passwd *
119vgetpwnam(const char * nam)
120{
121  return vnextpwent(nam, -1, 1);
122}
123
124
125static FILE * grp_fp = NULL;
126
127void
128vendgrent(void)
129{
130	if (grp_fp != NULL) {
131		fclose(grp_fp);
132		grp_fp = NULL;
133	}
134}
135
136RET_SETGRENT
137vsetgrent(void)
138{
139	vendgrent();
140#if defined(__FreeBSD__)
141	return 0;
142#endif
143}
144
145static struct group *
146vnextgrent(char const *nam, gid_t gid, int doclose)
147{
148	struct group *gr;
149	char *line;
150	size_t linecap;
151	ssize_t linelen;
152
153	gr = NULL;
154	line = NULL;
155	linecap = 0;
156
157	if (grp_fp != NULL || (grp_fp = fopen(getgrpath(_GROUP), "r")) != NULL) {
158		while ((linelen = getline(&line, &linecap, grp_fp)) > 0) {
159			/* Skip comments and empty lines */
160			if (*line == '\n' || *line == '#')
161				continue;
162			/* trim latest \n */
163			if (line[linelen - 1 ] == '\n')
164				line[linelen - 1] = '\0';
165			gr = gr_scan(line);
166			if (gr == NULL)
167				errx(EXIT_FAILURE, "Invalid group entry in '%s':"
168				    " '%s'", getgrpath(_GROUP), line);
169			if (gid != (gid_t)-1) {
170				if (gid == gr->gr_gid)
171					break;
172			} else if (nam != NULL) {
173				if (strcmp(nam, gr->gr_name) == 0)
174					break;
175			} else
176				break;
177			free(gr);
178			gr = NULL;
179		}
180		if (doclose)
181			vendgrent();
182	}
183	free(line);
184
185	return (gr);
186}
187
188struct group *
189vgetgrent(void)
190{
191  return vnextgrent(NULL, -1, 0);
192}
193
194
195struct group *
196vgetgrgid(gid_t gid)
197{
198  return vnextgrent(NULL, gid, 1);
199}
200
201struct group *
202vgetgrnam(const char * nam)
203{
204  return vnextgrent(nam, -1, 1);
205}
206
207