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