/*
* Copyright (C) 1997-2007 Andre Noll <maan@systemlinux.org>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ * Licensed under the GPL v2. For licencing details see COPYING.
*/
/** \file server.c Paraslash's main server */
*
*/
+#include <sys/types.h>
+#include <dirent.h>
-
+#include "para.h"
#include "server.cmdline.h"
-#include "afs.h"
+#include "afs_common.h"
+#include "afh.h"
#include "server.h"
#include "vss.h"
#include "config.h"
#include "string.h"
#include "ipc.h"
#include "fd.h"
+#include "list.h"
+#include "sched.h"
#include "signal.h"
#include "user_list.h"
+#include "afs.h"
/** define the array of error lists needed by para_server */
INIT_SERVER_ERRLISTS;
}
if (!ret) {
int tmp = conf.daemon_given;
- server_cmdline_parser_configfile(cf, &conf, override, 0, 0);
+ struct server_cmdline_parser_params params = {
+ .override = override,
+ .initialize = 0,
+ .check_required = 0,
+ .check_ambiguity = 0
+ };
+ server_cmdline_parser_config_file(cf, &conf, ¶ms);
conf.daemon_given = tmp;
}
/* logfile */
static void init_random_seed(void)
{
- int fd, ret = -1, len = sizeof(unsigned int);
+ int fd, ret = -1;
unsigned int seed;
+ size_t len = sizeof(unsigned int);
fd = open("/dev/urandom", O_RDONLY);
if (fd < 0)
exit(EXIT_FAILURE);
}
+uint32_t afs_socket_cookie;
+static int afs_socket;
+pid_t afs_pid;
+
+static void init_afs(void)
+{
+ int ret, afs_server_socket[2];
+
+ ret = socketpair(PF_UNIX, SOCK_DGRAM, 0, afs_server_socket);
+ if (ret < 0)
+ exit(EXIT_FAILURE);
+ afs_socket_cookie = para_random((uint32_t)-1);
+ afs_pid = fork();
+ if (afs_pid < 0)
+ exit(EXIT_FAILURE);
+ if (!afs_pid) { /* child (afs) */
+ close(afs_server_socket[0]);
+ afs_init(afs_socket_cookie, afs_server_socket[1]);
+ }
+ close(afs_server_socket[1]);
+ afs_socket = afs_server_socket[0];
+ ret = mark_fd_nonblock(afs_socket);
+ if (ret < 0)
+ exit(EXIT_FAILURE);
+ add_close_on_fork_list(afs_socket);
+ PARA_INFO_LOG("afs_socket: %d, afs_socket_cookie: %u\n", afs_socket,
+ (unsigned) afs_socket_cookie);
+}
+
+
static unsigned do_inits(int argc, char **argv)
{
/* connector's address information */
vss_init();
mmd->server_pid = getpid();
setup_signal_handling();
+ init_afs();
mmd_lock();
/* init network socket */
PARA_NOTICE_LOG("%s", "initializing tcp command socket\n");
status_refresh();
if (FD_ISSET(signal_pipe, &rfds)) {
int sig;
+ pid_t pid;
sig = para_next_signal();
switch (sig) {
case SIGHUP:
handle_sighup();
break;
case SIGCHLD:
- para_reap_children();
+ for (;;) {
+ pid = para_reap_child();
+ if (pid <= 0)
+ break;
+ if (pid != afs_pid)
+ continue;
+ PARA_EMERG_LOG("fatal: afs died\n");
+ goto genocide;
+ }
break;
/* die on sigint/sigterm. Kill all children too. */
case SIGINT:
case SIGTERM:
PARA_EMERG_LOG("terminating on signal %d\n", sig);
+genocide:
kill(0, SIGTERM);
selectors[mmd->selector_num].shutdown();
mutex_destroy(mmd_mutex);
shm_detach(mmd);
shm_destroy(mmd_shm_id);
+
exit(EXIT_FAILURE);
}
}