minor cleanups for cray
[unix-history] / usr / src / usr.sbin / vipw / vipw.c
CommitLineData
8c5eec2f 1/*
e50bab02 2 * Copyright (c) 1987 Regents of the University of California.
3dd425ca
KB
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
b8c620d6
KB
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
8c5eec2f
DF
16 */
17
18#ifndef lint
19char copyright[] =
e50bab02 20"@(#) Copyright (c) 1987 Regents of the University of California.\n\
8c5eec2f 21 All rights reserved.\n";
3dd425ca 22#endif /* not lint */
8c5eec2f 23
4c6b79b5 24#ifndef lint
b8c620d6 25static char sccsid[] = "@(#)vipw.c 5.5 (Berkeley) %G%";
3dd425ca 26#endif /* not lint */
4c6b79b5 27
f79ee00c 28#include <machine/machparam.h>
4c6b79b5
SL
29#include <sys/types.h>
30#include <sys/stat.h>
f79ee00c 31#include <sys/signal.h>
4c6b79b5 32#include <sys/file.h>
4c6b79b5
SL
33#include <stdio.h>
34#include <errno.h>
4c6b79b5
SL
35
36/*
37 * Password file editor with locking.
38 */
f79ee00c 39static char *passwd = "/etc/passwd", buf[BUFSIZ];
e50bab02
KB
40
41main()
4c6b79b5 42{
f79ee00c
KB
43 register int n, fd_passwd, fd_temp;
44 static char *temp = "/etc/ptmp";
45 struct stat s1, s2;
3dd425ca 46 char *editor, *getenv();
e50bab02
KB
47
48 (void)signal(SIGHUP, SIG_IGN);
49 (void)signal(SIGINT, SIG_IGN);
50 (void)signal(SIGQUIT, SIG_IGN);
51
52 setbuf(stderr, (char *)NULL);
f79ee00c 53 (void)umask(0);
e50bab02
KB
54
55 if ((fd_passwd = open(passwd, O_RDONLY, 0)) < 0) {
f79ee00c 56 fputs("vipw: ", stderr);
e50bab02
KB
57 perror(passwd);
58 exit(1);
59 }
60 if ((fd_temp = open(temp, O_WRONLY|O_CREAT|O_EXCL, 0644)) < 0) {
61 extern int errno;
62
4c6b79b5 63 if (errno == EEXIST) {
f79ee00c 64 fputs("vipw: password file busy.\n", stderr);
4c6b79b5
SL
65 exit(1);
66 }
f79ee00c 67 fputs("vipw: ", stderr);
e50bab02 68 perror(temp);
4c6b79b5
SL
69 exit(1);
70 }
e50bab02
KB
71 while ((n = read(fd_passwd, buf, sizeof(buf))) > 0)
72 if (write(fd_temp, buf, n) != n) {
73 perror("vipw: write");
74 goto bad;
75 }
76 if (n == -1) {
77 perror("vipw: read");
78 goto bad;
79 }
80 (void)close(fd_passwd);
81 if (fsync(fd_temp)) {
82 perror("vipw: fsync");
4c6b79b5
SL
83 goto bad;
84 }
e50bab02
KB
85 if (fstat(fd_temp, &s1)) {
86 perror("vipw: fstat");
4c6b79b5
SL
87 goto bad;
88 }
e50bab02
KB
89 (void)close(fd_temp);
90
91 if (!(editor = getenv("EDITOR")))
4c6b79b5 92 editor = "vi";
e50bab02
KB
93 (void)sprintf(buf, "%s %s", editor, temp);
94 if (system(buf)) {
95 perror("vipw: system");
96 goto bad;
97 }
98
99 if (!freopen(temp, "r", stdin)) {
f79ee00c 100 fprintf(stderr, "vipw: can't reopen temp file; %s unchanged.\n", passwd);
e50bab02
KB
101 goto bad;
102 }
103 if (fstat(fileno(stdin), &s2)) {
f79ee00c 104 fprintf(stderr, "vipw: can't stat temp file; %s unchanged.\n", passwd);
e50bab02
KB
105 goto bad;
106 }
107 if (s1.st_mtime == s2.st_mtime) {
f79ee00c 108 fprintf(stderr, "vipw: %s unchanged.\n", passwd);
e50bab02
KB
109 goto bad;
110 }
111 if (!s2.st_size) {
f79ee00c 112 fprintf(stderr, "vipw: bad temp file; %s unchanged.\n", passwd);
e50bab02
KB
113 goto bad;
114 }
f79ee00c 115 if (check()) {
e50bab02
KB
116 static char *temp_pag = "/etc/ptmp.pag",
117 *temp_dir = "/etc/ptmp.dir",
118 *passwd_pag = "/etc/passwd.pag",
119 *passwd_dir = "/etc/passwd.dir";
120
121 if (makedb(temp) < 0)
122 fputs("vipw: mkpasswd failed.\n", stderr);
123 else if (rename(temp_pag, passwd_pag) < 0) {
124 fprintf(stderr, "vipw: ");
125 perror(temp_pag);
4c6b79b5 126 }
e50bab02
KB
127 else if (rename(temp_dir, passwd_dir) < 0) {
128 fprintf(stderr, "vipw: ");
129 perror(temp_dir);
4c6b79b5 130 }
e50bab02
KB
131 else if (rename(temp, passwd) < 0) {
132 fprintf(stderr, "vipw: ");
133 perror("rename");
4c6b79b5 134 }
e50bab02
KB
135 else
136 exit(0);
137 (void)unlink(temp_pag);
138 (void)unlink(temp_dir);
4c6b79b5 139 }
e50bab02 140bad: (void)unlink(temp);
6b52f313 141 exit(1);
4c6b79b5 142}
ae41743d 143
f79ee00c 144#define CHN ((char *)NULL)
e50bab02 145static
f79ee00c 146check()
e50bab02 147{
f79ee00c
KB
148 register char *cp, *sh;
149 register long id;
150 register int root;
151 long atol();
152 char *token(), *getusershell();
153
154 for (root = 0; gets(buf); root = 0) {
155 if (!*buf) {
156 fputs("vipw: empty line.\n", stderr);
e50bab02 157 continue;
f79ee00c
KB
158 }
159 if (!(cp = token(buf)) || !*cp) /* login */
160 goto bad;
161 if (!strcmp(cp, "root"))
162 root = 1;
163 (void)token(CHN); /* passwd */
164 if (!(cp = token(CHN)) || !*cp) /* uid */
165 goto bad;
166 id = atol(cp);
167 if (root && id) {
168 fprintf(stderr, "vipw: root uid should be 0; %s unchanged.\n", passwd);
169 return(0);
170 }
171 if (id > USHRT_MAX) {
172 fprintf(stderr, "vipw: %s > max uid value (%u); %s unchanged.\n", cp, USHRT_MAX, passwd);
173 return(0);
174 }
175 if (!(cp = token(CHN)) || !*cp) /* gid */
176 goto bad;
177 id = atol(cp);
178 if (id > USHRT_MAX) {
179 fprintf(stderr, "vipw: %s > max gid value (%u); %s unchanged.\n", cp, USHRT_MAX, passwd);
180 return(0);
181 }
182 (void)token(CHN); /* gcos */
183 if (!token(CHN)) /* home directory */
184 goto bad;
185 if (!(cp = token(CHN))) /* shell */
186 goto bad;
187 if (root && *cp) /* empty == /bin/sh */
188 for (;;)
189 if (!(sh = getusershell())) {
190 fprintf(stderr, "vipw: illegal shell (%s) for root; %s unchanged.\n", cp, passwd);
191 return(0);
192 }
193 else if (!strcmp(cp, sh))
194 break;
195 if (token(CHN)) { /* too many fields */
196bad: fprintf(stderr, "vipw: corrupted entry; %s unchanged.\n", passwd);
197 return(0);
198 }
e50bab02 199 }
f79ee00c 200 return(1);
e50bab02
KB
201}
202
203static
ae41743d 204makedb(file)
f79ee00c 205 char *file;
ae41743d 206{
f79ee00c 207 int status, pid, w;
ae41743d 208
e50bab02 209 if (!(pid = vfork())) {
ae41743d
RC
210 execl("/etc/mkpasswd", "mkpasswd", file, 0);
211 _exit(127);
212 }
e50bab02
KB
213 while ((w = wait(&status)) != pid && w != -1);
214 if (w == -1 || status)
215 return(-1);
216 return(0);
ae41743d 217}
f79ee00c
KB
218
219static char *
220token(bfr)
221 char *bfr;
222{
223 static char *cp;
224 char *start;
225
226 if (bfr) /* re-init string */
227 cp = bfr;
228 else if (!cp) /* check if hit EOS last time */
229 return(CHN);
230 else if (!bfr) /* start at next char after ':' */
231 ++cp;
232 for (start = cp;; ++cp)
233 if (!*cp) { /* found EOS; mark it for next time */
234 cp = CHN;
235 break;
236 }
237 else if (*cp == ':') { /* found ':'; end token */
238 *cp = '\0';
239 break;
240 }
241 return(start); /* return token */
242}