Daemons detach atomically to avoid having to wait
Tests that start daemons have to "wait" for them to start. This commit makes Heimdal daemons prep to detach (when requested) by forking early, then having the child signal readiness to the parent when the child really is ready. The parent exits only which the child is ready. This means that tests will no longer need to wait for daemons. However, tests will still need a pidfile or such so they can stop the daemons. Note that the --detach options should not be used on OS X from launchd, only from tests.
This commit is contained in:
@@ -307,14 +307,10 @@ AC_FIND_IF_NOT_BROKEN(gai_strerror,,
|
||||
#include <ws2tcpip.h>
|
||||
#endif],[0])
|
||||
|
||||
dnl Darwin is weird, and in some senses not unix, launchd doesn't want
|
||||
dnl servers to use daemon(), so its deprecated.
|
||||
case "$host_os" in
|
||||
darwin*)
|
||||
;;
|
||||
*)
|
||||
AC_DEFINE([SUPPORT_DETACH], 1,
|
||||
[Define if os support want to detach is daemonens.])
|
||||
AC_BROKEN([daemon]) ;;
|
||||
esac
|
||||
|
||||
|
@@ -36,6 +36,8 @@
|
||||
#include <sys/wait.h>
|
||||
#endif
|
||||
|
||||
extern int daemon_child;
|
||||
|
||||
struct kadm_port {
|
||||
char *port;
|
||||
unsigned short def_port;
|
||||
@@ -292,5 +294,7 @@ start_server(krb5_context contextp, const char *port_str)
|
||||
if(num_socks == 0)
|
||||
krb5_errx(contextp, 1, "no sockets to listen to - exiting");
|
||||
|
||||
roken_detach_finish(NULL, daemon_child);
|
||||
|
||||
wait_for_connection(contextp, socks, num_socks);
|
||||
}
|
||||
|
@@ -45,6 +45,9 @@ static int debug_flag;
|
||||
static char *port_str;
|
||||
char *realm;
|
||||
|
||||
static int detach_from_console = -1;
|
||||
int daemon_child = -1;
|
||||
|
||||
static struct getargs args[] = {
|
||||
{
|
||||
"config-file", 'c', arg_string, &config_file,
|
||||
@@ -68,6 +71,14 @@ static struct getargs args[] = {
|
||||
{ "debug", 'd', arg_flag, &debug_flag,
|
||||
"enable debugging", NULL
|
||||
},
|
||||
{
|
||||
"detach", 0 , arg_flag, &detach_from_console,
|
||||
"detach from console", NULL
|
||||
},
|
||||
{
|
||||
"daemon-child", 0 , arg_integer, &daemon_child,
|
||||
"private argument, do not use", NULL
|
||||
},
|
||||
{ "ports", 'p', arg_string, &port_str,
|
||||
"ports to listen to", "port" },
|
||||
{ "help", 'h', arg_flag, &help_flag, NULL, NULL },
|
||||
@@ -98,10 +109,6 @@ main(int argc, char **argv)
|
||||
|
||||
setprogname(argv[0]);
|
||||
|
||||
ret = krb5_init_context(&context);
|
||||
if (ret)
|
||||
errx (1, "krb5_init_context failed: %d", ret);
|
||||
|
||||
if (getarg(args, num_args, argc, argv, &optidx)) {
|
||||
warnx("error at argument `%s'", argv[optidx]);
|
||||
usage(1);
|
||||
@@ -115,6 +122,13 @@ main(int argc, char **argv)
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (detach_from_console > 0 && daemon_child == -1)
|
||||
roken_detach_prep(argc, argv, "--daemon-child");
|
||||
|
||||
ret = krb5_init_context(&context);
|
||||
if (ret)
|
||||
errx (1, "krb5_init_context failed: %d", ret);
|
||||
|
||||
argc -= optidx;
|
||||
argv += optidx;
|
||||
|
||||
|
25
kcm/config.c
25
kcm/config.c
@@ -44,10 +44,8 @@ char *door_path = NULL;
|
||||
|
||||
static char *max_request_str; /* `max_request' as a string */
|
||||
|
||||
#ifdef SUPPORT_DETACH
|
||||
int detach_from_console = -1;
|
||||
#define DETACH_IS_DEFAULT FALSE
|
||||
#endif
|
||||
int daemon_child = -1;
|
||||
|
||||
static const char *system_cache_name = NULL;
|
||||
static const char *system_keytab = NULL;
|
||||
@@ -88,19 +86,14 @@ static struct getargs args[] = {
|
||||
"launchd", 0, arg_flag, &launchd_flag,
|
||||
"when in use by launchd", NULL
|
||||
},
|
||||
#ifdef SUPPORT_DETACH
|
||||
#if DETACH_IS_DEFAULT
|
||||
{
|
||||
"detach", 'D', arg_negative_flag, &detach_from_console,
|
||||
"don't detach from console", NULL
|
||||
},
|
||||
#else
|
||||
{
|
||||
"detach", 0 , arg_flag, &detach_from_console,
|
||||
"detach from console", NULL
|
||||
},
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
"daemon-child", 0 , arg_integer, &daemon_child,
|
||||
"private argument, do not use", NULL
|
||||
},
|
||||
{ "help", 'h', arg_flag, &help_flag, NULL, NULL },
|
||||
{
|
||||
"system-principal", 'k', arg_string, &system_principal,
|
||||
@@ -331,10 +324,10 @@ kcm_configure(int argc, char **argv)
|
||||
int optidx = 0;
|
||||
const char *p;
|
||||
|
||||
while(getarg(args, num_args, argc, argv, &optidx))
|
||||
while (getarg(args, num_args, argc, argv, &optidx))
|
||||
warnx("error at argument `%s'", argv[optidx]);
|
||||
|
||||
if(help_flag)
|
||||
if (help_flag)
|
||||
usage (0);
|
||||
|
||||
if (version_flag) {
|
||||
@@ -387,13 +380,11 @@ kcm_configure(int argc, char **argv)
|
||||
krb5_err(kcm_context, 1, ret, "initializing system ccache");
|
||||
}
|
||||
|
||||
#ifdef SUPPORT_DETACH
|
||||
if(detach_from_console == -1)
|
||||
detach_from_console = krb5_config_get_bool_default(kcm_context, NULL,
|
||||
DETACH_IS_DEFAULT,
|
||||
FALSE,
|
||||
"kcm",
|
||||
"detach", NULL);
|
||||
#endif
|
||||
kcm_openlog();
|
||||
if(max_request == 0)
|
||||
max_request = 64 * 1024;
|
||||
|
@@ -169,9 +169,8 @@ extern char *door_path;
|
||||
extern size_t max_request;
|
||||
extern sig_atomic_t exit_flag;
|
||||
extern int name_constraints;
|
||||
#ifdef SUPPORT_DETACH
|
||||
extern int detach_from_console;
|
||||
#endif
|
||||
extern int daemon_child;
|
||||
extern int launchd_flag;
|
||||
extern int disallow_getting_krbtgt;
|
||||
|
||||
|
@@ -86,11 +86,8 @@ main(int argc, char **argv)
|
||||
signal(SIGUSR2, sigusr2);
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
#endif
|
||||
#ifdef SUPPORT_DETACH
|
||||
if (detach_from_console)
|
||||
if (daemon(0, 0) == -1)
|
||||
err(1, "daemon");
|
||||
#endif
|
||||
if (detach_from_console && !launchd_flag && daemon_child == -1)
|
||||
roken_detach_prep(argc, argv, "--daemon-child");
|
||||
pidfile(NULL);
|
||||
|
||||
if (launchd_flag) {
|
||||
@@ -101,6 +98,8 @@ main(int argc, char **argv)
|
||||
heim_sipc_service_unix(service_name, kcm_service, NULL, &un);
|
||||
}
|
||||
|
||||
roken_detach_finish(NULL, daemon_child);
|
||||
|
||||
heim_ipc_main();
|
||||
|
||||
krb5_free_context(kcm_context);
|
||||
|
34
kdc/config.c
34
kdc/config.c
@@ -94,19 +94,14 @@ static struct getargs args[] = {
|
||||
{ "ports", 'P', arg_string, rk_UNCONST(&port_str),
|
||||
"ports to listen to", "portspec"
|
||||
},
|
||||
#ifdef SUPPORT_DETACH
|
||||
#if DETACH_IS_DEFAULT
|
||||
{
|
||||
"detach", 'D', arg_negative_flag, &detach_from_console,
|
||||
"don't detach from console", NULL
|
||||
},
|
||||
#else
|
||||
{
|
||||
"detach", 0 , arg_flag, &detach_from_console,
|
||||
"detach from console", NULL
|
||||
},
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
"daemon-child", 0 , arg_flag, &daemon_child,
|
||||
"private argument, do not use", NULL
|
||||
},
|
||||
{ "addresses", 0, arg_strings, &addresses_str,
|
||||
"addresses to listen on", "list of addresses" },
|
||||
{ "disable-des", 0, arg_flag, &disable_des,
|
||||
@@ -158,10 +153,10 @@ configure(krb5_context context, int argc, char **argv, int *optidx)
|
||||
|
||||
*optidx = 0;
|
||||
|
||||
while(getarg(args, num_args, argc, argv, optidx))
|
||||
while (getarg(args, num_args, argc, argv, optidx))
|
||||
warnx("error at argument `%s'", argv[*optidx]);
|
||||
|
||||
if(help_flag)
|
||||
if (help_flag)
|
||||
usage (0);
|
||||
|
||||
if (version_flag) {
|
||||
@@ -179,6 +174,15 @@ configure(krb5_context context, int argc, char **argv, int *optidx)
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if(detach_from_console == -1)
|
||||
detach_from_console = krb5_config_get_bool_default(context, NULL,
|
||||
FALSE,
|
||||
"kdc",
|
||||
"detach", NULL);
|
||||
|
||||
if (detach_from_console && daemon_child == -1)
|
||||
roken_detach_prep(argc, argv, "--daemon-child");
|
||||
|
||||
{
|
||||
char **files;
|
||||
int aret;
|
||||
@@ -265,14 +269,6 @@ configure(krb5_context context, int argc, char **argv, int *optidx)
|
||||
krb5_errx(context, 1, "enforce-transited-policy deprecated, "
|
||||
"use [kdc]transited-policy instead");
|
||||
|
||||
#ifdef SUPPORT_DETACH
|
||||
if(detach_from_console == -1)
|
||||
detach_from_console = krb5_config_get_bool_default(context, NULL,
|
||||
DETACH_IS_DEFAULT,
|
||||
"kdc",
|
||||
"detach", NULL);
|
||||
#endif /* SUPPORT_DETACH */
|
||||
|
||||
if(max_request_tcp == 0)
|
||||
max_request_tcp = 64 * 1024;
|
||||
if(max_request_udp == 0)
|
||||
|
@@ -867,16 +867,17 @@ next_min_free(krb5_context context, struct descr **d, unsigned int *ndescr)
|
||||
}
|
||||
|
||||
void
|
||||
loop(krb5_context context,
|
||||
krb5_kdc_configuration *config)
|
||||
loop(krb5_context context, krb5_kdc_configuration *config)
|
||||
{
|
||||
struct descr *d;
|
||||
unsigned int ndescr;
|
||||
int ret;
|
||||
|
||||
ndescr = init_sockets(context, config, &d);
|
||||
if(ndescr <= 0)
|
||||
krb5_errx(context, 1, "No sockets!");
|
||||
kdc_log(context, config, 0, "KDC started");
|
||||
roken_detach_finish(NULL, daemon_child);
|
||||
while(exit_flag == 0){
|
||||
struct timeval tmout;
|
||||
fd_set fds;
|
||||
|
@@ -44,10 +44,8 @@ struct perf {
|
||||
struct perf *next;
|
||||
} *ptop;
|
||||
|
||||
#ifdef SUPPORT_DETACH
|
||||
int detach_from_console = -1;
|
||||
#define DETACH_IS_DEFAULT FALSE
|
||||
#endif
|
||||
int daemon_child = -1;
|
||||
|
||||
static krb5_kdc_configuration *kdc_config;
|
||||
static krb5_context kdc_context;
|
||||
|
@@ -99,12 +99,8 @@ extern krb5_addresses explicit_addresses;
|
||||
|
||||
extern int enable_http;
|
||||
|
||||
#ifdef SUPPORT_DETACH
|
||||
|
||||
#define DETACH_IS_DEFAULT FALSE
|
||||
|
||||
extern int detach_from_console;
|
||||
#endif
|
||||
extern int daemon_child;
|
||||
|
||||
extern const struct units _kdc_digestunits[];
|
||||
|
||||
|
@@ -44,9 +44,8 @@
|
||||
|
||||
sig_atomic_t exit_flag = 0;
|
||||
|
||||
#ifdef SUPPORT_DETACH
|
||||
int detach_from_console = -1;
|
||||
#endif
|
||||
int daemon_child = -1;
|
||||
|
||||
static RETSIGTYPE
|
||||
sigterm(int sig)
|
||||
@@ -105,7 +104,6 @@ switch_environment(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
@@ -157,10 +155,6 @@ main(int argc, char **argv)
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef SUPPORT_DETACH
|
||||
if (detach_from_console)
|
||||
daemon(0, 0);
|
||||
#endif
|
||||
#ifdef __APPLE__
|
||||
bonjour_announce(context, config);
|
||||
#endif
|
||||
|
@@ -644,8 +644,46 @@ out:
|
||||
krb5_auth_con_free(context, auth_context);
|
||||
}
|
||||
|
||||
static const char *check_library = NULL;
|
||||
static const char *check_function = NULL;
|
||||
static getarg_strings policy_libraries = { 0, NULL };
|
||||
static char sHDB[] = "HDBGET:";
|
||||
static char *keytab_str = sHDB;
|
||||
static char *realm_str;
|
||||
static int version_flag;
|
||||
static int help_flag;
|
||||
static int detach_from_console;
|
||||
static int daemon_child = -1;
|
||||
static char *port_str;
|
||||
static char *config_file;
|
||||
|
||||
struct getargs args[] = {
|
||||
#ifdef HAVE_DLOPEN
|
||||
{ "check-library", 0, arg_string, &check_library,
|
||||
"library to load password check function from", "library" },
|
||||
{ "check-function", 0, arg_string, &check_function,
|
||||
"password check function to load", "function" },
|
||||
{ "policy-libraries", 0, arg_strings, &policy_libraries,
|
||||
"password check function to load", "function" },
|
||||
#endif
|
||||
{ "addresses", 0, arg_strings, &addresses_str,
|
||||
"addresses to listen on", "list of addresses" },
|
||||
{ "detach", 0, arg_flag, &detach_from_console,
|
||||
"detach from console", NULL },
|
||||
{ "daemon-child", 0 , arg_integer, &daemon_child,
|
||||
"private argument, do not use", NULL },
|
||||
{ "keytab", 'k', arg_string, &keytab_str,
|
||||
"keytab to get authentication key from", "kspec" },
|
||||
{ "config-file", 'c', arg_string, &config_file, NULL, NULL },
|
||||
{ "realm", 'r', arg_string, &realm_str, "default realm", "realm" },
|
||||
{ "port", 'p', arg_string, &port_str, "port", NULL },
|
||||
{ "version", 0, arg_flag, &version_flag, NULL, NULL },
|
||||
{ "help", 0, arg_flag, &help_flag, NULL, NULL }
|
||||
};
|
||||
int num_args = sizeof(args) / sizeof(args[0]);
|
||||
|
||||
static int
|
||||
doit (krb5_keytab keytab, int port)
|
||||
doit(krb5_keytab keytab, int port)
|
||||
{
|
||||
krb5_error_code ret;
|
||||
int *sockets;
|
||||
@@ -659,54 +697,56 @@ doit (krb5_keytab keytab, int port)
|
||||
if (explicit_addresses.len) {
|
||||
addrs = explicit_addresses;
|
||||
} else {
|
||||
ret = krb5_get_all_server_addrs (context, &addrs);
|
||||
ret = krb5_get_all_server_addrs(context, &addrs);
|
||||
if (ret)
|
||||
krb5_err (context, 1, ret, "krb5_get_all_server_addrs");
|
||||
krb5_err(context, 1, ret, "krb5_get_all_server_addrs");
|
||||
}
|
||||
n = addrs.len;
|
||||
|
||||
sockets = malloc (n * sizeof(*sockets));
|
||||
sockets = malloc(n * sizeof(*sockets));
|
||||
if (sockets == NULL)
|
||||
krb5_errx (context, 1, "out of memory");
|
||||
krb5_errx(context, 1, "out of memory");
|
||||
maxfd = -1;
|
||||
FD_ZERO(&real_fdset);
|
||||
for (i = 0; i < n; ++i) {
|
||||
krb5_socklen_t sa_size = sizeof(__ss);
|
||||
|
||||
krb5_addr2sockaddr (context, &addrs.val[i], sa, &sa_size, port);
|
||||
krb5_addr2sockaddr(context, &addrs.val[i], sa, &sa_size, port);
|
||||
|
||||
sockets[i] = socket (__ss.ss_family, SOCK_DGRAM, 0);
|
||||
sockets[i] = socket(__ss.ss_family, SOCK_DGRAM, 0);
|
||||
if (sockets[i] < 0)
|
||||
krb5_err (context, 1, errno, "socket");
|
||||
if (bind (sockets[i], sa, sa_size) < 0) {
|
||||
krb5_err(context, 1, errno, "socket");
|
||||
if (bind(sockets[i], sa, sa_size) < 0) {
|
||||
char str[128];
|
||||
size_t len;
|
||||
int save_errno = errno;
|
||||
|
||||
ret = krb5_print_address (&addrs.val[i], str, sizeof(str), &len);
|
||||
ret = krb5_print_address(&addrs.val[i], str, sizeof(str), &len);
|
||||
if (ret)
|
||||
strlcpy(str, "unknown address", sizeof(str));
|
||||
krb5_warn (context, save_errno, "bind(%s)", str);
|
||||
krb5_warn(context, save_errno, "bind(%s)", str);
|
||||
continue;
|
||||
}
|
||||
maxfd = max (maxfd, sockets[i]);
|
||||
maxfd = max(maxfd, sockets[i]);
|
||||
if (maxfd >= FD_SETSIZE)
|
||||
krb5_errx (context, 1, "fd too large");
|
||||
krb5_errx(context, 1, "fd too large");
|
||||
FD_SET(sockets[i], &real_fdset);
|
||||
}
|
||||
if (maxfd == -1)
|
||||
krb5_errx (context, 1, "No sockets!");
|
||||
krb5_errx(context, 1, "No sockets!");
|
||||
|
||||
while(exit_flag == 0) {
|
||||
roken_detach_finish(NULL, daemon_child);
|
||||
|
||||
while (exit_flag == 0) {
|
||||
krb5_ssize_t retx;
|
||||
fd_set fdset = real_fdset;
|
||||
|
||||
retx = select (maxfd + 1, &fdset, NULL, NULL, NULL);
|
||||
retx = select(maxfd + 1, &fdset, NULL, NULL, NULL);
|
||||
if (retx < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
else
|
||||
krb5_err (context, 1, errno, "select");
|
||||
krb5_err(context, 1, errno, "select");
|
||||
}
|
||||
for (i = 0; i < n; ++i)
|
||||
if (FD_ISSET(sockets[i], &fdset)) {
|
||||
@@ -716,13 +756,13 @@ doit (krb5_keytab keytab, int port)
|
||||
retx = recvfrom(sockets[i], buf, sizeof(buf), 0,
|
||||
sa, &addrlen);
|
||||
if (retx < 0) {
|
||||
if(errno == EINTR)
|
||||
if (errno == EINTR)
|
||||
break;
|
||||
else
|
||||
krb5_err (context, 1, errno, "recvfrom");
|
||||
krb5_err(context, 1, errno, "recvfrom");
|
||||
}
|
||||
|
||||
process (keytab, sockets[i],
|
||||
process(keytab, sockets[i],
|
||||
&addrs.val[i],
|
||||
sa, addrlen,
|
||||
buf, retx);
|
||||
@@ -733,8 +773,8 @@ doit (krb5_keytab keytab, int port)
|
||||
close(sockets[i]);
|
||||
free(sockets);
|
||||
|
||||
krb5_free_addresses (context, &addrs);
|
||||
krb5_free_context (context);
|
||||
krb5_free_addresses(context, &addrs);
|
||||
krb5_free_context(context);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -744,40 +784,8 @@ sigterm(int sig)
|
||||
exit_flag = 1;
|
||||
}
|
||||
|
||||
static const char *check_library = NULL;
|
||||
static const char *check_function = NULL;
|
||||
static getarg_strings policy_libraries = { 0, NULL };
|
||||
static char sHDB[] = "HDBGET:";
|
||||
static char *keytab_str = sHDB;
|
||||
static char *realm_str;
|
||||
static int version_flag;
|
||||
static int help_flag;
|
||||
static char *port_str;
|
||||
static char *config_file;
|
||||
|
||||
struct getargs args[] = {
|
||||
#ifdef HAVE_DLOPEN
|
||||
{ "check-library", 0, arg_string, &check_library,
|
||||
"library to load password check function from", "library" },
|
||||
{ "check-function", 0, arg_string, &check_function,
|
||||
"password check function to load", "function" },
|
||||
{ "policy-libraries", 0, arg_strings, &policy_libraries,
|
||||
"password check function to load", "function" },
|
||||
#endif
|
||||
{ "addresses", 0, arg_strings, &addresses_str,
|
||||
"addresses to listen on", "list of addresses" },
|
||||
{ "keytab", 'k', arg_string, &keytab_str,
|
||||
"keytab to get authentication key from", "kspec" },
|
||||
{ "config-file", 'c', arg_string, &config_file, NULL, NULL },
|
||||
{ "realm", 'r', arg_string, &realm_str, "default realm", "realm" },
|
||||
{ "port", 'p', arg_string, &port_str, "port", NULL },
|
||||
{ "version", 0, arg_flag, &version_flag, NULL, NULL },
|
||||
{ "help", 0, arg_flag, &help_flag, NULL, NULL }
|
||||
};
|
||||
int num_args = sizeof(args) / sizeof(args[0]);
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
krb5_keytab keytab;
|
||||
krb5_error_code ret;
|
||||
@@ -787,13 +795,17 @@ main (int argc, char **argv)
|
||||
|
||||
krb5_program_setup(&context, argc, argv, args, num_args, NULL);
|
||||
|
||||
if(help_flag)
|
||||
if (help_flag)
|
||||
krb5_std_usage(0, args, num_args);
|
||||
if(version_flag) {
|
||||
|
||||
if (version_flag) {
|
||||
print_version(NULL);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (detach_from_console > 0 && daemon_child == -1)
|
||||
roken_detach_prep(argc, argv, "--daemon-child");
|
||||
|
||||
if (config_file == NULL) {
|
||||
aret = asprintf(&config_file, "%s/kdc.conf", hdb_db_dir(context));
|
||||
if (aret == -1)
|
||||
@@ -809,37 +821,37 @@ main (int argc, char **argv)
|
||||
if (ret)
|
||||
krb5_err(context, 1, ret, "reading configuration files");
|
||||
|
||||
if(realm_str)
|
||||
if (realm_str)
|
||||
krb5_set_default_realm(context, realm_str);
|
||||
|
||||
krb5_openlog (context, "kpasswdd", &log_facility);
|
||||
krb5_openlog(context, "kpasswdd", &log_facility);
|
||||
krb5_set_warn_dest(context, log_facility);
|
||||
|
||||
if (port_str != NULL) {
|
||||
struct servent *s = roken_getservbyname (port_str, "udp");
|
||||
struct servent *s = roken_getservbyname(port_str, "udp");
|
||||
|
||||
if (s != NULL)
|
||||
port = s->s_port;
|
||||
else {
|
||||
char *ptr;
|
||||
|
||||
port = strtol (port_str, &ptr, 10);
|
||||
port = strtol(port_str, &ptr, 10);
|
||||
if (port == 0 && ptr == port_str)
|
||||
krb5_errx (context, 1, "bad port `%s'", port_str);
|
||||
krb5_errx(context, 1, "bad port `%s'", port_str);
|
||||
port = htons(port);
|
||||
}
|
||||
} else
|
||||
port = krb5_getportbyname (context, "kpasswd", "udp", KPASSWD_PORT);
|
||||
port = krb5_getportbyname(context, "kpasswd", "udp", KPASSWD_PORT);
|
||||
|
||||
ret = krb5_kt_register(context, &hdb_get_kt_ops);
|
||||
if(ret)
|
||||
if (ret)
|
||||
krb5_err(context, 1, ret, "krb5_kt_register");
|
||||
|
||||
ret = krb5_kt_resolve(context, keytab_str, &keytab);
|
||||
if(ret)
|
||||
if (ret)
|
||||
krb5_err(context, 1, ret, "%s", keytab_str);
|
||||
|
||||
kadm5_setup_passwd_quality_check (context, check_library, check_function);
|
||||
kadm5_setup_passwd_quality_check(context, check_library, check_function);
|
||||
|
||||
for (i = 0; i < policy_libraries.num_strings; i++) {
|
||||
ret = kadm5_add_passwd_quality_verifier(context,
|
||||
@@ -858,16 +870,16 @@ main (int argc, char **argv)
|
||||
int j;
|
||||
|
||||
for (j = 0; j < addresses_str.num_strings; ++j)
|
||||
add_one_address (addresses_str.strings[j], j == 0);
|
||||
free_getarg_strings (&addresses_str);
|
||||
add_one_address(addresses_str.strings[j], j == 0);
|
||||
free_getarg_strings(&addresses_str);
|
||||
} else {
|
||||
char **foo = krb5_config_get_strings (context, NULL,
|
||||
char **foo = krb5_config_get_strings(context, NULL,
|
||||
"kdc", "addresses", NULL);
|
||||
|
||||
if (foo != NULL) {
|
||||
add_one_address (*foo++, TRUE);
|
||||
add_one_address(*foo++, TRUE);
|
||||
while (*foo)
|
||||
add_one_address (*foo++, FALSE);
|
||||
add_one_address(*foo++, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -889,5 +901,5 @@ main (int argc, char **argv)
|
||||
|
||||
pidfile(NULL);
|
||||
|
||||
return doit (keytab, port);
|
||||
return doit(keytab, port);
|
||||
}
|
||||
|
@@ -929,9 +929,8 @@ static char *keytab_str = sHDB;
|
||||
static char *database;
|
||||
static char *config_file;
|
||||
static char *port_str;
|
||||
#ifdef SUPPORT_DETACH
|
||||
static int detach_from_console = 0;
|
||||
#endif
|
||||
static int detach_from_console;
|
||||
static int daemon_child = -1;
|
||||
|
||||
static struct getargs args[] = {
|
||||
{ "config-file", 'c', arg_string, &config_file, NULL, NULL },
|
||||
@@ -947,10 +946,10 @@ static struct getargs args[] = {
|
||||
"time of inactivity after which a slave is considered gone", "time"},
|
||||
{ "port", 0, arg_string, &port_str,
|
||||
"port ipropd will listen to", "port"},
|
||||
#ifdef SUPPORT_DETACH
|
||||
{ "detach", 0, arg_flag, &detach_from_console,
|
||||
"detach from console", NULL },
|
||||
#endif
|
||||
{ "daemon-child", 0 , arg_integer, &daemon_child,
|
||||
"private argument, do not use", NULL },
|
||||
{ "hostname", 0, arg_string, rk_UNCONST(&master_hostname),
|
||||
"hostname of master (if not same as hostname)", "hostname" },
|
||||
{ "version", 0, arg_flag, &version_flag, NULL, NULL },
|
||||
@@ -973,16 +972,29 @@ main(int argc, char **argv)
|
||||
krb5_keytab keytab;
|
||||
char **files;
|
||||
int aret;
|
||||
int optidx = 0;
|
||||
|
||||
(void) krb5_program_setup(&context, argc, argv, args, num_args, NULL);
|
||||
setprogname(argv[0]);
|
||||
|
||||
if(help_flag)
|
||||
if (getarg(args, num_args, argc, argv, &optidx))
|
||||
krb5_std_usage(1, args, num_args);
|
||||
|
||||
if (help_flag)
|
||||
krb5_std_usage(0, args, num_args);
|
||||
if(version_flag) {
|
||||
|
||||
if (version_flag) {
|
||||
print_version(NULL);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (detach_from_console && daemon_child == -1)
|
||||
roken_detach_prep(argc, argv, "--daemon-child");
|
||||
pidfile(NULL);
|
||||
|
||||
ret = krb5_init_context(&context);
|
||||
if (ret)
|
||||
errx(1, "krb5_init_context failed: %d", ret);
|
||||
|
||||
setup_signal();
|
||||
|
||||
if (config_file == NULL) {
|
||||
@@ -1007,17 +1019,7 @@ main(int argc, char **argv)
|
||||
if (time_before_missing < 0)
|
||||
krb5_errx (context, 1, "couldn't parse time: %s", slave_time_missing);
|
||||
|
||||
#ifdef SUPPORT_DETACH
|
||||
if (detach_from_console) {
|
||||
aret = daemon(0, 0);
|
||||
if (aret == -1) {
|
||||
/* not much to do if detaching fails... */
|
||||
krb5_err(context, 1, aret, "failed to daemon(3)ise");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
pidfile (NULL);
|
||||
krb5_openlog (context, "ipropd-master", &log_facility);
|
||||
krb5_openlog(context, "ipropd-master", &log_facility);
|
||||
krb5_set_warn_dest(context, log_facility);
|
||||
|
||||
ret = krb5_kt_register(context, &hdb_get_kt_ops);
|
||||
@@ -1059,7 +1061,9 @@ main(int argc, char **argv)
|
||||
krb5_warnx(context, "ipropd-master started at version: %lu",
|
||||
(unsigned long)current_version);
|
||||
|
||||
while(exit_flag == 0){
|
||||
roken_detach_finish(NULL, daemon_child);
|
||||
|
||||
while (exit_flag == 0){
|
||||
slave *p;
|
||||
fd_set readset;
|
||||
int max_fd = 0;
|
||||
|
@@ -514,9 +514,8 @@ static int version_flag;
|
||||
static int help_flag;
|
||||
static char *keytab_str;
|
||||
static char *port_str;
|
||||
#ifdef SUPPORT_DETACH
|
||||
static int detach_from_console = 0;
|
||||
#endif
|
||||
static int detach_from_console;
|
||||
static int daemon_child = -1;
|
||||
|
||||
static struct getargs args[] = {
|
||||
{ "config-file", 'c', arg_string, &config_file, NULL, NULL },
|
||||
@@ -529,10 +528,10 @@ static struct getargs args[] = {
|
||||
"file to write out status into", "file" },
|
||||
{ "port", 0, arg_string, &port_str,
|
||||
"port ipropd-slave will connect to", "port"},
|
||||
#ifdef SUPPORT_DETACH
|
||||
{ "detach", 0, arg_flag, &detach_from_console,
|
||||
"detach from console", NULL },
|
||||
#endif
|
||||
{ "daemon-child", 0 , arg_integer, &daemon_child,
|
||||
"private argument, do not use", NULL },
|
||||
{ "hostname", 0, arg_string, rk_UNCONST(&slave_str),
|
||||
"hostname of slave (if not same as hostname)", "hostname" },
|
||||
{ "version", 0, arg_flag, &version_flag, NULL, NULL },
|
||||
@@ -572,16 +571,21 @@ main(int argc, char **argv)
|
||||
|
||||
setprogname(argv[0]);
|
||||
|
||||
if(getarg(args, num_args, argc, argv, &optidx))
|
||||
if (getarg(args, num_args, argc, argv, &optidx))
|
||||
usage(1);
|
||||
|
||||
if(help_flag)
|
||||
if (help_flag)
|
||||
usage(0);
|
||||
if(version_flag) {
|
||||
|
||||
if (version_flag) {
|
||||
print_version(NULL);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (detach_from_console && daemon_child == -1)
|
||||
roken_detach_prep(argc, argv, "--daemon-child");
|
||||
pidfile(NULL);
|
||||
|
||||
ret = krb5_init_context(&context);
|
||||
if (ret)
|
||||
errx (1, "krb5_init_context failed: %d", ret);
|
||||
@@ -616,17 +620,7 @@ main(int argc, char **argv)
|
||||
krb5_errx(context, 1, "can't allocate status file buffer");
|
||||
}
|
||||
|
||||
#ifdef SUPPORT_DETACH
|
||||
if (detach_from_console){
|
||||
int aret = daemon(0, 0);
|
||||
if (aret == -1) {
|
||||
/* not much to do if detaching fails... */
|
||||
krb5_err(context, 1, aret, "failed to daemon(3)ise");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
pidfile (NULL);
|
||||
krb5_openlog (context, "ipropd-slave", &log_facility);
|
||||
krb5_openlog(context, "ipropd-slave", &log_facility);
|
||||
krb5_set_warn_dest(context, log_facility);
|
||||
|
||||
slave_status(context, status_file, "bootstrapping");
|
||||
@@ -683,6 +677,8 @@ main(int argc, char **argv)
|
||||
|
||||
slave_status(context, status_file, "ipropd-slave started");
|
||||
|
||||
roken_detach_finish(NULL, daemon_child);
|
||||
|
||||
while (!exit_flag) {
|
||||
time_t now, elapsed;
|
||||
int connected = FALSE;
|
||||
|
@@ -1609,7 +1609,7 @@ make_rules_safe(krb5_context context, krb5_name_canon_rule rules)
|
||||
* conversion. Better let the user get failures and make them think about
|
||||
* their naming rules.
|
||||
*/
|
||||
if (rules != NULL)
|
||||
if (rules == NULL)
|
||||
return;
|
||||
for (; rules[0].type != KRB5_NCRT_BOGUS; rules++) {
|
||||
if (rules->type == KRB5_NCRT_NSS)
|
||||
@@ -1843,7 +1843,7 @@ apply_name_canon_rule(krb5_context context, krb5_name_canon_rule rules,
|
||||
}
|
||||
|
||||
/* If we stripped off a :port, add it back in */
|
||||
if (port != NULL) {
|
||||
if (port != NULL && new_hostname != NULL) {
|
||||
if (asprintf(&hostname_with_port, "%s%s", new_hostname, port) == -1 ||
|
||||
hostname_with_port == NULL) {
|
||||
ret = krb5_enomem(context);
|
||||
|
@@ -20,7 +20,9 @@ if HAVE_DBHEADER
|
||||
AM_CPPFLAGS += -I$(DBHEADER)
|
||||
endif
|
||||
|
||||
noinst_PROGRAMS = snprintf-test resolve-test rkpty
|
||||
noinst_PROGRAMS = snprintf-test resolve-test rkpty test-detach
|
||||
|
||||
CHECK_LOCAL = snprintf-test resolve-test rkpty make-roken
|
||||
|
||||
check_PROGRAMS = \
|
||||
base64-test \
|
||||
@@ -50,6 +52,8 @@ parse_reply_test_CFLAGS = -DTEST_RESOLVE
|
||||
|
||||
test_readenv_SOURCES = test-readenv.c test-mem.c
|
||||
|
||||
test_detach_SOURCES = test-detach.c
|
||||
|
||||
rkpty_LDADD = $(LIB_openpty) $(LDADD)
|
||||
|
||||
parse_time_test_SOURCES = parse_time-test.c test-mem.c
|
||||
@@ -75,6 +79,7 @@ libroken_la_SOURCES = \
|
||||
concat.c \
|
||||
cloexec.c \
|
||||
ct.c \
|
||||
detach.c \
|
||||
doxygen.c \
|
||||
dumpdata.c \
|
||||
environment.c \
|
||||
|
@@ -39,6 +39,7 @@ libroken_la_OBJS = \
|
||||
$(OBJ)\concat.obj \
|
||||
$(OBJ)\cloexec.obj \
|
||||
$(OBJ)\ct.obj \
|
||||
$(OBJ)\detach.obj \
|
||||
$(OBJ)\dirent.obj \
|
||||
$(OBJ)\dlfcn_w32.obj \
|
||||
$(OBJ)\dumpdata.obj \
|
||||
@@ -189,6 +190,7 @@ TEST_PROGS = \
|
||||
$(OBJ)\getaddrinfo-test.exe \
|
||||
$(OBJ)\getifaddrs-test.exe \
|
||||
$(OBJ)\hex-test.exe \
|
||||
$(OBJ)\test-detach.exe \
|
||||
$(OBJ)\test-readenv.exe \
|
||||
$(OBJ)\parse_bytes-test.exe \
|
||||
$(OBJ)\parse_reply-test.exe \
|
||||
@@ -252,6 +254,9 @@ $(OBJ)\hex-test.exe: $(OBJ)\hex-test.obj $(LIBROKEN)
|
||||
$(OBJ)\parse_bytes-test.exe: $(OBJ)\parse_bytes-test.obj $(LIBROKEN)
|
||||
$(EXECONLINK)
|
||||
|
||||
$(OBJ)\test-detach.exe: $(OBJ)\test-detach.obj $(OBJ)\detach.obj $(LIBROKEN)
|
||||
$(EXECONLINK)
|
||||
|
||||
$(OBJ)\dirent-test.exe: $(OBJ)\dirent-test.obj $(LIBROKEN)
|
||||
$(EXECONLINK)
|
||||
|
||||
|
@@ -72,7 +72,7 @@ daemon(int nochdir, int noclose)
|
||||
dup2(fd, STDOUT_FILENO);
|
||||
dup2(fd, STDERR_FILENO);
|
||||
if (fd > 2)
|
||||
close (fd);
|
||||
(void) close(fd);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
211
lib/roken/detach.c
Normal file
211
lib/roken/detach.c
Normal file
@@ -0,0 +1,211 @@
|
||||
/*-
|
||||
* Copyright (c) 2015
|
||||
* Cryptonector LLC. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Cryptonector LLC may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#ifdef WIN32
|
||||
#include <io.h>
|
||||
#include <stdlib.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include "roken.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#define dup2 _dup2
|
||||
#endif
|
||||
|
||||
static int pipefds[2] = {-1, -1};
|
||||
|
||||
ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
|
||||
roken_detach_prep(int argc, char **argv, char *special_arg)
|
||||
{
|
||||
pid_t child;
|
||||
char buf[1];
|
||||
ssize_t bytes;
|
||||
int status;
|
||||
|
||||
pipefds[0] = -1;
|
||||
pipefds[1] = -1;
|
||||
|
||||
#ifdef WIN32
|
||||
if (_pipe(pipefds, 4, O_BINARY) == -1)
|
||||
err(1, "failed to setup to detach daemon (_pipe failed)");
|
||||
#else
|
||||
if (pipe(pipefds) == -1)
|
||||
err(1, "failed to setup to detach daemon (pipe failed)");
|
||||
#endif
|
||||
|
||||
#ifndef WIN32
|
||||
fflush(stdout);
|
||||
child = fork();
|
||||
#else
|
||||
{
|
||||
intptr_t child_handle;
|
||||
int write_side;
|
||||
size_t i;
|
||||
char *fildes;
|
||||
char **new_argv;
|
||||
|
||||
new_argv = calloc(argc + 2, sizeof(*new_argv));
|
||||
if (new_argv == NULL)
|
||||
err(1, "Out of memory");
|
||||
|
||||
write_side = _dup(pipefds[1]); /* The new fd will be inherited */
|
||||
if (write_side == -1)
|
||||
err(1, "Out of memory");
|
||||
|
||||
if (asprintf(&fildes, "%d", write_side) == -1 ||
|
||||
fildes == NULL)
|
||||
err(1, "failed to setup to detach daemon (_dup failed)");
|
||||
|
||||
new_argv[0] = argv[0];
|
||||
new_argv[1] = special_arg;
|
||||
new_argv[2] = fildes;
|
||||
for (i = 1; argv[i] != NULL; i++)
|
||||
new_argv[i + 1] = argv[i];
|
||||
new_argv[argc + 2] = NULL;
|
||||
|
||||
_flushall();
|
||||
child_handle = spawnvp(_P_NOWAIT, argv[0], new_argv);
|
||||
if (child_handle == -1)
|
||||
child = (pid_t)-1;
|
||||
else
|
||||
child = GetProcessId((HANDLE)child_handle);
|
||||
}
|
||||
#endif
|
||||
if (child == (pid_t)-1)
|
||||
err(1, "failed to setup to fork daemon (fork failed)");
|
||||
|
||||
#ifndef WIN32
|
||||
if (child == 0) {
|
||||
int fd;
|
||||
|
||||
(void) close(pipefds[0]);
|
||||
pipefds[0] = -1;
|
||||
/*
|
||||
* Keep stdout/stderr for now so output and errors prior to
|
||||
* detach_finish() can be seen by the user.
|
||||
*/
|
||||
fd = open(_PATH_DEVNULL, O_RDWR, 0);
|
||||
if (fd == -1)
|
||||
err(1, "failed to open /dev/null");
|
||||
(void) dup2(fd, STDIN_FILENO);
|
||||
if (fd > STDERR_FILENO)
|
||||
(void) close(fd);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
(void) close(pipefds[1]);
|
||||
pipefds[1] = -1;
|
||||
do {
|
||||
bytes = read(pipefds[0], buf, sizeof(buf));
|
||||
} while (bytes == -1 && errno == EINTR);
|
||||
if (bytes == -1) {
|
||||
/*
|
||||
* No need to wait for the process. We've killed it. If it
|
||||
* doesn't want to exit, we'd have to wait potentially forever,
|
||||
* but we want to indicate failure to the user as soon as
|
||||
* possible. A wait with timeout would end the same way
|
||||
* (attempting to kill the process).
|
||||
*/
|
||||
err(1, "failed to setup daemon child (read from child pipe)");
|
||||
}
|
||||
if (bytes == 0) {
|
||||
warnx("daemon child preparation failed, waiting for child");
|
||||
status = wait_for_process(child);
|
||||
if (SE_IS_ERROR(status) || SE_PROCSTATUS(status) != 0)
|
||||
errx(SE_PROCSTATUS(status),
|
||||
"daemon child preparation failed (child exited)");
|
||||
}
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
#ifdef dup2
|
||||
#undef dup2
|
||||
#endif
|
||||
#define dup2 _dup2
|
||||
#endif
|
||||
|
||||
ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
|
||||
roken_detach_finish(const char *dir, int daemon_child_fd)
|
||||
{
|
||||
char buf[1];
|
||||
ssize_t bytes;
|
||||
int fd;
|
||||
|
||||
if (pipefds[1] == -1 && daemon_child_fd != -1)
|
||||
pipefds[1] = daemon_child_fd;
|
||||
if (pipefds[0] != -1)
|
||||
(void) close(pipefds[0]);
|
||||
if (pipefds[1] == -1)
|
||||
return;
|
||||
|
||||
#ifdef HAVE_SETSID
|
||||
if (setsid() == -1)
|
||||
err(1, "failed to detach from tty");
|
||||
#endif
|
||||
|
||||
#ifndef WIN32
|
||||
/*
|
||||
* Hopefully we've written any pidfiles by now, if they had to be in
|
||||
* the current directory...
|
||||
*
|
||||
* The daemons do re-open logs and so on, therefore this chdir()
|
||||
* call needs to be optional for testing.
|
||||
*/
|
||||
if (dir != NULL && chdir(dir) == -1)
|
||||
err(1, "failed to chdir to /");
|
||||
#endif
|
||||
|
||||
buf[1] = 0;
|
||||
do {
|
||||
bytes = write(pipefds[1], buf, sizeof(buf));
|
||||
} while (bytes == -1 && errno == EINTR);
|
||||
if (bytes == -1)
|
||||
err(1, "failed to signal parent while detaching");
|
||||
(void) close(pipefds[1]);
|
||||
if (bytes != sizeof(buf))
|
||||
errx(1, "failed to signal parent while detaching");
|
||||
|
||||
fd = open(_PATH_DEVNULL, O_RDWR, 0);
|
||||
if (fd == -1)
|
||||
err(1, "failed to open /dev/null");
|
||||
/*
|
||||
* Maybe we should check that our output got written, if redirected
|
||||
* to a file. File utils normally do this.
|
||||
*/
|
||||
(void) dup2(fd, STDOUT_FILENO);
|
||||
(void) dup2(fd, STDERR_FILENO);
|
||||
if (fd > 2)
|
||||
(void) close(fd);
|
||||
}
|
@@ -595,7 +595,7 @@ struct getargs args[] = {
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int goptind = 0;
|
||||
while(getarg(args, 5, argc, argv, &goptind))
|
||||
while (getarg(args, 5, argc, argv, &goptind))
|
||||
printf("Bad arg: %s\n", argv[goptind]);
|
||||
printf("flag1 = %d\n", flag1);
|
||||
printf("flag2 = %d\n", flag2);
|
||||
|
@@ -126,7 +126,11 @@
|
||||
#define O_NOFOLLOW 0
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
#ifdef _WIN32
|
||||
|
||||
#define _PATH_DEVNULL "\\\\.\\NUL"
|
||||
|
||||
#else
|
||||
|
||||
#ifndef _PATH_DEV
|
||||
#define _PATH_DEV "/dev/"
|
||||
|
@@ -810,6 +810,9 @@ ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL roken_vconcat (char *, size_t, va_list);
|
||||
ROKEN_LIB_FUNCTION size_t ROKEN_LIB_CALL
|
||||
roken_vmconcat (char **, size_t, va_list);
|
||||
|
||||
ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL roken_detach_prep(int, char **, char *);
|
||||
ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL roken_detach_finish(const char *, int);
|
||||
|
||||
ROKEN_LIB_FUNCTION ssize_t ROKEN_LIB_CALL
|
||||
net_write (rk_socket_t, const void *, size_t);
|
||||
|
||||
|
82
lib/roken/test-detach.c
Normal file
82
lib/roken/test-detach.c
Normal file
@@ -0,0 +1,82 @@
|
||||
/***********************************************************************
|
||||
* Copyright (c) 2015, Cryptonector LLC
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
**********************************************************************/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <err.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#ifdef WIN32
|
||||
#include <process.h>
|
||||
#ifdef getpid
|
||||
#undef getpid
|
||||
#endif
|
||||
#define getpid _getpid
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include "roken.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char *ends;
|
||||
long n;
|
||||
int fd = -1;
|
||||
|
||||
if (argc > 1) {
|
||||
if (argc != 3)
|
||||
errx(1, "Usage: test-detach [--daemon-child fd]");
|
||||
fprintf(stderr, "Child started (argv[1] = %s, argv[2] = %s)!\n", argv[1], argv[2]);
|
||||
errno = 0;
|
||||
n = strtol(argv[2], &ends, 10);
|
||||
fd = n;
|
||||
if (errno != 0)
|
||||
err(1, "Usage: test-detach [--daemon-child fd]");
|
||||
if (n < 0 || ends == NULL || *ends != '\0' || n != fd)
|
||||
errx(1, "Usage: test-detach [--daemon-child fd]");
|
||||
} else {
|
||||
fprintf(stderr, "Parent started as %ld\n", (long)getpid());
|
||||
roken_detach_prep(argc, argv, "--daemon-child");
|
||||
}
|
||||
fprintf(stderr, "Now should be the child: %ld\n", (long)getpid());
|
||||
roken_detach_finish(NULL, fd);
|
||||
/*
|
||||
* These printfs will not appear: stderr will have been replaced
|
||||
* with /dev/null.
|
||||
*/
|
||||
fprintf(stderr, "Now should be the child: %ld, wrote to parent\n", (long)getpid());
|
||||
sleep(5);
|
||||
fprintf(stderr, "Daemon child done\n");
|
||||
return 0;
|
||||
}
|
@@ -162,6 +162,8 @@ HEIMDAL_ROKEN_1.0 {
|
||||
rk_warnerr;
|
||||
rk_xfree;
|
||||
roken_concat;
|
||||
roken_detach_prep;
|
||||
roken_detach_finish;
|
||||
roken_getaddrinfo_hostspec2;
|
||||
roken_getaddrinfo_hostspec;
|
||||
roken_gethostby_setup;
|
||||
|
@@ -36,29 +36,42 @@
|
||||
#include "roken.h"
|
||||
|
||||
ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL
|
||||
pid_file_write (const char *progname)
|
||||
pid_file_write(const char *progname)
|
||||
{
|
||||
const char *pidfile_dir = NULL;
|
||||
char *ret = NULL;
|
||||
FILE *fp;
|
||||
|
||||
if (asprintf (&ret, "%s%s.pid", _PATH_VARRUN, progname) < 0 || ret == NULL)
|
||||
/*
|
||||
* Maybe we could have a version of this function (and pidfile())
|
||||
* where we get a directory from the caller. That would allow us to
|
||||
* have command-line options for the daemons for this.
|
||||
*
|
||||
* For now we use an environment variable.
|
||||
*/
|
||||
if (!issuid())
|
||||
pidfile_dir = getenv("HEIM_PIDFILE_DIR");
|
||||
if (pidfile_dir == NULL)
|
||||
pidfile_dir = _PATH_VARRUN;
|
||||
|
||||
if (asprintf(&ret, "%s%s.pid", pidfile_dir, progname) < 0 || ret == NULL)
|
||||
return NULL;
|
||||
fp = fopen (ret, "w");
|
||||
fp = fopen(ret, "w");
|
||||
if (fp == NULL) {
|
||||
free (ret);
|
||||
free(ret);
|
||||
return NULL;
|
||||
}
|
||||
fprintf (fp, "%u", (unsigned)getpid());
|
||||
fclose (fp);
|
||||
fprintf(fp, "%u", (unsigned)getpid());
|
||||
fclose(fp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
|
||||
pid_file_delete (char **filename)
|
||||
pid_file_delete(char **filename)
|
||||
{
|
||||
if (*filename != NULL) {
|
||||
unlink (*filename);
|
||||
free (*filename);
|
||||
unlink(*filename);
|
||||
free(*filename);
|
||||
*filename = NULL;
|
||||
}
|
||||
}
|
||||
@@ -69,16 +82,16 @@ static char *pidfile_path;
|
||||
static void
|
||||
pidfile_cleanup(void)
|
||||
{
|
||||
if(pidfile_path != NULL)
|
||||
if (pidfile_path != NULL)
|
||||
pid_file_delete(&pidfile_path);
|
||||
}
|
||||
|
||||
ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
|
||||
pidfile(const char *bname)
|
||||
{
|
||||
if(pidfile_path != NULL)
|
||||
if (pidfile_path != NULL)
|
||||
return;
|
||||
if(bname == NULL)
|
||||
if (bname == NULL)
|
||||
bname = getprogname();
|
||||
pidfile_path = pid_file_write(bname);
|
||||
#if defined(HAVE_ATEXIT)
|
||||
|
Reference in New Issue
Block a user