* Copyright (c) 1987 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 MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
"@(#) Copyright (c) 1987 Regents of the University of California.\n\
static char sccsid
[] = "@(#)vipw.c 5.11 (Berkeley) %G%";
#include <sys/resource.h>
register int n
, fd_passwd
, fd
;
char buf
[8*1024], from
[MAXPATHLEN
], to
[MAXPATHLEN
];
(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_RDWR
|O_CREAT
|O_EXCL
, 0600)) < 0) {
(void)fprintf(stderr
, "vipw: password file busy.\n");
"vipw: %s: %s\n", temp
, strerror(errno
));
passwd
= _PATH_MASTERPASSWD
;
if ((fd_passwd
= open(passwd
, O_RDONLY
, 0)) < 0) {
(void)fprintf(stderr
, "vipw: %s: %s\n", passwd
,
while ((n
= read(fd_passwd
, buf
, sizeof(buf
))) > 0)
if (write(fd
, buf
, n
) != n
)
if (n
== -1 || close(fd_passwd
)) {
syserr
: (void)fprintf(stderr
, "vipw: %s: %s; ",
passwd
, strerror(errno
));
(void)fprintf(stderr
, "vipw: edit failed; ");
* close and re-open the file each time we edit it; some
* editors create a new physical file on each edit session.
if (!(tfp
= fopen(temp
, "r"))) {
(void)fprintf(stderr
, "vipw: %s: %s; ",
(void)fstat(fileno(tfp
), &s2
);
if (s1
.st_mtime
== s2
.st_mtime
) {
(void)fprintf(stderr
, "vipw: no changes made; ");
(void)fstat(fileno(tfp
), &s1
);
(void)fprintf(stderr
, "vipw: can't fork; ");
(void)fprintf(stderr
, "vipw: mkpasswd failed; ");
* 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
);
char buf
[1024], *getusershell();
for (lcnt
= 1; fgets(buf
, sizeof(buf
), tfp
); ++lcnt
) {
/* skip lines that are too big */
if (!(p
= index(buf
, '\n'))) {
(void)fprintf(stderr
, "vipw: line too long");
if (!(p
= strsep(buf
, ":"))) /* login */
root
= !strcmp(p
, "root");
(void)strsep((char *)NULL
, ":"); /* passwd */
if (!(p
= strsep((char *)NULL
, ":"))) /* uid */
(void)fprintf(stderr
, "vipw: root uid should be 0");
(void)fprintf(stderr
, "vipw: %s > max uid value (%d)",
if (!(p
= strsep((char *)NULL
, ":"))) /* gid */
(void)fprintf(stderr
, "vipw: %s > max gid value (%d)",
(void)strsep((char *)NULL
, ":"); /* class */
(void)strsep((char *)NULL
, ":"); /* change */
(void)strsep((char *)NULL
, ":"); /* expire */
(void)strsep((char *)NULL
, ":"); /* gecos */
(void)strsep((char *)NULL
, ":"); /* directory */
if (!(p
= strsep((char *)NULL
, ":"))) /* shell */
if (root
&& *p
) /* empty == /bin/sh */
if (!(sh
= getusershell())) {
"vipw: warning, unknown root shell.\n");
if (p
= strsep((char *)NULL
, ":")) { /* too many */
(void)fprintf(stderr
, "got {%s}\n", p
);
general
: (void)fprintf(stderr
, "vipw: corrupted entry");
bad
: (void)fprintf(stderr
, "; line #%d.\n", lcnt
);
execl(_PATH_MKPASSWD
, "mkpasswd", "-p", file
, NULL
);
while ((w
= wait(&status
)) != pid
&& w
!= -1);
return(w
== -1 || status
);
char *p
, *editor
, *getenv(), *strerror();
if (editor
= getenv("EDITOR")) {
if (p
= rindex(editor
, '/'))
execlp(editor
, p
, temp
, NULL
);
(void)fprintf(stderr
, "vipw: %s: %s\n", editor
,
while ((w
= wait(&status
)) != pid
&& w
!= -1);
return(w
== -1 || status
);
(void)printf("re-edit the password file? [y]: ");
if (c
!= EOF
&& c
!= (int)'\n')
while (getchar() != (int)'\n');
(void)fprintf(stderr
, "%s unchanged.\n", passwd
);