xref: /minix/external/bsd/bind/dist/bin/named/win32/os.c (revision fb9c64b2)
1 /*	$NetBSD: os.c,v 1.8 2015/07/08 17:28:55 christos Exp $	*/
2 
3 /*
4  * Copyright (C) 2004, 2005, 2007-2009, 2012-2015  Internet Systems Consortium, Inc. ("ISC")
5  * Copyright (C) 1999-2002  Internet Software Consortium.
6  *
7  * Permission to use, copy, modify, and/or distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /* Id: os.c,v 1.39 2012/02/06 23:46:44 tbox Exp  */
21 
22 #include <config.h>
23 #include <stdarg.h>
24 
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 
28 #include <ctype.h>
29 #include <errno.h>
30 #include <io.h>
31 #include <process.h>
32 #include <fcntl.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <syslog.h>
36 
37 #include <isc/print.h>
38 #include <isc/result.h>
39 #include <isc/strerror.h>
40 #include <isc/string.h>
41 #include <isc/ntpaths.h>
42 #include <isc/util.h>
43 #include <isc/win32os.h>
44 
45 #include <named/main.h>
46 #include <named/log.h>
47 #include <named/os.h>
48 #include <named/globals.h>
49 #include <named/ntservice.h>
50 
51 
52 static char *pidfile = NULL;
53 static int devnullfd = -1;
54 
55 static BOOL Initialized = FALSE;
56 
57 static char *version_error =
58 	"named requires Windows 2000 Service Pack 2 or later to run correctly";
59 
60 void
61 ns_paths_init(void) {
62 	if (!Initialized)
63 		isc_ntpaths_init();
64 
65 	ns_g_conffile = isc_ntpaths_get(NAMED_CONF_PATH);
66 	lwresd_g_conffile = isc_ntpaths_get(LWRES_CONF_PATH);
67 	lwresd_g_resolvconffile = isc_ntpaths_get(RESOLV_CONF_PATH);
68 	ns_g_conffile = isc_ntpaths_get(NAMED_CONF_PATH);
69 	ns_g_defaultpidfile = isc_ntpaths_get(NAMED_PID_PATH);
70 	lwresd_g_defaultpidfile = isc_ntpaths_get(LWRESD_PID_PATH);
71 	ns_g_keyfile = isc_ntpaths_get(RNDC_KEY_PATH);
72 	ns_g_defaultsessionkeyfile = isc_ntpaths_get(SESSION_KEY_PATH);
73 
74 	Initialized = TRUE;
75 }
76 
77 /*
78  * Due to Knowledge base article Q263823 we need to make sure that
79  * Windows 2000 systems have Service Pack 2 or later installed and
80  * warn when it isn't.
81  */
82 static void
83 version_check(const char *progname) {
84 
85 	if ((isc_win32os_versioncheck(4, 0, 0, 0) >= 0) &&
86 	    (isc_win32os_versioncheck(5, 0, 0, 0) < 0))
87 		return;	/* No problem with Version 4.0 */
88 	if (isc_win32os_versioncheck(5, 0, 2, 0) < 0)
89 		if (ntservice_isservice())
90 			NTReportError(progname, version_error);
91 		else
92 			fprintf(stderr, "%s\n", version_error);
93 }
94 
95 static void
96 setup_syslog(const char *progname) {
97 	int options;
98 
99 	options = LOG_PID;
100 #ifdef LOG_NDELAY
101 	options |= LOG_NDELAY;
102 #endif
103 
104 	openlog(progname, options, LOG_DAEMON);
105 }
106 
107 void
108 ns_os_init(const char *progname) {
109 	ns_paths_init();
110 	setup_syslog(progname);
111 	/*
112 	 * XXXMPA. We may need to split ntservice_init() in two and
113 	 * just mark as running in ns_os_started().  If we do that
114 	 * this is where the first part of ntservice_init() should be
115 	 * called from.
116 	 *
117 	 * XXX970 Remove comment if no problems by 9.7.0.
118 	 *
119 	 * ntservice_init();
120 	 */
121 	version_check(progname);
122 }
123 
124 void
125 ns_os_daemonize(void) {
126 	/*
127 	 * Try to set stdin, stdout, and stderr to /dev/null, but press
128 	 * on even if it fails.
129 	 */
130 	if (devnullfd != -1) {
131 		if (devnullfd != _fileno(stdin)) {
132 			close(_fileno(stdin));
133 			(void)_dup2(devnullfd, _fileno(stdin));
134 		}
135 		if (devnullfd != _fileno(stdout)) {
136 			close(_fileno(stdout));
137 			(void)_dup2(devnullfd, _fileno(stdout));
138 		}
139 		if (devnullfd != _fileno(stderr)) {
140 			close(_fileno(stderr));
141 			(void)_dup2(devnullfd, _fileno(stderr));
142 		}
143 	}
144 }
145 
146 void
147 ns_os_opendevnull(void) {
148 	devnullfd = open("NUL", O_RDWR, 0);
149 }
150 
151 void
152 ns_os_closedevnull(void) {
153 	if (devnullfd != _fileno(stdin) &&
154 	    devnullfd != _fileno(stdout) &&
155 	    devnullfd != _fileno(stderr)) {
156 		close(devnullfd);
157 		devnullfd = -1;
158 	}
159 }
160 
161 void
162 ns_os_chroot(const char *root) {
163 	if (root != NULL)
164 		ns_main_earlyfatal("chroot(): isn't supported by Win32 API");
165 }
166 
167 void
168 ns_os_inituserinfo(const char *username) {
169 }
170 
171 void
172 ns_os_changeuser(void) {
173 }
174 
175 void
176 ns_os_adjustnofile(void) {
177 }
178 
179 void
180 ns_os_minprivs(void) {
181 }
182 
183 static int
184 safe_open(const char *filename, int mode, isc_boolean_t append) {
185 	int fd;
186 	struct stat sb;
187 
188 	if (stat(filename, &sb) == -1) {
189 		if (errno != ENOENT)
190 			return (-1);
191 	} else if ((sb.st_mode & S_IFREG) == 0)
192 		return (-1);
193 
194 	if (append)
195 		fd = open(filename, O_WRONLY|O_CREAT|O_APPEND, mode);
196 	else {
197 		(void)unlink(filename);
198 		fd = open(filename, O_WRONLY|O_CREAT|O_EXCL, mode);
199 	}
200 	return (fd);
201 }
202 
203 static void
204 cleanup_pidfile(void) {
205 	if (pidfile != NULL) {
206 		(void)unlink(pidfile);
207 		free(pidfile);
208 	}
209 	pidfile = NULL;
210 }
211 
212 FILE *
213 ns_os_openfile(const char *filename, int mode, isc_boolean_t switch_user) {
214 	char strbuf[ISC_STRERRORSIZE];
215 	FILE *fp;
216 	int fd;
217 
218 	UNUSED(switch_user);
219 	fd = safe_open(filename, mode, ISC_FALSE);
220 	if (fd < 0) {
221 		isc__strerror(errno, strbuf, sizeof(strbuf));
222 		ns_main_earlywarning("could not open file '%s': %s",
223 				     filename, strbuf);
224 		return (NULL);
225 	}
226 
227 	fp = fdopen(fd, "w");
228 	if (fp == NULL) {
229 		isc__strerror(errno, strbuf, sizeof(strbuf));
230 		ns_main_earlywarning("could not fdopen() file '%s': %s",
231 				     filename, strbuf);
232 		close(fd);
233 	}
234 
235 	return (fp);
236 }
237 
238 void
239 ns_os_writepidfile(const char *filename, isc_boolean_t first_time) {
240 	FILE *lockfile;
241 	pid_t pid;
242 	char strbuf[ISC_STRERRORSIZE];
243 	void (*report)(const char *, ...);
244 
245 	/*
246 	 * The caller must ensure any required synchronization.
247 	 */
248 
249 	report = first_time ? ns_main_earlyfatal : ns_main_earlywarning;
250 
251 	cleanup_pidfile();
252 
253 	if (filename == NULL)
254 		return;
255 
256 	pidfile = strdup(filename);
257 	if (pidfile == NULL) {
258 		isc__strerror(errno, strbuf, sizeof(strbuf));
259 		(*report)("couldn't strdup() '%s': %s", filename, strbuf);
260 		return;
261 	}
262 
263 	lockfile = ns_os_openfile(filename, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH,
264 				  ISC_FALSE);
265 	if (lockfile == NULL) {
266 		free(pidfile);
267 		pidfile = NULL;
268 		return;
269 	}
270 
271 	pid = getpid();
272 
273 	if (fprintf(lockfile, "%ld\n", (long)pid) < 0) {
274 		(*report)("fprintf() to pid file '%s' failed", filename);
275 		(void)fclose(lockfile);
276 		cleanup_pidfile();
277 		return;
278 	}
279 	if (fflush(lockfile) == EOF) {
280 		(*report)("fflush() to pid file '%s' failed", filename);
281 		(void)fclose(lockfile);
282 		cleanup_pidfile();
283 		return;
284 	}
285 	(void)fclose(lockfile);
286 }
287 
288 void
289 ns_os_shutdown(void) {
290 	closelog();
291 	cleanup_pidfile();
292 	ntservice_shutdown();	/* This MUST be the last thing done */
293 }
294 
295 isc_result_t
296 ns_os_gethostname(char *buf, size_t len) {
297 	int n;
298 
299 	n = gethostname(buf, (int)len);
300 	return ((n == 0) ? ISC_R_SUCCESS : ISC_R_FAILURE);
301 }
302 
303 void
304 ns_os_shutdownmsg(char *command, isc_buffer_t *text) {
305 	UNUSED(command);
306 	UNUSED(text);
307 }
308 
309 void
310 ns_os_tzset(void) {
311 #ifdef HAVE_TZSET
312 	tzset();
313 #endif
314 }
315 
316 void
317 ns_os_started(void) {
318 	ntservice_init();
319 }
320