]>
git.ipfire.org Git - thirdparty/util-linux.git/blob - login-utils/setpwnam.c
3 * edit an entry in a password database.
5 * (c) 1994 Salvatore Valente <svalente@mit.edu>
6 * This file is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) any later version.
11 * Edited 11/10/96 (DD/MM/YY ;-) by Nicolai Langfeldt (janl@math.uio.no)
12 * to read /etc/passwd directly so that passwd, chsh and chfn can work
13 * on machines that run NIS (né YP). Changes will not be made to
14 * usernames starting with +.
16 * This file is distributed with no warranty.
19 * 1) get a struct passwd * from getpwnam().
20 * You should assume a struct passwd has an infinite number of fields,
21 * so you should not try to create one from scratch.
22 * 2) edit the fields you want to edit.
23 * 3) call setpwnam() with the edited struct passwd.
25 * A _normal user_ program should never directly manipulate
26 * /etc/passwd but use getpwnam() and (family, as well as)
29 * But, setpwnam was made to _edit_ the password file. For use by
30 * chfn, chsh and passwd. _I_ _HAVE_ to read and write /etc/passwd
31 * directly. Let those who say nay be forever silent and think about
32 * how getpwnam (and family) works on a machine running YP.
34 * Added checks for failure of malloc() and removed error reporting
35 * to stderr, this is a library function and should not print on the
36 * screen, but return appropriate error codes.
37 * 27-Jan-97 - poe@daimi.aau.dk
39 * Thanks to "two guys named Ian".
43 * $Date: 1997/06/23 08:26:29 $
49 /* because I use getpwent(), putpwent(), etc... */
52 #include <sys/types.h>
61 #include <sys/resource.h>
72 static void pw_init(void);
76 * takes a struct passwd in which every field is filled in and valid.
77 * If the given username exists in the passwd file, the entry is
78 * replaced with the given entry.
81 setpwnam (struct passwd
*pwd
)
83 FILE *fp
= NULL
, *pwf
= NULL
;
84 int x
, save_errno
, fd
, ret
;
90 char *linebuf
= malloc(buflen
);
92 if (!linebuf
) return -1;
94 oldumask
= umask(0); /* Create with exact permissions */
99 for (x
= 0; x
< 3; x
++) {
101 fd
= open(PTMPTMP_FILE
, O_WRONLY
|O_CREAT
, 0644);
106 ret
= link(PTMPTMP_FILE
, PTMP_FILE
);
107 unlink(PTMPTMP_FILE
);
114 if (ret
== -1) return -1;
116 /* ptmp should be owned by root.root or root.wheel */
117 if (chown(PTMP_FILE
, (uid_t
) 0, (gid_t
) 0) < 0) return -1;
119 /* open ptmp for writing and passwd for reading */
120 fp
= fdopen(fd
, "w");
123 pwf
= fopen(PASSWD_FILE
, "r");
126 namelen
= strlen(pwd
->pw_name
);
128 /* parse the passwd file */
130 /* Do you wonder why I don't use getpwent? Read comments at top of file */
131 while (fgets(linebuf
, buflen
, pwf
) != NULL
) {
132 contlen
= strlen(linebuf
);
133 while (linebuf
[contlen
-1] != '\n' && !feof(pwf
)) {
134 /* Extend input buffer if it failed getting the whole line */
136 /* So now we double the buffer size */
139 linebuf
= realloc(linebuf
, buflen
);
140 if (linebuf
== NULL
) goto fail
;
142 /* And fill the rest of the buffer */
143 if (fgets(&linebuf
[contlen
], buflen
/2, pwf
) == NULL
) break;
144 contlen
= strlen(linebuf
);
146 /* That was a lot of work for nothing. Gimme perl! */
149 /* Is this the username we were sent to change? */
150 if (!found
&& linebuf
[namelen
] == ':' &&
151 !strncmp(linebuf
, pwd
->pw_name
, namelen
)) {
152 /* Yes! So go forth in the name of the Lord and change it! */
153 if (putpwent(pwd
, fp
) < 0) goto fail
;
157 /* Nothing in particular happened, copy input to output */
161 if (fclose(fp
) < 0) goto fail
;
165 fclose (pwf
); /* I don't think I want to know if this failed */
169 errno
= ENOENT
; /* give me something better */
173 /* we don't care if we can't remove the backup file */
174 unlink(PASSWD_FILE
".OLD");
175 /* we don't care if we can't create the backup file */
176 link(PASSWD_FILE
, PASSWD_FILE
".OLD");
177 /* we DO care if we can't rename to the passwd file */
178 if(rename(PTMP_FILE
, PASSWD_FILE
) < 0)
180 /* finally: success */
185 if (fp
!= NULL
) fclose (fp
);
186 if (pwf
!= NULL
) fclose(pwf
);
187 if (fd
>= 0) close (fd
);
188 if (linebuf
!= NULL
) free(linebuf
);
194 /* Set up the limits so that we're not foiled */
201 /* Unlimited resource limits. */
202 rlim
.rlim_cur
= rlim
.rlim_max
= RLIM_INFINITY
;
203 setrlimit(RLIMIT_CPU
, &rlim
);
204 setrlimit(RLIMIT_FSIZE
, &rlim
);
205 setrlimit(RLIMIT_STACK
, &rlim
);
206 setrlimit(RLIMIT_DATA
, &rlim
);
207 setrlimit(RLIMIT_RSS
, &rlim
);
210 /* Don't drop core (not really necessary, but GP's). */
211 rlim
.rlim_cur
= rlim
.rlim_max
= 0;
212 setrlimit(RLIMIT_CORE
, &rlim
);
215 /* Turn off signals. */
216 signal(SIGALRM
, SIG_IGN
);
217 signal(SIGHUP
, SIG_IGN
);
218 signal(SIGINT
, SIG_IGN
);
219 signal(SIGPIPE
, SIG_IGN
);
220 signal(SIGQUIT
, SIG_IGN
);
221 signal(SIGTERM
, SIG_IGN
);
222 signal(SIGTSTP
, SIG_IGN
);
223 signal(SIGTTOU
, SIG_IGN
);
225 /* Create with exact permissions. */