]>
git.ipfire.org Git - thirdparty/util-linux.git/blob - login-utils/setpwnam.c
2 * setpwnam.c -- edit an entry in a password database.
4 * (c) 1994 Salvatore Valente <svalente@mit.edu>
5 * This file is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
10 * Edited 11/10/96 (DD/MM/YY ;-) by Nicolai Langfeldt (janl@math.uio.no)
11 * to read /etc/passwd directly so that passwd, chsh and chfn can work on
12 * machines that run NIS (previously YP). Changes will not be made to
13 * usernames starting with +.
15 * This file is distributed with no warranty.
18 * 1) get a struct passwd * from getpwnam().
19 * You should assume a struct passwd has an infinite number of fields, so
20 * you should not try to create one from scratch.
21 * 2) edit the fields you want to edit.
22 * 3) call setpwnam() with the edited struct passwd.
24 * A _normal user_ program should never directly manipulate etc/passwd but
25 * /use getpwnam() and (family, as well as) setpwnam().
27 * But, setpwnam was made to _edit_ the password file. For use by chfn,
28 * chsh and passwd. _I_ _HAVE_ to read and write /etc/passwd directly. Let
29 * those who say nay be forever silent and think about how getpwnam (and
30 * family) works on a machine running YP.
32 * Added checks for failure of malloc() and removed error reporting to
33 * stderr, this is a library function and should not print on the screen,
34 * but return appropriate error codes.
35 * 27-Jan-97 - poe@daimi.aau.dk
37 * Thanks to "two guys named Ian".
41 * $Date: 1997/06/23 08:26:29 $
56 #include <sys/resource.h>
58 #include <sys/types.h>
62 #include "fileutils.h"
63 #include "closestream.h"
66 static void pw_init(void);
70 * takes a struct passwd in which every field is filled in and valid.
71 * If the given username exists in the passwd file, the entry is
72 * replaced with the given entry.
74 int setpwnam(struct passwd
*pwd
, const char *prefix
)
76 FILE *fp
= NULL
, *pwf
= NULL
;
87 if ((fp
= xfmkstemp(&tmpname
, "/etc", prefix
)) == NULL
)
90 /* ptmp should be owned by root.root or root.wheel */
91 if (fchown(fileno(fp
), (uid_t
) 0, (gid_t
) 0) < 0)
94 /* acquire exclusive lock */
97 pwf
= fopen(PASSWD_FILE
, "r");
101 namelen
= strlen(pwd
->pw_name
);
103 linebuf
= malloc(buflen
);
107 /* parse the passwd file */
110 /* Do you wonder why I don't use getpwent? Read comments at top of
112 while (fgets(linebuf
, buflen
, pwf
) != NULL
) {
113 contlen
= strlen(linebuf
);
114 while (linebuf
[contlen
- 1] != '\n' && !feof(pwf
)) {
116 /* Extend input buffer if it failed getting the whole line,
117 * so now we double the buffer size */
119 tmp
= realloc(linebuf
, buflen
);
123 /* And fill the rest of the buffer */
124 if (fgets(&linebuf
[contlen
], buflen
/ 2, pwf
) == NULL
)
126 contlen
= strlen(linebuf
);
127 /* That was a lot of work for nothing. Gimme perl! */
130 /* Is this the username we were sent to change? */
131 if (!found
&& linebuf
[namelen
] == ':' &&
132 !strncmp(linebuf
, pwd
->pw_name
, namelen
)) {
133 /* Yes! So go forth in the name of the Lord and
135 if (putpwent(pwd
, fp
) < 0)
140 /* Nothing in particular happened, copy input to output */
144 /* xfmkstemp is too restrictive by default for passwd file */
145 if (fchmod(fileno(fp
), 0644) < 0)
147 rc
= close_stream(fp
);
152 fclose(pwf
); /* I don't think I want to know if this failed */
156 errno
= ENOENT
; /* give me something better */
160 /* we don't care if we can't remove the backup file */
161 unlink(PASSWD_FILE
".OLD");
162 /* we don't care if we can't create the backup file */
163 ignore_result(link(PASSWD_FILE
, PASSWD_FILE
".OLD"));
164 /* we DO care if we can't rename to the passwd file */
165 if (rename(tmpname
, PASSWD_FILE
) < 0)
167 /* finally: success */
187 /* Set up the limits so that we're not foiled */
188 static void pw_init(void)
192 /* Unlimited resource limits. */
193 rlim
.rlim_cur
= rlim
.rlim_max
= RLIM_INFINITY
;
194 setrlimit(RLIMIT_CPU
, &rlim
);
195 setrlimit(RLIMIT_FSIZE
, &rlim
);
196 setrlimit(RLIMIT_STACK
, &rlim
);
197 setrlimit(RLIMIT_DATA
, &rlim
);
198 setrlimit(RLIMIT_RSS
, &rlim
);
201 /* Don't drop core (not really necessary, but GP's). */
202 rlim
.rlim_cur
= rlim
.rlim_max
= 0;
203 setrlimit(RLIMIT_CORE
, &rlim
);
206 /* Turn off signals. */
207 signal(SIGALRM
, SIG_IGN
);
208 signal(SIGHUP
, SIG_IGN
);
209 signal(SIGINT
, SIG_IGN
);
210 signal(SIGPIPE
, SIG_IGN
);
211 signal(SIGQUIT
, SIG_IGN
);
212 signal(SIGTERM
, SIG_IGN
);
213 signal(SIGTSTP
, SIG_IGN
);
214 signal(SIGTTOU
, SIG_IGN
);
216 /* Create with exact permissions. */