we go to LAST_ACK even if data is outstanding, so watch for window
[unix-history] / usr / src / usr.sbin / vipw / vipw.c
CommitLineData
8c5eec2f
DF
1/*
2 * Copyright (c) 1980 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 */
6
7#ifndef lint
8char copyright[] =
9"@(#) Copyright (c) 1980 Regents of the University of California.\n\
10 All rights reserved.\n";
11#endif not lint
12
4c6b79b5 13#ifndef lint
8c5eec2f
DF
14static char sccsid[] = "@(#)vipw.c 5.1 (Berkeley) %G%";
15#endif not lint
4c6b79b5
SL
16
17#include <sys/types.h>
18#include <sys/stat.h>
19#include <sys/file.h>
20
21#include <stdio.h>
22#include <errno.h>
23#include <signal.h>
24
25/*
26 * Password file editor with locking.
27 */
c6ab0749
RC
28char temp[] = "/etc/ptmp";
29char temp_pag[] = "/etc/ptmp.pag";
30char temp_dir[] = "/etc/ptmp.dir";
31char passwd[] = "/etc/passwd";
32char passwd_pag[] = "/etc/passwd.pag";
33char passwd_dir[] = "/etc/passwd.dir";
4c6b79b5
SL
34char buf[BUFSIZ];
35char *getenv();
36char *index();
37extern int errno;
38
39main(argc, argv)
40 char *argv[];
41{
42 int fd;
43 FILE *ft, *fp;
44 char *editor;
45
c6ab0749 46 signal(SIGHUP, SIG_IGN);
4c6b79b5
SL
47 signal(SIGINT, SIG_IGN);
48 signal(SIGQUIT, SIG_IGN);
4c6b79b5 49 setbuf(stderr, NULL);
b2018160 50 umask(0);
4c6b79b5
SL
51 fd = open(temp, O_WRONLY|O_CREAT|O_EXCL, 0644);
52 if (fd < 0) {
53 if (errno == EEXIST) {
54 fprintf(stderr, "vipw: password file busy\n");
55 exit(1);
56 }
57 fprintf(stderr, "vipw: "); perror(temp);
58 exit(1);
59 }
60 ft = fdopen(fd, "w");
61 if (ft == NULL) {
62 fprintf(stderr, "vipw: "); perror(temp);
63 goto bad;
64 }
65 fp = fopen(passwd, "r");
66 if (fp == NULL) {
67 fprintf(stderr, "vipw: "); perror(passwd);
68 goto bad;
69 }
70 while (fgets(buf, sizeof (buf) - 1, fp) != NULL)
71 fputs(buf, ft);
72 fclose(ft); fclose(fp);
73 editor = getenv("EDITOR");
74 if (editor == 0)
75 editor = "vi";
76 sprintf(buf, "%s %s", editor, temp);
77 if (system(buf) == 0) {
78 struct stat sbuf;
79 int ok;
80
81 /* sanity checks */
82 if (stat(temp, &sbuf) < 0) {
83 fprintf(stderr,
84 "vipw: can't stat temp file, %s unchanged\n",
85 passwd);
86 goto bad;
87 }
88 if (sbuf.st_size == 0) {
89 fprintf(stderr, "vipw: bad temp file, %s unchanged\n",
90 passwd);
91 goto bad;
92 }
93 ft = fopen(temp, "r");
94 if (ft == NULL) {
95 fprintf(stderr,
96 "vipw: can't reopen temp file, %s unchanged\n",
97 passwd);
98 goto bad;
99 }
100 ok = 0;
101 while (fgets(buf, sizeof (buf) - 1, ft) != NULL) {
102 register char *cp;
103
104 cp = index(buf, '\n');
105 if (cp == 0)
106 continue;
107 *cp = '\0';
108 cp = index(buf, ':');
109 if (cp == 0)
110 continue;
111 *cp = '\0';
112 if (strcmp(buf, "root"))
113 continue;
114 /* password */
115 cp = index(cp + 1, ':');
116 if (cp == 0)
117 break;
118 /* uid */
119 if (atoi(cp + 1) != 0)
120 break;
121 cp = index(cp + 1, ':');
122 if (cp == 0)
123 break;
124 /* gid */
125 cp = index(cp + 1, ':');
126 if (cp == 0)
127 break;
128 /* gecos */
129 cp = index(cp + 1, ':');
130 if (cp == 0)
131 break;
132 /* login directory */
76eb92c8 133 if (strncmp(++cp, "/:", 2))
4c6b79b5
SL
134 break;
135 cp += 2;
136 if (*cp && strcmp(cp, "/bin/sh") &&
137 strcmp(cp, "/bin/csh"))
138 break;
139 ok++;
140 }
141 fclose(ft);
142 if (ok) {
ae41743d
RC
143 if (makedb(temp) < 0)
144 fprintf(stderr, "vipw: mkpasswd failed\n");
145 else if (rename(temp_pag, passwd_pag) < 0)
146 fprintf(stderr, "vipw: "), perror(temp_pag);
147 else if (rename(temp_dir, passwd_dir) < 0)
148 fprintf(stderr, "vipw: "), perror(temp_dir);
149 else if (rename(temp, passwd) < 0)
4c6b79b5 150 fprintf(stderr, "vipw: "), perror("rename");
6b52f313
RC
151 else
152 exit(0);
4c6b79b5
SL
153 } else
154 fprintf(stderr,
155 "vipw: you mangled the temp file, %s unchanged\n",
156 passwd);
157 }
158bad:
c6ab0749
RC
159 unlink(temp_pag);
160 unlink(temp_dir);
4c6b79b5 161 unlink(temp);
6b52f313 162 exit(1);
4c6b79b5 163}
ae41743d
RC
164
165makedb(file)
166 char *file;
167{
168 int status, pid, w;
169
170 if ((pid = vfork()) == 0) {
171 execl("/etc/mkpasswd", "mkpasswd", file, 0);
172 _exit(127);
173 }
174 while ((w = wait(&status)) != pid && w != -1)
175 ;
176 if (w == -1 || status != 0)
177 status = -1;
178 return(status);
179}