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