xref: /original-bsd/usr.sbin/vipw/pw_util.c (revision 3705696b)
1 /*-
2  * Copyright (c) 1990, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char sccsid[] = "@(#)pw_util.c	8.1 (Berkeley) 07/23/93";
10 #endif /* not lint */
11 
12 /*
13  * This file is used by all the "password" programs; vipw(8), chpass(1),
14  * and passwd(1).
15  */
16 
17 #include <sys/param.h>
18 #include <sys/wait.h>
19 #include <sys/time.h>
20 #include <sys/resource.h>
21 
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <paths.h>
25 #include <pwd.h>
26 #include <signal.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 
31 extern char *progname;
32 extern char *tempname;
33 
34 pw_init()
35 {
36 	struct rlimit rlim;
37 
38 	/* Unlimited resource limits. */
39 	rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
40 	(void)setrlimit(RLIMIT_CPU, &rlim);
41 	(void)setrlimit(RLIMIT_FSIZE, &rlim);
42 	(void)setrlimit(RLIMIT_STACK, &rlim);
43 	(void)setrlimit(RLIMIT_DATA, &rlim);
44 	(void)setrlimit(RLIMIT_RSS, &rlim);
45 
46 	/* Don't drop core (not really necessary, but GP's). */
47 	rlim.rlim_cur = rlim.rlim_max = 0;
48 	(void)setrlimit(RLIMIT_CORE, &rlim);
49 
50 	/* Turn off signals. */
51 	(void)signal(SIGALRM, SIG_IGN);
52 	(void)signal(SIGHUP, SIG_IGN);
53 	(void)signal(SIGINT, SIG_IGN);
54 	(void)signal(SIGPIPE, SIG_IGN);
55 	(void)signal(SIGQUIT, SIG_IGN);
56 	(void)signal(SIGTERM, SIG_IGN);
57 	(void)signal(SIGTSTP, SIG_IGN);
58 	(void)signal(SIGTTOU, SIG_IGN);
59 
60 	/* Create with exact permissions. */
61 	(void)umask(0);
62 }
63 
64 static int lockfd;
65 pw_lock()
66 {
67 	/*
68 	 * If the master password file doesn't exist, the system is hosed.
69 	 * Might as well try to build one.  Set the close-on-exec bit so
70 	 * that users can't get at the encrypted passwords while editing.
71 	 * Open should allow flock'ing the file; see 4.4BSD.	XXX
72 	 */
73 	lockfd = open(_PATH_MASTERPASSWD, O_RDONLY, 0);
74 	if (lockfd < 0 || fcntl(lockfd, F_SETFD, 1) == -1) {
75 		(void)fprintf(stderr, "%s: %s: %s\n",
76 		    progname, _PATH_MASTERPASSWD, strerror(errno));
77 		exit(1);
78 	}
79 	if (flock(lockfd, LOCK_EX|LOCK_NB)) {
80 		(void)fprintf(stderr,
81 		    "%s: the password db is busy.\n", progname);
82 		exit(1);
83 	}
84 	return(lockfd);
85 }
86 
87 pw_tmp()
88 {
89 	static char path[MAXPATHLEN] = _PATH_MASTERPASSWD;
90 	int fd;
91 	char *p;
92 
93 	if (p = rindex(path, '/'))
94 		++p;
95 	else
96 		p = path;
97 	(void)snprintf(p, sizeof(path), "%s.XXXXXX", progname);
98 	if ((fd = mkstemp(path)) == -1) {
99 		(void)fprintf(stderr,
100 		    "%s: %s: %s\n", progname, path, strerror(errno));
101 		exit(1);
102 	}
103 	tempname = path;
104 	return(fd);
105 }
106 
107 pw_mkdb()
108 {
109 	union wait pstat;
110 	pid_t pid;
111 
112 	(void)printf("%s: rebuilding the database...\n", progname);
113 	(void)fflush(stdout);
114 	if (!(pid = vfork())) {
115 		execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p", tempname, NULL);
116 		pw_error(_PATH_PWD_MKDB, 1, 1);
117 	}
118 	pid = waitpid(pid, (int *)&pstat, 0);
119 	if (pid == -1 || pstat.w_status)
120 		return(0);
121 	(void)printf("%s: done\n", progname);
122 	return(1);
123 }
124 
125 pw_edit(notsetuid)
126 	int notsetuid;
127 {
128 	union wait pstat;
129 	pid_t pid;
130 	char *p, *editor;
131 
132 	if (!(editor = getenv("EDITOR")))
133 		editor = _PATH_VI;
134 	if (p = rindex(editor, '/'))
135 		++p;
136 	else
137 		p = editor;
138 
139 	if (!(pid = vfork())) {
140 		if (notsetuid) {
141 			(void)setgid(getgid());
142 			(void)setuid(getuid());
143 		}
144 		execlp(editor, p, tempname, NULL);
145 		_exit(1);
146 	}
147 	pid = waitpid(pid, (int *)&pstat, 0);
148 	if (pid == -1 || pstat.w_status)
149 		pw_error(editor, 1, 1);
150 }
151 
152 pw_prompt()
153 {
154 	register int c;
155 
156 	for (;;) {
157 		(void)printf("re-edit the password file? [y]: ");
158 		(void)fflush(stdout);
159 		c = getchar();
160 		if (c != EOF && c != (int)'\n')
161 			while (getchar() != (int)'\n');
162 		if (c == (int)'n')
163 			pw_error((char *)NULL, 0, 0);
164 		break;
165 	}
166 }
167 
168 pw_error(name, err, eval)
169 	char *name;
170 	int err, eval;
171 {
172 	int sverrno;
173 
174 	if (err) {
175 		sverrno = errno;
176 		(void)fprintf(stderr, "%s: ", progname);
177 		if (name)
178 			(void)fprintf(stderr, "%s: ", name);
179 		(void)fprintf(stderr, "%s\n", strerror(sverrno));
180 	}
181 	(void)fprintf(stderr,
182 	    "%s: %s unchanged\n", progname, _PATH_MASTERPASSWD);
183 	(void)unlink(tempname);
184 	exit(eval);
185 }
186