Commit 44fee668 authored by James Brister's avatar James Brister
Browse files

Implement deamon-ising (`-f' to run in foreground).

log to syslog if deamon.
implement `-t' option and chroot
parent 5bd937c6
......@@ -69,6 +69,11 @@ EXTERN const char * ns_g_conffile INIT("/etc/named.conf");
* Misc.
*/
EXTERN isc_boolean_t ns_g_coreok INIT(ISC_TRUE);
EXTERN const char * ns_g_chrootdir INIT(NULL);
EXTERN isc_boolean_t ns_g_foreground INIT(ISC_FALSE);
EXTERN const char * ns_g_defaultpidfile INIT("/var/run/named.pid");
EXTERN char * ns_g_pidfile INIT(NULL);
/*
* XXX Temporary.
......
......@@ -87,4 +87,10 @@ ns_server_reloadwanted(ns_server_t *server);
* is ignored.
*/
void
ns_update_pidfile(const char *filename);
/*
* Save the pid to the given file
*/
#endif /* NS_SERVER_H */
......@@ -89,15 +89,25 @@ ns_log_init(void) {
/*
* Create and install the default channel.
*/
destination.file.stream = stderr;
destination.file.name = NULL;
destination.file.versions = ISC_LOG_ROLLNEVER;
destination.file.maximum_size = 0;
flags = ISC_LOG_PRINTTIME;
result = isc_log_createchannel(ns_g_lctx, "_default",
ISC_LOG_TOFILEDESC,
ISC_LOG_DYNAMIC,
&destination, flags);
if (ns_g_foreground) {
destination.file.stream = stderr;
destination.file.name = NULL;
destination.file.versions = ISC_LOG_ROLLNEVER;
destination.file.maximum_size = 0;
flags = ISC_LOG_PRINTTIME;
result = isc_log_createchannel(ns_g_lctx, "_default",
ISC_LOG_TOFILEDESC,
ISC_LOG_DYNAMIC,
&destination, flags);
} else {
destination.facility = LOG_DAEMON;
flags = ISC_LOG_PRINTTIME;
result = isc_log_createchannel(ns_g_lctx, "_default",
ISC_LOG_TOSYSLOG,
ISC_LOG_DYNAMIC,
&destination, flags);
}
if (result != ISC_R_SUCCESS)
goto cleanup;
result = isc_log_usechannel(ns_g_lctx, "_default", NULL, NULL);
......
......@@ -19,11 +19,16 @@
#include <config.h>
#include <errno.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stddef.h>
/* XXX this include will need to go. It's here for _SC_OPEN_MAX */
#include <unistd.h>
#include <isc/app.h>
#include <isc/assertions.h>
#include <isc/error.h>
......@@ -140,7 +145,7 @@ parse_command_line(int argc, char *argv[]) {
int ch;
isc_commandline_errprint = ISC_FALSE;
while ((ch = isc_commandline_parse(argc, argv, "b:c:d:N:p:sx:")) !=
while ((ch = isc_commandline_parse(argc, argv, "b:c:d:fN:p:st:x:")) !=
-1) {
switch (ch) {
case 'b':
......@@ -150,6 +155,9 @@ parse_command_line(int argc, char *argv[]) {
case 'd':
ns_g_debuglevel = atoi(isc_commandline_argument);
break;
case 'f':
ns_g_foreground = ISC_TRUE;
break;
case 'N':
ns_g_cpus = atoi(isc_commandline_argument);
if (ns_g_cpus == 0)
......@@ -162,6 +170,10 @@ parse_command_line(int argc, char *argv[]) {
/* XXXRTH temporary syntax */
want_stats = ISC_TRUE;
break;
case 't':
/* XXXJAB should be make a copy? */
ns_g_chrootdir = isc_commandline_argument;
break;
case 'x':
/* XXXRTH temporary syntax */
ns_g_cachefile = isc_commandline_argument;
......@@ -251,16 +263,29 @@ cleanup() {
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
ISC_LOG_NOTICE, "exiting");
ns_log_shutdown();
if (ns_g_pidfile != NULL) {
(void)unlink(ns_g_pidfile);
isc_mem_free(ns_g_mctx, ns_g_pidfile);
}
}
int
main(int argc, char *argv[]) {
isc_result_t result;
int n;
program_name = argv[0];
isc_assertion_setcallback(assertion_failed);
isc_error_setfatal(library_fatal_error);
for (n = sysconf(_SC_OPEN_MAX) - 1; n >= 0; n--)
if (n != STDIN_FILENO &&
n != STDOUT_FILENO &&
n != STDERR_FILENO)
(void) close(n);
result = ns_os_init();
if (result != ISC_R_SUCCESS)
ns_main_earlyfatal("ns_os_init() failed: %s",
......@@ -281,6 +306,33 @@ main(int argc, char *argv[]) {
parse_command_line(argc, argv);
if (ns_g_chrootdir != NULL) {
#ifdef HAVE_CHROOT
if (chroot(ns_g_chrootdir) < 0) {
ns_main_earlyfatal("chroot %s failed: %s\n",
ns_g_chrootdir, strerror(errno));
exit(1);
}
if (chdir("/") < 0) {
ns_main_earlyfatal("chdir(\"/\") failed: %s\n",
strerror(errno));
exit(1);
}
#else
fprintf(stderr, "warning: chroot() not available\n");
#endif
}
/*
* deamon() must be called before any threads are created
* (fork() is deadly to threads). Threads get created in setup().
*/
if (ns_g_foreground == ISC_FALSE) {
if (daemon(1, 0) != 0) {
ns_main_earlyfatal("daemon(): %s", strerror(errno));
}
}
setup();
/*
......@@ -315,3 +367,5 @@ main(int argc, char *argv[]) {
return (0);
}
......@@ -17,6 +17,9 @@
#include <config.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
......@@ -101,6 +104,8 @@ typedef struct {
static void fatal(char *msg, isc_result_t result);
static void ns_server_reload(isc_task_t *task, isc_event_t *event);
static FILE *write_open(char *filename);
static isc_result_t
ns_listenelt_fromconfig(dns_c_lstnon_t *celt, dns_c_ctx_t *cctx,
dns_aclconfctx_t *actx,
......@@ -440,6 +445,7 @@ load_configuration(const char *filename, ns_server_t *server) {
dns_view_t *view, *view_next;
dns_viewlist_t tmpviewlist;
dns_aclconfctx_t aclconfctx;
char *pidfile;
dns_aclconfctx_init(&aclconfctx);
......@@ -563,6 +569,15 @@ load_configuration(const char *filename, ns_server_t *server) {
}
}
if (dns_c_ctx_getpidfilename(configctx, &pidfile) == ISC_R_SUCCESS) {
ns_update_pidfile(pidfile);
} else {
ns_update_pidfile(ns_g_defaultpidfile);
}
/*
* Swap our new view list with the production one.
*/
......@@ -905,3 +920,83 @@ ns_listenelt_fromconfig(dns_c_lstnon_t *celt, dns_c_ctx_t *cctx,
return (ISC_R_SUCCESS);
}
void
ns_update_pidfile(const char *pidfile)
{
FILE *fp;
INSIST(pidfile != NULL);
INSIST(strlen(pidfile) > 0);
if (ns_g_pidfile != NULL) {
(void)unlink(ns_g_pidfile);
isc_mem_free(ns_g_mctx, ns_g_pidfile);
}
ns_g_pidfile = isc_mem_strdup(ns_g_mctx, (char *) pidfile);
if (ns_g_pidfile == NULL) {
fatal("failed to isc_mem_strdup() the pidfile",
ISC_R_NOMEMORY);
}
/* Not sure why I'm doing it this way, but bind8 did */
fp = write_open(ns_g_pidfile);
if (fp != NULL) {
fprintf(fp, "%ld\n", (long)getpid());
(void)fclose(fp);
} else {
isc_log_write(ns_g_lctx,
NS_LOGCATEGORY_GENERAL,
NS_LOGMODULE_SERVER,
ISC_LOG_ERROR,
"couldn't create pid file '%s'",
ns_g_pidfile);
}
}
static FILE *
write_open(char *filename)
{
FILE *stream;
int fd;
struct stat sb;
int regular;
if (stat(filename, &sb) < 0) {
if (errno != ENOENT) {
isc_log_write(ns_g_lctx,
NS_LOGCATEGORY_GENERAL,
NS_LOGMODULE_SERVER,
ISC_LOG_ERROR,
"write_open: stat of %s failed: %s",
filename, strerror(errno));
return (NULL);
}
regular = 1;
} else
regular = (sb.st_mode & S_IFREG);
if (!regular) {
isc_log_write(ns_g_lctx,
NS_LOGCATEGORY_GENERAL,
NS_LOGMODULE_SERVER,
ISC_LOG_ERROR,
"write_open: %s isn't a regular file",
filename);
return (NULL);
}
(void)unlink(filename);
fd = open(filename, O_WRONLY|O_CREAT|O_EXCL,
S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
if (fd < 0)
return (NULL);
stream = fdopen(fd, "w");
if (stream == NULL)
(void)close(fd);
return (stream);
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment