dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / oamuser / user / groups.c
blobc8c1644e8fd530304c6751bfeaba61380aafd1c8
1 /*
2 * CDDL HEADER START
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
7 * with the License.
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]
20 * CDDL HEADER END
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>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <ctype.h>
37 #include <sys/stat.h>
38 #include <grp.h>
39 #include <unistd.h>
40 #include <userdefs.h>
41 #include <errno.h>
42 #include <limits.h>
43 #include "users.h"
44 #include "messages.h"
46 #define MYBUFSIZE (LINE_MAX)
47 /* Corresponds to MYBUFSIZE in grpck.c, BUFCONST in nss_dbdefs.c */
49 int
50 edit_group(char *login, char *new_login, gid_t gids[], int overwrite)
52 char **memptr;
53 char t_name[] = "/etc/gtmp.XXXXXX";
54 int fd;
55 FILE *e_fptr, *t_fptr;
56 struct group *g_ptr; /* group structure from fgetgrent */
57 int i;
58 int modified = 0;
59 struct stat sbuf;
61 int bufsize, g_length, sav_errno;
62 long g_curr = 0L;
63 char *g_string, *new_g_string, *gstr_off;
65 if ((e_fptr = fopen(GROUP, "r")) == NULL)
66 return (EX_UPDATE);
68 if (fstat(fileno(e_fptr), &sbuf) != 0) {
69 (void) fclose(e_fptr);
70 return (EX_UPDATE);
73 if ((fd = mkstemp(t_name)) == -1) {
74 (void) fclose(e_fptr);
75 return (EX_UPDATE);
78 if ((t_fptr = fdopen(fd, "w")) == NULL) {
79 (void) close(fd);
80 (void) unlink(t_name);
81 (void) fclose(e_fptr);
82 return (EX_UPDATE);
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);
94 return (EX_UPDATE);
97 g_curr = ftell(e_fptr);
99 /* Make TMP file look like we want GROUP file to look */
101 bufsize = MYBUFSIZE;
102 if ((g_string = malloc(bufsize)) == NULL) {
103 (void) fclose(t_fptr);
104 (void) fclose(e_fptr);
105 (void) unlink(t_name);
106 return (EX_UPDATE);
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
112 * by MYBUFSIZE.
113 * g_string always points to the beginning of the buffer (even after
114 * realloc()).
115 * gstr_off = g_string + MYBUFSIZE * (n), where n >= 0.
117 while (!feof(e_fptr) && !ferror(e_fptr)) {
118 g_length = 0;
119 gstr_off = g_string;
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))
123 break;
124 new_g_string = realloc(g_string, (bufsize + MYBUFSIZE));
125 if (new_g_string == NULL) {
126 free(g_string);
127 (void) fclose(t_fptr);
128 (void) fclose(e_fptr);
129 (void) unlink(t_name);
130 return (EX_UPDATE);
132 bufsize += MYBUFSIZE;
133 g_string = new_g_string;
134 gstr_off = g_string + g_length;
136 if (g_length == 0) {
137 continue;
140 /* While there is another group string */
142 (void) fseek(e_fptr, g_curr, SEEK_SET);
143 errno = 0;
144 g_ptr = fgetgrent(e_fptr);
145 sav_errno = errno;
146 g_curr = ftell(e_fptr);
148 if (g_ptr == NULL) {
149 /* tried to parse a group string over MYBUFSIZ char */
150 if (sav_errno == ERANGE)
151 errmsg(M_GROUP_ENTRY_OVF);
152 else
153 errmsg(M_READ_ERROR);
155 modified = 0; /* bad group file: cannot rebuild */
156 break;
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;
163 memptr++) {
164 if (strcmp(*memptr, login) == 0) {
165 /* Delete this one */
166 char **from = memptr + 1;
168 g_length -= (strlen(*memptr)+1);
170 do {
171 *(from - 1) = *from;
172 } while (*from++);
174 modified++;
175 break;
181 /* now check to see if group is one to add to */
182 if (gids) {
183 for (i = 0; gids[i] != -1; i++) {
184 if (g_ptr->gr_gid == gids[i]) {
185 /* Find end */
186 for (memptr = g_ptr->gr_mem; *memptr;
187 memptr++)
189 g_length += strlen(new_login ?
190 new_login : login)+1;
192 *memptr++ = new_login ?
193 new_login : login;
194 *memptr = NULL;
196 modified++;
200 putgrent(g_ptr, t_fptr);
202 free(g_string);
204 (void) fclose(e_fptr);
206 if (fclose(t_fptr) != 0) {
207 (void) unlink(t_name);
208 return (EX_UPDATE);
211 /* Now, update GROUP file, if it was modified */
212 if (modified) {
213 if (rename(t_name, GROUP) != 0) {
214 (void) unlink(t_name);
215 return (EX_UPDATE);
217 return (EX_SUCCESS);
218 } else {
219 (void) unlink(t_name);
220 return (EX_SUCCESS);