]>
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 */
108 /* Do you wonder why I don't use getpwent? Read comments at top of
110 while (fgets(linebuf
, buflen
, pwf
) != NULL
) {
111 contlen
= strlen(linebuf
);
112 while (linebuf
[contlen
- 1] != '\n' && !feof(pwf
)) {
114 /* Extend input buffer if it failed getting the whole line,
115 * so now we double the buffer size */
117 tmp
= realloc(linebuf
, buflen
);
121 /* And fill the rest of the buffer */
122 if (fgets(&linebuf
[contlen
], buflen
/ 2, pwf
) == NULL
)
124 contlen
= strlen(linebuf
);
125 /* That was a lot of work for nothing. Gimme perl! */
128 /* Is this the username we were sent to change? */
129 if (!found
&& linebuf
[namelen
] == ':' &&
130 !strncmp(linebuf
, pwd
->pw_name
, namelen
)) {
131 /* Yes! So go forth in the name of the Lord and
133 if (putpwent(pwd
, fp
) < 0)
138 /* Nothing in particular happened, copy input to output */
142 /* xfmkstemp is too restrictive by default for passwd file */
143 if (fchmod(fileno(fp
), 0644) < 0)
145 rc
= close_stream(fp
);
150 fclose(pwf
); /* I don't think I want to know if this failed */
154 errno
= ENOENT
; /* give me something better */
158 /* we don't care if we can't remove the backup file */
159 unlink(PASSWD_FILE
".OLD");
160 /* we don't care if we can't create the backup file */
161 ignore_result(link(PASSWD_FILE
, PASSWD_FILE
".OLD"));
162 /* we DO care if we can't rename to the passwd file */
163 if (rename(tmpname
, PASSWD_FILE
) < 0)
165 /* finally: success */
185 /* Set up the limits so that we're not foiled */
186 static void pw_init(void)
190 /* Unlimited resource limits. */
191 rlim
.rlim_cur
= rlim
.rlim_max
= RLIM_INFINITY
;
192 setrlimit(RLIMIT_CPU
, &rlim
);
193 setrlimit(RLIMIT_FSIZE
, &rlim
);
194 setrlimit(RLIMIT_STACK
, &rlim
);
195 setrlimit(RLIMIT_DATA
, &rlim
);
196 setrlimit(RLIMIT_RSS
, &rlim
);
199 /* Don't drop core (not really necessary, but GP's). */
200 rlim
.rlim_cur
= rlim
.rlim_max
= 0;
201 setrlimit(RLIMIT_CORE
, &rlim
);
204 /* Turn off signals. */
205 signal(SIGALRM
, SIG_IGN
);
206 signal(SIGHUP
, SIG_IGN
);
207 signal(SIGINT
, SIG_IGN
);
208 signal(SIGPIPE
, SIG_IGN
);
209 signal(SIGQUIT
, SIG_IGN
);
210 signal(SIGTERM
, SIG_IGN
);
211 signal(SIGTSTP
, SIG_IGN
);
212 signal(SIGTTOU
, SIG_IGN
);
214 /* Create with exact permissions. */