1/*
2 * CDDL HEADER START
3 *
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.
7 *
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.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27/*	Copyright (c) 1988 AT&T	*/
28/*	  All Rights Reserved  	*/
29
30#pragma ident	"%Z%%M%	%I%	%E% SMI"
31
32#pragma weak _getgrnam	= getgrnam
33#pragma weak _getgrgid	= getgrgid
34
35#include "lint.h"
36#include <sys/types.h>
37#include <grp.h>
38#include <nss_dbdefs.h>
39#include <stdio.h>
40#include "tsd.h"
41
42#ifdef	NSS_INCLUDE_UNSAFE
43
44extern size_t _nss_get_bufsizes(int arg);
45
46/*
47 * Ye olde non-reentrant interface (MT-unsafe, caveat utor)
48 */
49
50static void
51free_grbuf(void *arg)
52{
53	nss_XbyY_buf_t **buffer = arg;
54
55	NSS_XbyY_FREE(buffer);
56}
57
58static nss_XbyY_buf_t *
59get_grbuf(int max_buf)
60{
61	nss_XbyY_buf_t **buffer =
62	    tsdalloc(_T_GRBUF, sizeof (nss_XbyY_buf_t *), free_grbuf);
63	nss_XbyY_buf_t *b;
64	size_t	blen;
65
66	if (buffer == NULL)
67		return (NULL);
68	if (max_buf == 0)
69		blen = _nss_get_bufsizes(0);		/* default size */
70	else
71		blen = sysconf(_SC_GETGR_R_SIZE_MAX);	/* max size */
72	if (*buffer) {
73		if ((*buffer)->buflen >= blen)	/* existing size fits */
74			return (*buffer);
75		NSS_XbyY_FREE(buffer);		/* existing is too small */
76	}
77	b = NSS_XbyY_ALLOC(buffer, sizeof (struct group), blen);
78	return (b);
79}
80
81struct group *
82getgrgid(gid_t gid)
83{
84	nss_XbyY_buf_t	*b = get_grbuf(0);
85	struct group *ret;
86
87	if (b == NULL)
88		return (NULL);
89
90	ret = getgrgid_r(gid, b->result, b->buffer, b->buflen);
91	if (ret == NULL && errno == ERANGE) {
92		b = get_grbuf(1);
93		if (b == NULL)
94			return (NULL);
95		ret = getgrgid_r(gid, b->result, b->buffer, b->buflen);
96	}
97	return (ret);
98}
99
100struct group *
101getgrnam(const char *nam)
102{
103	nss_XbyY_buf_t	*b = get_grbuf(0);
104	struct group *ret;
105
106	if (b == NULL)
107		return (NULL);
108
109	ret = getgrnam_r(nam, b->result, b->buffer, b->buflen);
110	if (ret == NULL && errno == ERANGE && nam != NULL) {
111		b = get_grbuf(1);
112		if (b == NULL)
113			return (NULL);
114		ret = getgrnam_r(nam, b->result, b->buffer, b->buflen);
115	}
116	return (ret);
117}
118
119struct group *
120getgrent(void)
121{
122	nss_XbyY_buf_t	*b = get_grbuf(1);
123
124	return (b == NULL ? NULL :
125	    getgrent_r(b->result, b->buffer, b->buflen));
126}
127
128struct group *
129fgetgrent(FILE *f)
130{
131	nss_XbyY_buf_t	*b = get_grbuf(1);
132
133	return (b == NULL ? NULL :
134	    fgetgrent_r(f, b->result, b->buffer, b->buflen));
135}
136
137#endif	/* NSS_INCLUDE_UNSAFE */
138