#if defined(DARWIN)
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include "config.h"
#include "distcc.h"
#include "dopt.h"
#include "exitcode.h"
#include "io.h"
#include "rpc.h"
#include "setuid.h"
#include "srvnet.h"
#include "trace.h"
#include "util.h"
#include "zeroconf_browse.h"
#include "zeroconf_util.h"
const char *rs_program_name = "distccschedd";
static void dcc_zc_process_messages(int clientFD);
static void dccschedd_setup_log(void);
void dcc_detach(void);
void dcc_reap_kids(void);
int main(int argc, char *argv[])
{
int listen_fd;
int ret;
char *zcTxtRecord;
rs_trace_set_level(RS_LOG_INFO);
rs_add_logger(rs_logger_file, RS_LOG_DEBUG, 0, STDERR_FILENO);
if (distccd_parse_options(argc, (const char **) argv))
dcc_exit(EXIT_DISTCC_FAILED);
if ((ret = dcc_discard_root()) != 0)
dcc_exit(ret);
dccschedd_setup_log();
if ((listen_fd = open_socket_in(DISTCC_DEFAULT_SCHEDULER_PORT)) == -1)
return EXIT_BIND_FAILED;
set_cloexec_flag(listen_fd, 1);
rs_log(RS_LOG_INFO|RS_LOG_NONAME,
"%s (version %s, built %s %s) listening on port %d",
rs_program_name, PACKAGE_VERSION, __DATE__, __TIME__, DISTCC_DEFAULT_SCHEDULER_PORT);
dcc_catch_signals();
zcTxtRecord = dcc_generate_txt_record();
if (!opt_no_detach) {
dcc_detach();
chdir("/");
}
dcc_browse_for_zeroconfig(zcTxtRecord);
dcc_zc_process_messages(listen_fd);
free(zcTxtRecord);
return 0;
}
static void dccschedd_setup_log(void)
{
int fd;
if (opt_log_stderr)
return;
if (arg_log_file) {
if ((fd = open(arg_log_file, O_CREAT|O_APPEND|O_WRONLY, 0666)) == -1) {
rs_log_error("failed to open %s: %s", arg_log_file,
strerror(errno));
} else {
rs_remove_all_loggers();
rs_add_logger(rs_logger_file, RS_LOG_DEBUG, NULL, fd);
return;
}
}
openlog("distccschedd", LOG_PID, LOG_DAEMON);
rs_remove_all_loggers();
rs_add_logger(rs_logger_syslog, RS_LOG_DEBUG, NULL, 0);
}
static int dcc_zc_accept_request(int queuedFD)
{
int exitVal;
char *list = dcc_zc_resolved_services_list();
size_t len = strlen(list) + 1;
rs_trace("Transmitting service list length: %u", len);
exitVal = dcc_x_token_int(queuedFD, DISTCC_DEFAULT_ZC_LIST_LEN_TOKEN, len);
if ( exitVal == 0 ) {
rs_trace("Transmitted service list length, transmitting list: %s",
list);
exitVal = dcc_writex(queuedFD, list, len);
if ( exitVal == 0 ) {
rs_trace("Transmitted service list.");
} else {
rs_log_error("Failed to transmit service list: (%d) %s", exitVal,
strerror(exitVal));
}
} else {
rs_log_error("Failed to transmit service list length: (%d) %s",
exitVal, strerror(exitVal));
}
return exitVal;
}
static void dcc_zc_serve_connection(int clientFD)
{
int queuedFD = accept(clientFD, NULL, 0);
if ( queuedFD == -1 ) {
rs_log_error("Failure processing client connection: (%d) %s",
errno, strerror(errno));
} else {
if ( opt_no_fork ) {
dcc_zc_accept_request(queuedFD);
} else {
int pid = fork();
if ( pid < 0 ) {
rs_log_error("Unable to serve client connection: (%d) %s",
errno, strerror(errno));
} else if ( pid == 0 ) {
int exitVal = dcc_zc_accept_request(queuedFD);
close(queuedFD);
close(clientFD);
dcc_exit(exitVal);
} else {
rs_trace("Forked child to serve client connection (%d)", pid);
}
}
close(queuedFD);
}
if (!opt_no_fork) {
dcc_reap_kids();
}
}
static void dcc_zc_process_messages(int clientFD)
{
int exitVal;
int fdCount;
fd_set readFDs;
dcc_zc_add_to_select_set(clientFD);
rs_log_info("waiting to accept connection");
do {
FD_ZERO(&readFDs);
dcc_zc_select_set(&readFDs);
fdCount = dcc_zc_select_count();
exitVal = select(fdCount, &readFDs, NULL, NULL, NULL);
if ( exitVal == -1 ) {
rs_trace("Failure while processing messages: (%d) %s", exitVal,
strerror(exitVal));
} else if ( exitVal == 0 ) {
rs_trace("No messages available to process");
} else {
exitVal = dcc_zc_process_browse_messages(&readFDs, exitVal);
exitVal = dcc_zc_process_resolve_messages(&readFDs, exitVal);
if ( exitVal > 0 && FD_ISSET(clientFD, &readFDs) &&
dcc_zc_should_process_client_requests() ) {
dcc_zc_serve_connection(clientFD);
rs_log_info("waiting to accept more connections");
}
}
} while (TRUE);
}
#endif // DARWIN