#include "server.lsg.h"
#include "para.h"
#include "error.h"
+#include "lsu.h"
#include "crypt.h"
#include "afh.h"
#include "string.h"
/** The process id of the audio file selector process. */
pid_t afs_pid = 0;
-/* The the main server process (parent of afs and the command handlers). */
+/* The main server process (parent of afs and the command handlers). */
static pid_t server_pid;
/**
void parse_config_or_die(bool reload)
{
int ret;
- char *cf = NULL, *errctx = NULL, *user_list_file = NULL;
- void *map;
- size_t sz;
- int cf_argc;
- char **cf_argv;
- struct lls_parse_result *cf_lpr, *merged_lpr;
- char *home = para_homedir();
-
- if (OPT_GIVEN(CONFIG_FILE))
- cf = para_strdup(OPT_STRING_VAL(CONFIG_FILE));
- else
- cf = make_message("%s/.paraslash/server.conf", home);
- if (!mmd || getpid() != afs_pid) {
- if (OPT_GIVEN(USER_LIST))
- user_list_file = para_strdup(OPT_STRING_VAL(USER_LIST));
- else
- user_list_file = make_message("%s/.paraslash/server.users", home);
- }
- free(home);
- ret = mmap_full_file(cf, O_RDONLY, &map, &sz, NULL);
- if (ret < 0) {
- if (ret != -E_EMPTY && ret != -ERRNO_TO_PARA_ERROR(ENOENT))
- goto free_cf;
- if (ret == -ERRNO_TO_PARA_ERROR(ENOENT) && OPT_GIVEN(CONFIG_FILE))
- goto free_cf;
- server_lpr = cmdline_lpr;
- goto success;
- }
- ret = lls(lls_convert_config(map, sz, NULL, &cf_argv, &errctx));
- para_munmap(map, sz);
- if (ret < 0)
- goto free_cf;
- cf_argc = ret;
- ret = lls(lls_parse(cf_argc, cf_argv, CMD_PTR, &cf_lpr, &errctx));
- lls_free_argv(cf_argv);
- if (ret < 0)
- goto free_cf;
- if (reload) /* config file overrides command line */
- ret = lls(lls_merge(cf_lpr, cmdline_lpr, CMD_PTR, &merged_lpr,
- &errctx));
- else /* command line options override config file options */
- ret = lls(lls_merge(cmdline_lpr, cf_lpr, CMD_PTR, &merged_lpr,
- &errctx));
- lls_free_parse_result(cf_lpr, CMD_PTR);
- if (ret < 0)
- goto free_cf;
+ unsigned flags = MCF_DONT_FREE;
+
if (server_lpr != cmdline_lpr)
lls_free_parse_result(server_lpr, CMD_PTR);
- server_lpr = merged_lpr;
-success:
+ server_lpr = cmdline_lpr;
+ if (reload)
+ flags |= MCF_OVERRIDE;
+ ret = lsu_merge_config_file_options(OPT_STRING_VAL(CONFIG_FILE),
+ "server.conf", &server_lpr, CMD_PTR, server_suite, flags);
+ if (ret < 0) {
+ PARA_EMERG_LOG("failed to parse config file: %s\n",
+ para_strerror(-ret));
+ exit(EXIT_FAILURE);
+ }
daemon_set_loglevel(ENUM_STRING_VAL(LOGLEVEL));
if (OPT_GIVEN(LOGFILE)) {
daemon_set_logfile(OPT_STRING_VAL(LOGFILE));
if (OPT_GIVEN(LOG_TIMING))
daemon_set_flag(DF_LOG_TIMING);
daemon_set_priority(OPT_UINT32_VAL(PRIORITY));
- if (user_list_file)
+ if (!reload || getpid() != afs_pid) {
+ char *user_list_file;
+ if (OPT_GIVEN(USER_LIST))
+ user_list_file = para_strdup(OPT_STRING_VAL(USER_LIST));
+ else {
+ char *home = para_homedir();
+ user_list_file = make_message("%s/.paraslash/server.users", home);
+ free(home);
+ }
user_list_init(user_list_file);
- ret = 1;
-free_cf:
- free(cf);
- free(user_list_file);
- if (ret < 0) {
- if (errctx)
- PARA_ERROR_LOG("%s\n", errctx);
- free(errctx);
- PARA_EMERG_LOG("%s\n", para_strerror(-ret));
- exit(EXIT_FAILURE);
+ free(user_list_file);
}
+ return;
}
/*
if (pid != afs_pid)
continue;
PARA_EMERG_LOG("fatal: afs died\n");
- kill(0, SIGTERM);
- goto cleanup;
+ goto genocide;
}
break;
/* die on sigint/sigterm. Kill all children too. */
case SIGINT:
case SIGTERM:
PARA_EMERG_LOG("terminating on signal %d\n", signum);
+genocide:
kill(0, SIGTERM);
/*
* We must wait for all of our children to die. For the afs
while (wait(NULL) != -1 || errno != ECHILD)
; /* still at least one child alive */
mutex_lock(mmd_mutex);
-cleanup:
free(mmd->afd.afhi.chunk_table);
task_notify_all(s, E_DEADLY_SIGNAL);
return -E_DEADLY_SIGNAL;
ret = task_get_notification(sct->task);
if (ret < 0)
- return ret;
+ goto fail;
for (n = 0; n < sct->num_listen_fds; n++) {
ret = command_task_accept(n, s, sct);
- if (ret < 0) {
- free(sct->listen_fds);
- return ret;
- }
+ if (ret < 0)
+ goto fail;
}
return 0;
+fail:
+ free(sct->listen_fds);
+ return ret;
}
static void init_server_command_task(struct server_command_task *sct,
.post_select = command_post_select,
.context = sct,
}, &sched);
+ /*
+ * Detect whether the abstract Unix domain socket space is supported,
+ * but do not create the socket. We check this once in server context
+ * so that the command handlers inherit this bit of information and
+ * don't need to check again.
+ */
+ create_local_socket(NULL);
return;
err:
PARA_EMERG_LOG("%s\n", para_strerror(-ret));
init_ipc_or_die(); /* init mmd struct, mmd and log mutex */
daemon_set_start_time();
daemon_set_hooks(pre_log_hook, post_log_hook);
- PARA_NOTICE_LOG("initializing audio format handlers\n");
- afh_init();
-
/*
* Although afs uses its own signal handling we must ignore SIGUSR1
* _before_ the afs child process gets born by init_afs() below. It's