gid.c revision 4321:a8930ec16e52
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 * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25/*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
26/*	  All Rights Reserved  	*/
27
28
29#pragma ident	"%Z%%M%	%I%	%E% SMI"	/* SVr4.0 1.5 */
30
31#include <sys/types.h>
32#include <stdio.h>
33#include <userdefs.h>
34
35#include <sys/param.h>
36#ifndef	MAXUID
37#include <limits.h>
38#ifdef UID_MAX
39#define	MAXUID	UID_MAX
40#else
41#define	MAXUID	60000
42#endif
43#endif
44
45/*
46 * Check to see that the gid is not a reserved gid
47 * -- nobody, noaccess or nogroup
48 */
49static int
50isvalidgid(gid_t gid)
51{
52	return (gid != 60001 && gid != 60002 && gid != 65534);
53}
54
55gid_t
56findnextgid()
57{
58	FILE *fptr;
59	gid_t last, next;
60	gid_t gid;
61
62	/*
63	 * Sort the used GIDs in decreasing order to return MAXUSED + 1
64	 */
65	if ((fptr = popen("exec sh -c "
66	    "\"getent group|cut -f3 -d:|sort -nr|uniq \" 2>/dev/null",
67	    "r")) == NULL)
68		return (-1);
69
70	if (fscanf(fptr, "%u\n", &next) == EOF) {
71		(void) pclose(fptr);
72		return (DEFRID + 1);
73	}
74
75	/*
76	 * 'next' is now the highest allocated gid.
77	 *
78	 * The simplest allocation is where we just add one, and obtain
79	 * a valid gid.  If this fails look for a hole in the gid range ..
80	 */
81
82	last = MAXUID;		/* upper limit */
83	gid = -1;		/* start invalid */
84	do {
85		if (!isvalidgid(next))
86			continue;
87
88		if (next <= DEFRID) {
89			if (last != DEFRID + 1)
90				gid = DEFRID + 1;
91			break;
92		}
93
94		if ((gid = next + 1) != last) {
95			while (!isvalidgid(gid))
96				gid++;
97			if (gid > 0 && gid < last)
98				break;
99		}
100
101		gid = -1;
102		last = next;
103
104	} while (fscanf(fptr, "%u\n", &next) != EOF);
105
106	(void) pclose(fptr);
107
108	return (gid);
109}
110