xref: /original-bsd/usr.sbin/vipw/pw_util.c (revision b21da0a0)
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.1 (Berkeley) 02/12/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 	sigset_t set;
37 
38 	/* Unlimited cpu, file size. */
39 	rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
40 	(void)setrlimit(RLIMIT_CPU, &rlim);
41 	(void)setrlimit(RLIMIT_FSIZE, &rlim);
42 
43 	/* Don't drop core (not really necessary, but GP's). */
44 	rlim.rlim_cur = rlim.rlim_max = 0;
45 	(void)setrlimit(RLIMIT_CORE, &rlim);
46 
47 	/* Turn off usual signals. */
48 	sigemptyset(&set);
49 	(void)sigaddset(&set, SIGTSTP);
50 	(void)sigaddset(&set, SIGHUP);
51 	(void)sigaddset(&set, SIGINT);
52 	(void)sigaddset(&set, SIGQUIT);
53 	(void)sigaddset(&set, SIGTERM);
54 	(void)sigprocmask(SIG_BLOCK, &set, (sigset_t *)NULL);
55 
56 	/* Create with exact permissions. */
57 	(void)umask(0);
58 }
59 
60 static int lockfd;
61 pw_lock()
62 {
63 	/*
64 	 * If the master password file doesn't exist, the system is hosed.
65 	 * Might as well try to build one.
66 	 * Open should allow flock'ing the file; see 4.4BSD.	XXX
67 	 */
68 	lockfd = open(_PATH_MASTERPASSWD, O_RDONLY, 0);
69 	if (lockfd < 0) {
70 		(void)fprintf(stderr, "%s: %s: %s\n",
71 		    progname, _PATH_MASTERPASSWD, strerror(errno));
72 		exit(1);
73 	}
74 	if (flock(lockfd, LOCK_EX)) {
75 		(void)fprintf(stderr,
76 		    "%s: the password db is busy.\n", progname);
77 		exit(1);
78 	}
79 	return(lockfd);
80 }
81 
82 pw_tmp()
83 {
84 	static char path[MAXPATHLEN] = _PATH_MASTERPASSWD;
85 	int fd;
86 	char *p;
87 
88 	if (p = rindex(path, '/'))
89 		++p;
90 	else
91 		p = path;
92 	(void)sprintf(p, "%s.XXXXXX", progname);
93 	if ((fd = mkstemp(path)) == -1) {
94 		(void)fprintf(stderr,
95 		    "%s: %s: %s\n", progname, path, strerror(errno));
96 		exit(1);
97 	}
98 	tempname = path;
99 	return(fd);
100 }
101 
102 pw_mkdb()
103 {
104 	union wait pstat;
105 	pid_t pid;
106 
107 	(void)printf("%s: rebuilding the database...\n", progname);
108 	(void)fflush(stdout);
109 	if (!(pid = vfork())) {
110 		execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p", tempname, NULL);
111 		pw_error(_PATH_PWD_MKDB, 1, 1);
112 	}
113 	pid = waitpid(pid, (int *)&pstat, 0);
114 	if (pid == -1 || pstat.w_status)
115 		return(0);
116 	(void)printf("%s: done\n", progname);
117 	return(1);
118 }
119 
120 pw_edit(notsetuid)
121 	int notsetuid;
122 {
123 	union wait pstat;
124 	pid_t pid;
125 	char *p, *editor;
126 
127 	if (!(editor = getenv("EDITOR")))
128 		editor = _PATH_VI;
129 	if (p = rindex(editor, '/'))
130 		++p;
131 	else
132 		p = editor;
133 
134 	if (!(pid = vfork())) {
135 		if (notsetuid) {
136 			(void)setgid(getgid());
137 			(void)setuid(getuid());
138 		}
139 		execlp(editor, p, tempname, NULL);
140 		pw_error(editor, 1, 1);
141 	}
142 	pid = waitpid(pid, (int *)&pstat, 0);
143 	return (pid == -1 ? 1 : pstat.w_status);
144 }
145 
146 pw_prompt()
147 {
148 	register int c;
149 
150 	for (;;) {
151 		(void)printf("re-edit the password file? [y]: ");
152 		(void)fflush(stdout);
153 		c = getchar();
154 		if (c != EOF && c != (int)'\n')
155 			while (getchar() != (int)'\n');
156 		if (c == (int)'n')
157 			pw_error((char *)NULL, 0, 0);
158 		break;
159 	}
160 }
161 
162 pw_error(name, err, eval)
163 	char *name;
164 	int err, eval;
165 {
166 	int sverrno;
167 
168 	if (err) {
169 		sverrno = errno;
170 		(void)fprintf(stderr, "%s: ", progname);
171 		if (name)
172 			(void)fprintf(stderr, "%s: ", name);
173 		(void)fprintf(stderr, "%s\n", strerror(sverrno));
174 	}
175 	(void)fprintf(stderr,
176 	    "%s: %s unchanged\n", progname, _PATH_MASTERPASSWD);
177 	(void)unlink(tempname);
178 	exit(eval);
179 }
180