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