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 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
22 /* All Rights Reserved */
23
24
25 /*
26 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
27 * Use is subject to license terms.
28 */
29
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <stdio.h>
33 #include <ctype.h>
34 #include <limits.h>
35 #include <pwd.h>
36 #include <project.h>
37 #include <string.h>
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <userdefs.h>
41 #include <stdlib.h>
42 #include <errno.h>
43 #include <unistd.h>
44 #include <strings.h>
45 #include "users.h"
46 #include "messages.h"
47 #include "funcs.h"
48
49 /*******************************************************************************
50 * userdel [-r] login
51 *
52 * This command deletes user logins. Arguments are:
53 *
54 * -r - when given, this option removes home directory & its contents
55 *
56 * login - a string of printable chars except colon (:)
57 ******************************************************************************/
58
59 extern int check_perm(), isbusy();
60 extern int rm_files(), call_passmgmt(), edit_group();
61
62 static char *logname; /* login name to delete */
63 static char *nargv[20]; /* arguments for execvp of passmgmt */
64
65 char *cmdname;
66
67 int
main(int argc,char ** argv)68 main(int argc, char **argv)
69 {
70 int ch, ret = 0, rflag = 0, argindex, tries;
71 struct passwd *pstruct;
72 struct stat statbuf;
73 #ifndef att
74 FILE *pwf; /* fille ptr for opened passwd file */
75 #endif
76 char *usertype = NULL;
77 int rc;
78
79 cmdname = argv[0];
80
81 if( geteuid() != 0 ) {
82 errmsg( M_PERM_DENIED );
83 exit( EX_NO_PERM );
84 }
85
86 opterr = 0; /* no print errors from getopt */
87 usertype = getusertype(argv[0]);
88
89 while( (ch = getopt(argc, argv, "r")) != EOF ) {
90 switch(ch) {
91 case 'r':
92 rflag++;
93 break;
94 case '?':
95 if (is_role(usertype))
96 errmsg( M_DRUSAGE );
97 else
98 errmsg( M_DUSAGE );
99 exit( EX_SYNTAX );
100 }
101 }
102
103 if( optind != argc - 1 ) {
104 if (is_role(usertype))
105 errmsg( M_DRUSAGE );
106 else
107 errmsg( M_DUSAGE );
108 exit( EX_SYNTAX );
109 }
110
111 logname = argv[optind];
112
113 #ifdef att
114 pstruct = getpwnam(logname);
115 #else
116 /*
117 * Do this with fgetpwent to make sure we are only looking on local
118 * system (since passmgmt only works on local system).
119 */
120 if ((pwf = fopen("/etc/passwd", "r")) == NULL) {
121 errmsg( M_OOPS, "open", "/etc/passwd");
122 exit(EX_FAILURE);
123 }
124 while ((pstruct = fgetpwent(pwf)) != NULL)
125 if (strcmp(pstruct->pw_name, logname) == 0)
126 break;
127
128 fclose(pwf);
129 #endif
130
131 if (pstruct == NULL) {
132 errmsg( M_EXIST, logname );
133 exit( EX_NAME_NOT_EXIST );
134 }
135
136 if( isbusy(logname) ) {
137 errmsg( M_BUSY, logname, "remove" );
138 exit( EX_BUSY );
139 }
140
141 /* that's it for validations - now do the work */
142 /* set up arguments to passmgmt in nargv array */
143 nargv[0] = PASSMGMT;
144 nargv[1] = "-d"; /* delete */
145 argindex = 2; /* next argument */
146
147 /* finally - login name */
148 nargv[argindex++] = logname;
149
150 /* set the last to null */
151 nargv[argindex++] = NULL;
152
153 /* remove home directory */
154 if( rflag ) {
155 /* Check Permissions */
156 if( stat( pstruct->pw_dir, &statbuf ) ) {
157 errmsg(M_OOPS, "find status about home directory",
158 strerror(errno));
159 exit( EX_HOMEDIR );
160 }
161
162 if( check_perm( statbuf, pstruct->pw_uid, pstruct->pw_gid,
163 S_IWOTH|S_IXOTH ) != 0 ) {
164 errmsg( M_NO_PERM, logname, pstruct->pw_dir );
165 exit( EX_HOMEDIR );
166 }
167
168 if( rm_files(pstruct->pw_dir, logname) != EX_SUCCESS )
169 exit( EX_HOMEDIR );
170 }
171
172 /* now call passmgmt */
173 ret = PEX_FAILED;
174 for( tries = 3; ret != PEX_SUCCESS && tries--; ) {
175 switch( ret = call_passmgmt( nargv ) ) {
176 case PEX_SUCCESS:
177 ret = edit_group( logname, (char *)0, (int **)0, 1 );
178 if( ret != EX_SUCCESS )
179 errmsg( M_UPDATE, "deleted" );
180 break;
181
182 case PEX_BUSY:
183 break;
184
185 case PEX_HOSED_FILES:
186 errmsg( M_HOSED_FILES );
187 exit( EX_INCONSISTENT );
188 break;
189
190 case PEX_SYNTAX:
191 case PEX_BADARG:
192 /* should NEVER occur that passmgmt usage is wrong */
193 if (is_role(usertype))
194 errmsg( M_DRUSAGE );
195 else
196 errmsg( M_DUSAGE );
197 exit( EX_SYNTAX );
198 break;
199
200 case PEX_BADUID:
201 /* uid is used - shouldn't happen but print message anyway */
202 errmsg( M_UID_USED, pstruct->pw_uid );
203 exit( EX_ID_EXISTS );
204 break;
205
206 case PEX_BADNAME:
207 /* invalid loname */
208 errmsg( M_USED, logname);
209 exit( EX_NAME_EXISTS );
210 break;
211
212 default:
213 errmsg( M_UPDATE, "deleted" );
214 exit( ret );
215 break;
216 }
217 }
218 if( tries == 0 )
219 errmsg( M_UPDATE, "deleted" );
220
221 /*
222 * Now, remove this user from all project entries
223 */
224
225 rc = edit_project(logname, (char *)0, (projid_t **)0, 1);
226 if (rc != EX_SUCCESS) {
227 errmsg(M_UPDATE, "modified");
228 exit(rc);
229 }
230
231 exit( ret );
232 /*NOTREACHED*/
233 }
234