xref: /illumos-gate/usr/src/cmd/oamuser/user/proj.c (revision 4eaa471005973e11a6110b69fe990530b3b95a38)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
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.
13  *
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]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <sys/types.h>
29 #include <stdio.h>
30 #include <ctype.h>
31 #include <sys/stat.h>
32 #include <project.h>
33 #include <unistd.h>
34 #include <userdefs.h>
35 #include <errno.h>
36 #include <nss_dbdefs.h>
37 #include "users.h"
38 #include "messages.h"
39 
40 int
41 edit_project(char *login, char *new_login, projid_t projids[], int overwrite)
42 {
43 	char **memptr;
44 	char t_name[] = "/etc/projtmp.XXXXXX";
45 	FILE *e_fptr, *t_fptr;
46 	struct project *p_ptr;
47 	struct project p_work;
48 	char workbuf[NSS_LINELEN_PROJECT];
49 	int i, modified = 0;
50 	struct stat sbuf;
51 	int p_length;
52 	char p_string[NSS_LINELEN_PROJECT];
53 	long p_curr = 0;
54 	int exist;
55 	int fd;
56 
57 	if ((e_fptr = fopen(PROJF_PATH, "r")) == NULL) {
58 		return (EX_UPDATE);
59 	}
60 
61 	if (fstat(fileno(e_fptr), &sbuf) != 0)
62 		return (EX_UPDATE);
63 
64 	if ((fd = mkstemp(t_name)) < 0) {
65 		return (EX_UPDATE);
66 	}
67 
68 	if ((t_fptr = fdopen(fd, "w+")) == NULL) {
69 		(void) close(fd);
70 		(void) unlink(t_name);
71 		return (EX_UPDATE);
72 	}
73 
74 	/*
75 	 * Get ownership and permissions correct
76 	 */
77 
78 	if (fchmod(fd, sbuf.st_mode) != 0 ||
79 	    fchown(fd, sbuf.st_uid, sbuf.st_gid) != 0) {
80 		(void) fclose(t_fptr);
81 		(void) unlink(t_name);
82 		return (EX_UPDATE);
83 	}
84 
85 	p_curr = ftell(e_fptr);
86 
87 	/* Make TMP file look like we want project file to look */
88 
89 	while (fgets(p_string, NSS_LINELEN_PROJECT - 1, e_fptr)) {
90 		/* While there is another group string */
91 
92 		p_length = strlen(p_string);
93 		(void) fseek(e_fptr, p_curr, SEEK_SET);
94 		p_ptr = fgetprojent(e_fptr, &p_work, &workbuf,
95 		    sizeof (workbuf));
96 		p_curr = ftell(e_fptr);
97 
98 		if (p_ptr == NULL) {
99 			/*
100 			 * tried to parse a proj string over
101 			 * NSS_LINELEN_PROJECT chars
102 			 */
103 			errmsg(M_PROJ_ENTRY_OVF, NSS_LINELEN_PROJECT);
104 			modified = 0; /* bad project file: cannot rebuild */
105 			break;
106 		}
107 
108 		/* first delete the login from the project, if it's there */
109 		if (overwrite || !projids) {
110 			if (p_ptr->pj_users != NULL) {
111 				for (memptr = p_ptr->pj_users; *memptr;
112 				    memptr++) {
113 					if (strcmp(*memptr, login) == 0) {
114 						/* Delete this one */
115 						char **from = memptr + 1;
116 						p_length -= (strlen(*memptr)+1);
117 						do {
118 							*(from - 1) = *from;
119 						} while (*from++);
120 
121 						modified++;
122 						break;
123 					}
124 				}
125 			}
126 		}
127 
128 		/* now check to see if project is one to add to */
129 		if (projids) {
130 			for (i = 0; projids[i] != -1; i++) {
131 				if (p_ptr->pj_projid == projids[i]) {
132 					/* Scan for dups */
133 					exist = 0;
134 					for (memptr = p_ptr->pj_users; *memptr;
135 					    memptr++) {
136 						if (strncmp(*memptr, new_login ?
137 						    new_login : login,
138 						    strlen(*memptr)) == 0)
139 							exist++;
140 					}
141 					p_length += strlen(new_login ?
142 					    new_login : login) + 1;
143 
144 					if (p_length >=
145 					    NSS_LINELEN_PROJECT - 1) {
146 						errmsg(M_PROJ_ENTRY_OVF,
147 						    NSS_LINELEN_PROJECT);
148 						break;
149 					} else {
150 						if (!exist) {
151 						*memptr++ = new_login ?
152 						    new_login : login;
153 						*memptr = NULL;
154 						modified++;
155 						}
156 					}
157 				}
158 			}
159 		}
160 		putprojent(p_ptr, t_fptr);
161 	}
162 
163 	(void) fclose(e_fptr);
164 	(void) fclose(t_fptr);
165 
166 	/* Now, update project file, if it was modified */
167 	if (modified && rename(t_name, PROJF_PATH) < 0) {
168 		(void) unlink(t_name);
169 		return (EX_UPDATE);
170 	}
171 
172 	(void) unlink(t_name);
173 	return (EX_SUCCESS);
174 }
175