* Copyright (c) 1988 The Regents of the University of California.
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
"@(#) Copyright (c) 1988 The Regents of the University of California.\n\
static char sccsid
[] = "@(#)passwd.c 4.35 (Berkeley) %G%";
#include <sys/resource.h>
char *fend
, *np
, *passwd
, *temp
, *tend
;
char from
[MAXPATHLEN
], to
[MAXPATHLEN
];
if (!(pw
= getpwuid(uid
))) {
fprintf(stderr
, "passwd: unknown user: uid %u\n", uid
);
if (!(pw
= getpwnam(argv
[1]))) {
fprintf(stderr
, "passwd: unknown user %s.\n", argv
[1]);
if (uid
&& uid
!= pw
->pw_uid
) {
fprintf(stderr
, "passwd: %s\n", strerror(EACCES
));
fprintf(stderr
, "usage: passwd [user]\n");
(void)signal(SIGHUP
, SIG_IGN
);
(void)signal(SIGINT
, SIG_IGN
);
(void)signal(SIGQUIT
, SIG_IGN
);
(void)signal(SIGTSTP
, SIG_IGN
);
rlim
.rlim_cur
= rlim
.rlim_max
= RLIM_INFINITY
;
(void)setrlimit(RLIMIT_CPU
, &rlim
);
(void)setrlimit(RLIMIT_FSIZE
, &rlim
);
if ((fd
= open(temp
, O_WRONLY
|O_CREAT
|O_EXCL
, 0600)) < 0) {
"passwd: password file busy -- try again later.\n");
fprintf(stderr
, "passwd: %s: %s", temp
, strerror(errno
));
if (!(temp_fp
= fdopen(fd
, "w"))) {
fprintf(stderr
, "passwd: can't write %s\n", temp
);
passwd
= _PATH_MASTERPASSWD
;
if (!freopen(passwd
, "r", stdin
)) {
fprintf(stderr
, "passwd: can't read %s\n", passwd
);
printf("Changing password for %s.\n", pw
->pw_name
);
np
= getnewpasswd(pw
, temp
);
if (!copy(pw
->pw_name
, np
, temp_fp
, pw
))
fprintf(stderr
, "passwd: can't fork");
fprintf(stderr
, "passwd: mkpasswd failed");
bad
: fprintf(stderr
, "; password unchanged.\n");
* possible race; have to rename four files, and someone could slip
* in between them. LOCK_EX and rename the ``passwd.dir'' file first
* so that getpwent(3) can't slip in; the lock should never fail and
* it's unclear what to do if it does. Rename ``ptmp'' last so that
* passwd/vipw/chpass can't slip in.
(void)setpriority(PRIO_PROCESS
, 0, -20);
fend
= strcpy(from
, temp
) + strlen(temp
);
tend
= strcpy(to
, _PATH_PASSWD
) + strlen(_PATH_PASSWD
);
if ((fd
= open(from
, O_RDONLY
, 0)) >= 0)
(void)flock(fd
, LOCK_EX
);
(void)rename(from
, _PATH_PASSWD
);
(void)rename(temp
, passwd
);
for (done
= 0; fgets(buf
, sizeof(buf
), stdin
);) {
/* skip lines that are too big */
fprintf(stderr
, "passwd: line too long.\n");
if (!(p
= index(buf
, ':'))) {
fprintf(stderr
, "passwd: corrupted entry.\n");
if (!(p
= index(++p
, ':'))) {
fprintf(stderr
, "passwd: corrupted entry.\n");
* reset change time to zero; when classes are implemented,
* go and get the "offset" value for this class and reset
fprintf(fp
, "%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s\n",
pw
->pw_name
, np
, pw
->pw_uid
, pw
->pw_gid
,
pw
->pw_class
, 0L, pw
->pw_expire
, pw
->pw_gecos
,
pw
->pw_dir
, pw
->pw_shell
);
register struct passwd
*pw
;
char buf
[10], salt
[2], *crypt(), *getpass();
if (uid
&& pw
->pw_passwd
&&
strcmp(crypt(getpass("Old password:"), pw
->pw_passwd
),
(void)printf("passwd: %s.\n", strerror(EACCES
));
p
= getpass("New password:");
(void)printf("Password unchanged.\n");
printf("Please enter a longer password.\n");
for (t
= p
; *t
&& islower(*t
); ++t
);
printf("Please don't use an all-lower case password.\nUnusual capitalization, control characters or digits are suggested.\n");
if (!strcmp(buf
, getpass("Retype new password:")))
printf("Mismatch; try again, EOF to quit.\n");
/* grab a random printable character that isn't a colon */
(void)srandom((int)time((time_t *)NULL
));
while ((salt
[0] = random() % 93 + 33) == ':');
while ((salt
[1] = random() % 93 + 33) == ':');
return(crypt(buf
, salt
));
execl(_PATH_MKPASSWD
, "mkpasswd", "-p", file
, NULL
);
while ((w
= wait(&status
)) != pid
&& w
!= -1);
return(w
== -1 || status
);