4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
30 #pragma ident "%Z%%M% %I% %E% SMI"
32 #include <sys/types.h>
46 #define MYBUFSIZE (LINE_MAX)
47 /* Corresponds to MYBUFSIZE in grpck.c, BUFCONST in nss_dbdefs.c */
50 edit_group(char *login
, char *new_login
, gid_t gids
[], int overwrite
)
53 char t_name
[] = "/etc/gtmp.XXXXXX";
55 FILE *e_fptr
, *t_fptr
;
56 struct group
*g_ptr
; /* group structure from fgetgrent */
61 int bufsize
, g_length
, sav_errno
;
63 char *g_string
, *new_g_string
, *gstr_off
;
65 if ((e_fptr
= fopen(GROUP
, "r")) == NULL
)
68 if (fstat(fileno(e_fptr
), &sbuf
) != 0) {
69 (void) fclose(e_fptr
);
73 if ((fd
= mkstemp(t_name
)) == -1) {
74 (void) fclose(e_fptr
);
78 if ((t_fptr
= fdopen(fd
, "w")) == NULL
) {
80 (void) unlink(t_name
);
81 (void) fclose(e_fptr
);
86 * Get ownership and permissions correct
89 if (fchmod(fd
, sbuf
.st_mode
) != 0 ||
90 fchown(fd
, sbuf
.st_uid
, sbuf
.st_gid
) != 0) {
91 (void) fclose(t_fptr
);
92 (void) fclose(e_fptr
);
93 (void) unlink(t_name
);
97 g_curr
= ftell(e_fptr
);
99 /* Make TMP file look like we want GROUP file to look */
102 if ((g_string
= malloc(bufsize
)) == NULL
) {
103 (void) fclose(t_fptr
);
104 (void) fclose(e_fptr
);
105 (void) unlink(t_name
);
109 * bufsize contains the size of the currently allocated buffer
110 * buffer size, which is initially MYBUFSIZE but when a line
111 * greater than MYBUFSIZE is encountered then bufsize gets increased
113 * g_string always points to the beginning of the buffer (even after
115 * gstr_off = g_string + MYBUFSIZE * (n), where n >= 0.
117 while (!feof(e_fptr
) && !ferror(e_fptr
)) {
120 while (fgets(gstr_off
, (bufsize
- g_length
), e_fptr
) != NULL
) {
121 g_length
+= strlen(gstr_off
);
122 if (g_string
[g_length
- 1] == '\n' || feof(e_fptr
))
124 new_g_string
= realloc(g_string
, (bufsize
+ MYBUFSIZE
));
125 if (new_g_string
== NULL
) {
127 (void) fclose(t_fptr
);
128 (void) fclose(e_fptr
);
129 (void) unlink(t_name
);
132 bufsize
+= MYBUFSIZE
;
133 g_string
= new_g_string
;
134 gstr_off
= g_string
+ g_length
;
140 /* While there is another group string */
142 (void) fseek(e_fptr
, g_curr
, SEEK_SET
);
144 g_ptr
= fgetgrent(e_fptr
);
146 g_curr
= ftell(e_fptr
);
149 /* tried to parse a group string over MYBUFSIZ char */
150 if (sav_errno
== ERANGE
)
151 errmsg(M_GROUP_ENTRY_OVF
);
153 errmsg(M_READ_ERROR
);
155 modified
= 0; /* bad group file: cannot rebuild */
159 /* first delete the login from the group, if it's there */
160 if (overwrite
|| !gids
) {
161 if (g_ptr
->gr_mem
!= NULL
) {
162 for (memptr
= g_ptr
->gr_mem
; *memptr
;
164 if (strcmp(*memptr
, login
) == 0) {
165 /* Delete this one */
166 char **from
= memptr
+ 1;
168 g_length
-= (strlen(*memptr
)+1);
181 /* now check to see if group is one to add to */
183 for (i
= 0; gids
[i
] != -1; i
++) {
184 if (g_ptr
->gr_gid
== gids
[i
]) {
186 for (memptr
= g_ptr
->gr_mem
; *memptr
;
189 g_length
+= strlen(new_login
?
190 new_login
: login
)+1;
192 *memptr
++ = new_login
?
200 putgrent(g_ptr
, t_fptr
);
204 (void) fclose(e_fptr
);
206 if (fclose(t_fptr
) != 0) {
207 (void) unlink(t_name
);
211 /* Now, update GROUP file, if it was modified */
213 if (rename(t_name
, GROUP
) != 0) {
214 (void) unlink(t_name
);
219 (void) unlink(t_name
);