2 Copyright (c) 1993 Richard V. Nash.
3 Copyright (c) 2000 Dan Papasian
4 Copyright (C) Andrew Tridgell 2002
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 ficsmain.c is a minimal wrapper around chessd.so. By keeping this module to a
23 minimum size we can reload nearly all the chess server functionality on a 'areload'
30 /* handle used to talk to chessd.so */
31 static void *chessd_so_handle;
34 static void main_event_loop(void);
36 unsigned chessd_reload_flag;
39 load a function from chessd.so
40 this is the core of the runtime reload functionality
42 static void *chessd_function(const char *name)
46 if (!chessd_so_handle) {
47 chessd_so_handle = dlopen(LIB_DIR "/chessd.so", RTLD_LAZY);
48 if (!chessd_so_handle) {
49 fprintf(stderr, "CHESSD: Failed to load chessd.so !! (%s)\n",
55 sym = dlsym(chessd_so_handle, name);
57 fprintf(stderr, "CHESSD: Failed to find symbol %s in chessd.so !!\n",
68 fprintf(stderr, "Usage: chessd -p port [-f] [-T timeseal_decoder] [-R rootdir]\n");
69 fprintf(stderr, "PORT_NUMBER is 5000 by default\n");
73 static int daemonize(void)
76 if ((pid = fork()) == -1)
85 static void main_event_loop(void)
87 void (*select_loop)(void ) = chessd_function("select_loop");
92 /* check the reload flag */
93 if (chessd_reload_flag) {
94 void (*reload_close)(void ) = chessd_function("reload_close");
95 void (*reload_open)(void );
97 chessd_reload_flag = 0;
99 fprintf(stderr, "CHESSD: Reloading server code!\n");
101 /* free up local vars */
104 /* close the handle to the shared lib */
105 dlclose(chessd_so_handle);
106 chessd_so_handle = NULL;
108 /* re-initialise local variables */
109 reload_open = chessd_function("reload_open");
111 select_loop = chessd_function("select_loop");
116 static void TerminateServer(int sig)
118 void (*output_shut_mess)(void ) = chessd_function("output_shut_mess");
119 void (*TerminateCleanup)(void ) = chessd_function("TerminateCleanup");
120 void (*net_close)(void ) = chessd_function("net_close");
122 fprintf(stderr, "CHESSD: Received signal %d\n", sig);
129 static void BrokenPipe(int sig)
131 signal(SIGPIPE, BrokenPipe);
132 fprintf(stderr, "CHESSD: Pipe signal\n");
136 /* this assumes we are setuid root to start */
137 static void do_chroot(const char *dir)
140 uid_t uid = getuid();
141 uid_t euid = geteuid();
144 if (euid != 0 || setuid(0) != 0) {
145 fprintf(stderr, "Must be setuid root to use -R\n");
148 if (chroot(dir) != 0 || chdir("/") != 0) {
152 if (setuid(uid) != 0) {
157 /* close all extraneous file descriptors */
158 for (i=0;i<3;i++) close(i);
159 open("stdin.log", O_RDWR|O_CREAT|O_TRUNC, 0644);
160 open("stdout.log", O_WRONLY|O_CREAT|O_TRUNC, 0644);
161 open("stderr.log", O_WRONLY|O_CREAT|O_TRUNC, 0644);
163 /* reestabish core limits */
164 getrlimit(RLIMIT_CORE, &rlp );
165 rlp.rlim_cur = MAX(64*1024*1024, rlp.rlim_max);
166 setrlimit( RLIMIT_CORE, &rlp );
170 give a decent backtrace on segv
172 static void segv_handler(int sig)
175 snprintf(cmd, sizeof(cmd), "/home/fics/bin/backtrace %d > /home/fics/chessd/segv_%d 2>&1",
176 (int)getpid(), (int)getpid());
181 int main(int argc, char *argv[])
183 int i, foreground, port;
184 void (*timeseal_init)(const char * ) = chessd_function("timeseal_init");
185 int (*net_init)(int ) = chessd_function("net_init");
186 void (*initial_load)(void ) = chessd_function("initial_load");
191 /* enable malloc checking in libc */
192 setenv("MALLOC_CHECK_", "2", 1);
194 while((i = getopt(argc, argv, "p:fR:T:")) != -1) {
203 timeseal_init(optarg);
213 if (!foreground && daemonize()){
214 printf("Problem with Daemonization - Aborting\n");
218 signal(SIGTERM, TerminateServer);
219 signal(SIGSEGV, segv_handler);
220 signal(SIGBUS, segv_handler);
221 signal(SIGINT, TerminateServer);
222 signal(SIGPIPE, BrokenPipe);
224 if (net_init(port)) {
225 fprintf(stderr, "CHESSD: Network initialize failed on port %d.\n", port);
228 fprintf(stderr, "CHESSD: Initialized on port %d\n", port);
233 /* will never get here - uses TerminateServer */