]>
git.saurik.com Git - apple/system_cmds.git/blob - passwd.tproj/file_passwd.c
a522730dc36928a8e636a4fc850256a661d39713
2 * Copyright (c) 1999-2010 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
39 #define _PASSWD_FILE "/etc/master.passwd"
40 #define _COMPAT_FILE "/etc/passwd"
41 #define _PASSWD_FIELDS 10
44 void getpasswd(char *, int, int, int, int, char *, char **, char**, char **);
46 static struct passwd
*
47 parse_user(char *line
, size_t len
)
49 static struct passwd pw
;
51 char *tokens
[_PASSWD_FIELDS
];
61 memset(&pw
, 0, sizeof(pw
));
63 if (line
== NULL
) return NULL
;
65 memset(&tokens
, 0, sizeof(char *) * _PASSWD_FIELDS
);
67 for (i
= 0, j
= 0; i
< len
&& j
< _PASSWD_FIELDS
; ++i
) {
69 if (!isspace(c
) && c
!= '#') {
72 if (!comment
&& token
== NULL
) {
75 } else if (token
&& (c
== ':' || c
== '\n')) {
76 // end the current token
77 // special case for empty token
78 while (token
[0] == ':' && token
< &line
[i
]) {
79 tokens
[j
++] = strdup("");
82 tokens
[j
++] = strndup(token
, &line
[i
] - token
);
87 if (comment
|| j
!= _PASSWD_FIELDS
) return NULL
;
90 pw
.pw_name
= tokens
[j
++];
91 pw
.pw_passwd
= tokens
[j
++];
92 pw
.pw_uid
= atoi(tokens
[j
]);
94 pw
.pw_gid
= atoi(tokens
[j
]);
96 pw
.pw_class
= tokens
[j
++];
97 pw
.pw_change
= atoi(tokens
[j
]);
99 pw
.pw_expire
= atoi(tokens
[j
]);
101 pw
.pw_gecos
= tokens
[j
++];
102 pw
.pw_dir
= tokens
[j
++];
103 pw
.pw_shell
= tokens
[j
++];
108 static struct passwd
*
109 find_user(FILE *fp
, char *uname
)
116 while ((line
= fgetln(fp
, &len
)) != NULL
) {
117 struct passwd
*pw
= parse_user(line
, len
);
118 if (pw
&& strcmp(uname
, pw
->pw_name
) == 0) {
126 rewrite_file(char *path
, FILE *fp
, struct passwd
*newpw
)
132 char *tempname
= NULL
; // temporary master.passwd file
134 asprintf(&tempname
, "%s.XXXXXX", path
);
136 fd
= mkstemp(tempname
);
138 err(EXIT_FAILURE
, "%s", tempname
);
140 tfp
= fdopen(fd
, "w+");
141 if (tfp
== NULL
|| fchmod(fd
, S_IRUSR
| S_IWUSR
) != 0) {
145 err(EXIT_FAILURE
, "%s", tempname
);
148 while ((line
= fgetln(fp
, &len
)) != NULL
) {
149 struct passwd
*pw
= parse_user(line
, len
);
151 // if this is not the entry we're looking for or if parsing
152 // failed (likely a comment) then print the entry as is.
153 if (pw
== NULL
|| strcmp(newpw
->pw_name
, pw
->pw_name
) != 0) {
154 fwrite(line
, sizeof(char), len
, tfp
);
156 fprintf(tfp
, "%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s\n",
170 // Move the temporary file into place.
171 if (fclose(tfp
) != 0 || rename(tempname
, path
) != 0) {
175 err(EXIT_FAILURE
, "%s", tempname
);
182 file_passwd(char *uname
, char *locn
)
192 fname
= _PASSWD_FILE
;
193 if (locn
!= NULL
) fname
= locn
;
195 fd
= open(fname
, O_RDONLY
| O_EXLOCK
);
197 err(EXIT_FAILURE
, "%s", fname
);
200 fp
= fdopen(fd
, "r");
202 err(EXIT_FAILURE
, "%s", fname
);
205 pw
= find_user(fp
, uname
);
207 errx(EXIT_FAILURE
, "user %s not found in %s", uname
, fname
);
211 if (uid
!= 0 && uid
!= pw
->pw_uid
) {
213 err(EXIT_FAILURE
, "%s", uname
);
217 getpasswd(uname
, (uid
== 0), 5, 0, 0, pw
->pw_passwd
, &ne
, &oc
, &nc
);
219 newpw
.pw_name
= strdup(pw
->pw_name
);
220 newpw
.pw_passwd
= strdup(ne
);
221 newpw
.pw_uid
= pw
->pw_uid
;
222 newpw
.pw_gid
= pw
->pw_gid
;
223 newpw
.pw_class
= strdup(pw
->pw_class
);
224 newpw
.pw_change
= pw
->pw_change
;
225 newpw
.pw_expire
= pw
->pw_expire
;
226 newpw
.pw_gecos
= strdup(pw
->pw_gecos
);
227 newpw
.pw_dir
= strdup(pw
->pw_dir
);
228 newpw
.pw_shell
= strdup(pw
->pw_shell
);
232 rewrite_file(fname
, fp
, &newpw
);