prettyness police
[unix-history] / usr / src / usr.bin / chpass / edit.c
CommitLineData
255347ad 1/*-
8964deec
KB
2 * Copyright (c) 1990, 1993
3 * The Regents of the University of California. All rights reserved.
255347ad
KB
4 *
5 * %sccs.include.redist.c%
6 */
7
8#ifndef lint
cc952d1c 9static char sccsid[] = "@(#)edit.c 8.2 (Berkeley) %G%";
255347ad
KB
10#endif /* not lint */
11
12#include <sys/param.h>
13#include <sys/stat.h>
cc952d1c
JSP
14
15#include <ctype.h>
16#include <err.h>
255347ad 17#include <errno.h>
255347ad 18#include <paths.h>
cc952d1c
JSP
19#include <pwd.h>
20#include <stdio.h>
255347ad
KB
21#include <stdlib.h>
22#include <string.h>
cc952d1c
JSP
23#include <unistd.h>
24
25#include <pw_scan.h>
26#include <pw_util.h>
27
255347ad
KB
28#include "chpass.h"
29
30extern char *tempname;
31
456319a0
KB
32void
33edit(pw)
255347ad
KB
34 struct passwd *pw;
35{
36 struct stat begin, end;
37
255347ad
KB
38 for (;;) {
39 if (stat(tempname, &begin))
40 pw_error(tempname, 1, 1);
456319a0 41 pw_edit(1);
255347ad
KB
42 if (stat(tempname, &end))
43 pw_error(tempname, 1, 1);
3148146f 44 if (begin.st_mtime == end.st_mtime) {
cc952d1c 45 warnx("no changes made");
488b1124 46 pw_error(NULL, 0, 0);
255347ad
KB
47 }
48 if (verify(pw))
49 break;
50 pw_prompt();
51 }
52}
53
54/*
55 * display --
56 * print out the file for the user to edit; strange side-effect:
57 * set conditional flag if the user gets to edit the shell.
58 */
cc952d1c 59void
255347ad
KB
60display(fd, pw)
61 int fd;
62 struct passwd *pw;
63{
255347ad 64 FILE *fp;
cc952d1c 65 char *bp, *p, *ttoa();
255347ad
KB
66
67 if (!(fp = fdopen(fd, "w")))
68 pw_error(tempname, 1, 1);
69
70 (void)fprintf(fp,
71 "#Changing user database information for %s.\n", pw->pw_name);
72 if (!uid) {
73 (void)fprintf(fp, "Login: %s\n", pw->pw_name);
74 (void)fprintf(fp, "Password: %s\n", pw->pw_passwd);
75 (void)fprintf(fp, "Uid [#]: %d\n", pw->pw_uid);
76 (void)fprintf(fp, "Gid [# or name]: %d\n", pw->pw_gid);
77 (void)fprintf(fp, "Change [month day year]: %s\n",
78 ttoa(pw->pw_change));
79 (void)fprintf(fp, "Expire [month day year]: %s\n",
80 ttoa(pw->pw_expire));
81 (void)fprintf(fp, "Class: %s\n", pw->pw_class);
82 (void)fprintf(fp, "Home directory: %s\n", pw->pw_dir);
83 (void)fprintf(fp, "Shell: %s\n",
84 *pw->pw_shell ? pw->pw_shell : _PATH_BSHELL);
85 }
86 /* Only admin can change "restricted" shells. */
87 else if (ok_shell(pw->pw_shell))
88 /*
89 * Make shell a restricted field. Ugly with a
90 * necklace, but there's not much else to do.
91 */
92 (void)fprintf(fp, "Shell: %s\n",
93 *pw->pw_shell ? pw->pw_shell : _PATH_BSHELL);
94 else
95 list[E_SHELL].restricted = 1;
96 bp = pw->pw_gecos;
97 p = strsep(&bp, ",");
98 (void)fprintf(fp, "Full Name: %s\n", p ? p : "");
99 p = strsep(&bp, ",");
100 (void)fprintf(fp, "Location: %s\n", p ? p : "");
101 p = strsep(&bp, ",");
102 (void)fprintf(fp, "Office Phone: %s\n", p ? p : "");
103 p = strsep(&bp, ",");
104 (void)fprintf(fp, "Home Phone: %s\n", p ? p : "");
105
456319a0 106 (void)fchown(fd, getuid(), getgid());
255347ad
KB
107 (void)fclose(fp);
108}
109
cc952d1c 110int
255347ad
KB
111verify(pw)
112 struct passwd *pw;
113{
cc952d1c
JSP
114 ENTRY *ep;
115 char *p;
3148146f 116 struct stat sb;
255347ad
KB
117 FILE *fp;
118 int len;
119 char buf[LINE_MAX];
120
121 if (!(fp = fopen(tempname, "r")))
122 pw_error(tempname, 1, 1);
3148146f
KB
123 if (fstat(fileno(fp), &sb))
124 pw_error(tempname, 1, 1);
125 if (sb.st_size == 0) {
cc952d1c 126 warnx("corrupted temporary file");
3148146f
KB
127 goto bad;
128 }
255347ad
KB
129 while (fgets(buf, sizeof(buf), fp)) {
130 if (!buf[0] || buf[0] == '#')
131 continue;
cc952d1c
JSP
132 if (!(p = strchr(buf, '\n'))) {
133 warnx("line too long");
255347ad
KB
134 goto bad;
135 }
136 *p = '\0';
137 for (ep = list;; ++ep) {
138 if (!ep->prompt) {
cc952d1c 139 warnx("unrecognized field");
255347ad
KB
140 goto bad;
141 }
142 if (!strncasecmp(buf, ep->prompt, ep->len)) {
143 if (ep->restricted && uid) {
cc952d1c
JSP
144 warnx(
145 "you may not change the %s field",
146 ep->prompt);
255347ad
KB
147 goto bad;
148 }
cc952d1c
JSP
149 if (!(p = strchr(buf, ':'))) {
150 warnx("line corrupted");
255347ad
KB
151 goto bad;
152 }
153 while (isspace(*++p));
154 if (ep->except && strpbrk(p, ep->except)) {
cc952d1c
JSP
155 warnx(
156 "illegal character in the \"%s\" field",
255347ad
KB
157 ep->prompt);
158 goto bad;
159 }
160 if ((ep->func)(p, pw, ep)) {
161bad: (void)fclose(fp);
cc952d1c 162 return (0);
255347ad
KB
163 }
164 break;
165 }
166 }
167 }
168 (void)fclose(fp);
169
170 /* Build the gecos field. */
171 len = strlen(list[E_NAME].save) + strlen(list[E_BPHONE].save) +
172 strlen(list[E_HPHONE].save) + strlen(list[E_LOCATE].save) + 4;
cc952d1c
JSP
173 if (!(p = malloc(len)))
174 err(1, NULL);
255347ad
KB
175 (void)sprintf(pw->pw_gecos = p, "%s,%s,%s,%s", list[E_NAME].save,
176 list[E_LOCATE].save, list[E_BPHONE].save, list[E_HPHONE].save);
177
178 if (snprintf(buf, sizeof(buf),
179 "%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s",
180 pw->pw_name, pw->pw_passwd, pw->pw_uid, pw->pw_gid, pw->pw_class,
181 pw->pw_change, pw->pw_expire, pw->pw_gecos, pw->pw_dir,
182 pw->pw_shell) >= sizeof(buf)) {
cc952d1c
JSP
183 warnx("entries too long");
184 return (0);
255347ad 185 }
cc952d1c 186 return (pw_scan(buf, pw));
255347ad 187}