prettyness police
[unix-history] / usr / src / usr.bin / chpass / chpass.c
CommitLineData
59f1a2c1 1/*-
8964deec
KB
2 * Copyright (c) 1988, 1993
3 * The Regents of the University of California. All rights reserved.
8b35ab41 4 *
59f1a2c1 5 * %sccs.include.redist.c%
8b35ab41
KB
6 */
7
8#ifndef lint
8964deec
KB
9static char copyright[] =
10"@(#) Copyright (c) 1988, 1993\n\
11 The Regents of the University of California. All rights reserved.\n";
8b35ab41
KB
12#endif /* not lint */
13
14#ifndef lint
cc952d1c 15static char sccsid[] = "@(#)chpass.c 8.2 (Berkeley) %G%";
8b35ab41
KB
16#endif /* not lint */
17
18#include <sys/param.h>
8b35ab41
KB
19#include <sys/stat.h>
20#include <sys/signal.h>
21#include <sys/time.h>
22#include <sys/resource.h>
cc952d1c
JSP
23
24#include <ctype.h>
25#include <err.h>
26#include <errno.h>
bc3d7b01 27#include <fcntl.h>
b7eb8299 28#include <pwd.h>
8b35ab41 29#include <stdio.h>
cc952d1c 30#include <stdlib.h>
59f1a2c1 31#include <string.h>
cc952d1c
JSP
32#include <unistd.h>
33
34#include <pw_scan.h>
35#include <pw_util.h>
36
435e8dff
KB
37#include "chpass.h"
38#include "pathnames.h"
8b35ab41 39
bc3d7b01
KB
40char *progname = "chpass";
41char *tempname;
b7eb8299 42uid_t uid;
8b35ab41 43
cc952d1c
JSP
44void baduser __P((void));
45void usage __P((void));
46
47int
8b35ab41
KB
48main(argc, argv)
49 int argc;
50 char **argv;
51{
cc952d1c
JSP
52 enum { NEWSH, LOADENTRY, EDITENTRY } op;
53 struct passwd *pw, lpw;
bc3d7b01
KB
54 int ch, pfd, tfd;
55 char *arg;
8b35ab41 56
bc3d7b01 57 op = EDITENTRY;
34dda72c 58 while ((ch = getopt(argc, argv, "a:s:")) != EOF)
b7eb8299
KB
59 switch(ch) {
60 case 'a':
bc3d7b01
KB
61 op = LOADENTRY;
62 arg = optarg;
b7eb8299 63 break;
34dda72c 64 case 's':
bc3d7b01
KB
65 op = NEWSH;
66 arg = optarg;
34dda72c 67 break;
b7eb8299
KB
68 case '?':
69 default:
70 usage();
8b35ab41 71 }
b7eb8299
KB
72 argc -= optind;
73 argv += optind;
74
bc3d7b01
KB
75 uid = getuid();
76
77 if (op == EDITENTRY || op == NEWSH)
b7eb8299
KB
78 switch(argc) {
79 case 0:
cc952d1c
JSP
80 if (!(pw = getpwuid(uid)))
81 errx(1, "unknown user: uid %u", uid);
b7eb8299
KB
82 break;
83 case 1:
cc952d1c
JSP
84 if (!(pw = getpwnam(*argv)))
85 errx(1, "unknown user: %s", *argv);
34dda72c
KB
86 if (uid && uid != pw->pw_uid)
87 baduser();
b7eb8299
KB
88 break;
89 default:
90 usage();
8b35ab41 91 }
8b35ab41 92
bc3d7b01
KB
93 if (op == NEWSH) {
94 /* protect p_shell -- it thinks NULL is /bin/sh */
95 if (!arg[0])
96 usage();
97 if (p_shell(arg, pw, (ENTRY *)NULL))
98 pw_error((char *)NULL, 0, 1);
34dda72c 99 }
8b35ab41 100
bc3d7b01
KB
101 if (op == LOADENTRY) {
102 if (uid)
103 baduser();
104 pw = &lpw;
105 if (!pw_scan(arg, pw))
8b35ab41 106 exit(1);
8b35ab41 107 }
7df40547 108
b7eb8299 109 /*
456319a0 110 * The temporary file/file descriptor usage is a little tricky here.
bc3d7b01 111 * 1: We start off with two fd's, one for the master password
456319a0
KB
112 * file (used to lock everything), and one for a temporary file.
113 * 2: Display() gets an fp for the temporary file, and copies the
114 * user's information into it. It then gives the temporary file
115 * to the user and closes the fp, closing the underlying fd.
bc3d7b01 116 * 3: The user edits the temporary file some number of times.
456319a0
KB
117 * 4: Verify() gets an fp for the temporary file, and verifies the
118 * contents. It can't use an fp derived from the step #2 fd,
119 * because the user's editor may have created a new instance of
120 * the file. Once the file is verified, its contents are stored
121 * in a password structure. The verify routine closes the fp,
122 * closing the underlying fd.
123 * 5: Delete the temporary file.
124 * 6: Get a new temporary file/fd. Pw_copy() gets an fp for it
125 * file and copies the master password file into it, replacing
126 * the user record with a new one. We can't use the first
127 * temporary file for this because it was owned by the user.
128 * Pw_copy() closes its fp, flushing the data and closing the
129 * underlying file descriptor. We can't close the master
130 * password fp, or we'd lose the lock.
131 * 7: Call pw_mkdb() (which renames the temporary file) and exit.
132 * The exit closes the master passwd fp/fd.
b7eb8299 133 */
bc3d7b01
KB
134 pw_init();
135 pfd = pw_lock();
136 tfd = pw_tmp();
8b35ab41 137
456319a0
KB
138 if (op == EDITENTRY) {
139 display(tfd, pw);
140 edit(pw);
141 (void)unlink(tempname);
142 tfd = pw_tmp();
143 }
144
145 pw_copy(pfd, tfd, pw);
b7eb8299 146
bc3d7b01
KB
147 if (!pw_mkdb())
148 pw_error((char *)NULL, 0, 1);
149 exit(0);
7df40547
KB
150}
151
cc952d1c 152void
34dda72c
KB
153baduser()
154{
cc952d1c
JSP
155
156 errx(1, "%s", strerror(EACCES));
34dda72c
KB
157}
158
cc952d1c 159void
b7eb8299
KB
160usage()
161{
cc952d1c 162
34dda72c 163 (void)fprintf(stderr, "usage: chpass [-a list] [-s shell] [user]\n");
b7eb8299
KB
164 exit(1);
165}