import less(1)
[unleashed/tickless.git] / usr / src / lib / libc / port / gen / getspent_r.c
blob23059c5073c5c30a084c60d956fb7b373e24383a
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 * Copyright (c) 2016 by Delphix. All rights reserved.
28 #pragma ident "%Z%%M% %I% %E% SMI"
30 #include "lint.h"
31 #include <mtlib.h>
32 #include <sys/types.h>
33 #include <shadow.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <nss_dbdefs.h>
37 #include <stdio.h>
38 #include <synch.h>
40 int str2spwd(const char *, int, void *,
41 char *, int);
43 static DEFINE_NSS_DB_ROOT(db_root);
44 static DEFINE_NSS_GETENT(context);
46 void
47 _nss_initf_shadow(nss_db_params_t *p)
49 p->name = NSS_DBNAM_SHADOW;
50 p->config_name = NSS_DBNAM_PASSWD; /* Use config for "passwd" */
51 p->default_config = NSS_DEFCONF_PASSWD;
54 struct spwd *
55 getspnam_r(const char *name, struct spwd *result, char *buffer, int buflen)
57 nss_XbyY_args_t arg;
59 NSS_XbyY_INIT(&arg, result, buffer, buflen, str2spwd);
60 arg.key.name = name;
61 (void) nss_search(&db_root, _nss_initf_shadow,
62 NSS_DBOP_SHADOW_BYNAME, &arg);
63 return ((struct spwd *)NSS_XbyY_FINI(&arg));
66 void
67 setspent(void)
69 nss_setent(&db_root, _nss_initf_shadow, &context);
72 void
73 endspent(void)
75 nss_endent(&db_root, _nss_initf_shadow, &context);
76 nss_delete(&db_root);
79 struct spwd *
80 getspent_r(struct spwd *result, char *buffer, int buflen)
82 nss_XbyY_args_t arg;
83 char *nam;
85 NSS_XbyY_INIT(&arg, result, buffer, buflen, str2spwd);
86 /* No key to fill in */
87 (void) nss_getent(&db_root, _nss_initf_shadow, &context, &arg);
89 return (struct spwd *)NSS_XbyY_FINI(&arg);
92 struct spwd *
93 fgetspent_r(FILE *f, struct spwd *result, char *buffer, int buflen)
95 extern void _nss_XbyY_fgets(FILE *, nss_XbyY_args_t *);
96 nss_XbyY_args_t arg;
98 /* No key to fill in */
99 NSS_XbyY_INIT(&arg, result, buffer, buflen, str2spwd);
100 _nss_XbyY_fgets(f, &arg);
101 return (struct spwd *)NSS_XbyY_FINI(&arg);
104 typedef const char *constp;
106 static int /* 1 means success and more input, 0 means error or no more */
107 getfield(constp *nextp, constp limit, int uns, void *valp)
109 constp p = *nextp;
110 char *endfield;
111 char numbuf[12]; /* Holds -2^31 and trailing ':' */
112 size_t len;
114 if (p == 0 || p >= limit) {
115 return (0);
117 if (*p == ':') {
118 p++;
119 *nextp = p;
120 return (p < limit);
122 if ((len = limit - p) > sizeof (numbuf) - 1) {
123 len = sizeof (numbuf) - 1;
126 * We want to use strtol() and we have a readonly non-zero-terminated
127 * string, so first we copy and terminate the interesting bit.
128 * Ugh. (It's convenient to terminate with a colon rather than \0).
130 if ((endfield = memccpy(numbuf, p, ':', len)) == 0) {
131 if (len != limit - p) {
132 /* Error -- field is too big to be a legit number */
133 return (0);
135 numbuf[len] = ':';
136 p = limit;
137 } else {
138 p += (endfield - numbuf);
140 if (uns) {
141 unsigned long ux = strtoul(numbuf, &endfield, 10);
142 if (*endfield != ':') {
143 /* Error -- expected <integer><colon> */
144 return (0);
146 *((unsigned int *)valp) = (unsigned int)ux;
147 } else {
148 long x = strtol(numbuf, &endfield, 10);
149 if (*endfield != ':') {
150 /* Error -- expected <integer><colon> */
151 return (0);
153 *((int *)valp) = (int)x;
155 *nextp = p;
156 return (p < limit);
160 * str2spwd() -- convert a string to a shadow passwd entry. The parser is
161 * more liberal than the passwd or group parsers; since it's legitimate
162 * for almost all the fields here to be blank, the parser lets one omit
163 * any number of blank fields at the end of the entry.
164 * === Is this likely to do more harm than good?
166 * Return values: 0 = success, 1 = parse error, 2 = erange ...
167 * The structure pointer passed in is a structure in the caller's space
168 * wherein the field pointers would be set to areas in the buffer if
169 * need be. instring and buffer should be separate areas.
172 str2spwd(const char *instr, int lenstr, void *ent, char *buffer, int buflen)
174 struct spwd *shadow = (struct spwd *)ent;
175 const char *p = instr, *limit;
176 char *bufp;
177 size_t lencopy;
179 limit = p + lenstr;
180 if ((p = memchr(instr, ':', lenstr)) == 0 ||
181 ++p >= limit ||
182 (p = memchr(p, ':', limit - p)) == 0) {
183 lencopy = (size_t)lenstr;
184 p = 0;
185 } else {
186 lencopy = p - instr;
187 p++;
189 if (lencopy + 1 > buflen) {
190 return (NSS_STR_PARSE_ERANGE);
193 if (instr != buffer) {
194 /* Overlapping buffer copies are OK */
195 (void) memmove(buffer, instr, lencopy);
196 buffer[lencopy] = 0;
199 /* quick exit do not entry fill if not needed */
200 if (ent == NULL)
201 return (NSS_STR_PARSE_SUCCESS);
203 shadow->sp_namp = bufp = buffer;
204 shadow->sp_pwdp = 0;
205 shadow->sp_lstchg = -1;
206 shadow->sp_min = -1;
207 shadow->sp_max = -1;
208 shadow->sp_warn = -1;
209 shadow->sp_inact = -1;
210 shadow->sp_expire = -1;
211 shadow->sp_flag = 0;
213 if ((bufp = strchr(bufp, ':')) == 0)
214 return (NSS_STR_PARSE_PARSE);
215 *bufp++ = '\0';
217 shadow->sp_pwdp = bufp;
218 if (instr == 0) {
219 if ((bufp = strchr(bufp, ':')) == 0)
220 return (NSS_STR_PARSE_PARSE);
221 *bufp++ = '\0';
222 p = bufp;
223 } /* else p was set when we copied name and passwd into the buffer */
225 if (!getfield(&p, limit, 0, &shadow->sp_lstchg))
226 return (NSS_STR_PARSE_SUCCESS);
227 if (!getfield(&p, limit, 0, &shadow->sp_min))
228 return (NSS_STR_PARSE_SUCCESS);
229 if (!getfield(&p, limit, 0, &shadow->sp_max))
230 return (NSS_STR_PARSE_SUCCESS);
231 if (!getfield(&p, limit, 0, &shadow->sp_warn))
232 return (NSS_STR_PARSE_SUCCESS);
233 if (!getfield(&p, limit, 0, &shadow->sp_inact))
234 return (NSS_STR_PARSE_SUCCESS);
235 if (!getfield(&p, limit, 0, &shadow->sp_expire))
236 return (NSS_STR_PARSE_SUCCESS);
237 if (!getfield(&p, limit, 1, &shadow->sp_flag))
238 return (NSS_STR_PARSE_SUCCESS);
239 if (p != limit) {
240 /* Syntax error -- garbage at end of line */
241 return (NSS_STR_PARSE_PARSE);
243 return (NSS_STR_PARSE_SUCCESS);