| 1 |
/*
|
| 2 |
* Copyright (C) 1998 Mark Baysinger (mbaysing@ucsd.edu)
|
| 3 |
* Copyright (C) 1998,1999,2000 Ross Combs (rocombs@cs.nmsu.edu)
|
| 4 |
*
|
| 5 |
* This program is free software; you can redistribute it and/or
|
| 6 |
* modify it under the terms of the GNU General Public License
|
| 7 |
* as published by the Free Software Foundation; either version 2
|
| 8 |
* of the License, or (at your option) any later version.
|
| 9 |
*
|
| 10 |
* This program is distributed in the hope that it will be useful,
|
| 11 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 12 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
| 13 |
* GNU General Public License for more details.
|
| 14 |
*
|
| 15 |
* You should have received a copy of the GNU General Public License
|
| 16 |
* along with this program; if not, write to the Free Software
|
| 17 |
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
| 18 |
*/
|
| 19 |
#include "common/setup_before.h"
|
| 20 |
#include <stdio.h>
|
| 21 |
#ifdef HAVE_STDDEF_H
|
| 22 |
# include <stddef.h>
|
| 23 |
#else
|
| 24 |
# ifndef NULL
|
| 25 |
# define NULL ((void *)0)
|
| 26 |
# endif
|
| 27 |
#endif
|
| 28 |
#ifdef STDC_HEADERS
|
| 29 |
# include <stdlib.h>
|
| 30 |
#else
|
| 31 |
# ifdef HAVE_MALLOC_H
|
| 32 |
# include <malloc.h>
|
| 33 |
# endif
|
| 34 |
#endif
|
| 35 |
#include "compat/exitstatus.h"
|
| 36 |
#ifdef HAVE_STRING_H
|
| 37 |
# include <string.h>
|
| 38 |
#else
|
| 39 |
# ifdef HAVE_STRINGS_H
|
| 40 |
# include <strings.h>
|
| 41 |
# endif
|
| 42 |
#endif
|
| 43 |
#include "compat/strdup.h"
|
| 44 |
#include <errno.h>
|
| 45 |
#include "compat/strerror.h"
|
| 46 |
#ifdef HAVE_UNISTD_H
|
| 47 |
# include <unistd.h>
|
| 48 |
#endif
|
| 49 |
#include "compat/stdfileno.h"
|
| 50 |
#include "compat/psock.h"
|
| 51 |
#include "common/hexdump.h"
|
| 52 |
#include "channel.h"
|
| 53 |
#include "game.h"
|
| 54 |
#include "server.h"
|
| 55 |
#include "common/eventlog.h"
|
| 56 |
#include "account.h"
|
| 57 |
#include "connection.h"
|
| 58 |
#include "game.h"
|
| 59 |
#include "common/version.h"
|
| 60 |
#include "prefs.h"
|
| 61 |
#include "ladder.h"
|
| 62 |
#include "adbanner.h"
|
| 63 |
#include "ipban.h"
|
| 64 |
#include "autoupdate.h"
|
| 65 |
#include "helpfile.h"
|
| 66 |
#include "timer.h"
|
| 67 |
#include "watch.h"
|
| 68 |
#include "common/tracker.h"
|
| 69 |
#include "realm.h"
|
| 70 |
#include "character.h"
|
| 71 |
#include "common/give_up_root_privileges.h"
|
| 72 |
#include "versioncheck.h"
|
| 73 |
#include "storage.h"
|
| 74 |
#include "anongame.h"
|
| 75 |
//aaron
|
| 76 |
#include "command_groups.h"
|
| 77 |
#include "output.h"
|
| 78 |
#include "alias_command.h"
|
| 79 |
#include "anongame_infos.h"
|
| 80 |
#include "anongame_maplists.h"
|
| 81 |
#include "tournament.h"
|
| 82 |
#include "news.h"
|
| 83 |
#include "clan.h"
|
| 84 |
#include "team.h"
|
| 85 |
#include "topic.h"
|
| 86 |
#include "support.h"
|
| 87 |
#include "common/trans.h"
|
| 88 |
#include "common/xalloc.h"
|
| 89 |
#include "common/fdwatch.h"
|
| 90 |
#ifdef WIN32
|
| 91 |
# include "win32/service.h"
|
| 92 |
#endif
|
| 93 |
#ifdef WIN32_GUI
|
| 94 |
# include "win32/winmain.h"
|
| 95 |
# define printf gui_printf
|
| 96 |
#endif
|
| 97 |
#include "common/setup_after.h"
|
| 98 |
|
| 99 |
/* out of memory safety */
|
| 100 |
#define OOM_SAFE_MEM 1000000 /* 1 Mbyte of safety memory */
|
| 101 |
|
| 102 |
void *oom_buffer = NULL;
|
| 103 |
|
| 104 |
static int bnetd_oom_handler(void)
|
| 105 |
{
|
| 106 |
/* no safety buffer, sorry :( */
|
| 107 |
if (!oom_buffer) return 0;
|
| 108 |
|
| 109 |
/* free the safety buffer hoping next allocs will succeed */
|
| 110 |
free(oom_buffer);
|
| 111 |
oom_buffer = NULL;
|
| 112 |
|
| 113 |
eventlog(eventlog_level_fatal,__FUNCTION__,"out of memory, forcing immediate shutdown");
|
| 114 |
|
| 115 |
/* shutdown immediatly */
|
| 116 |
server_quit_delay(-1);
|
| 117 |
|
| 118 |
return 1; /* ask xalloc codes to retry the allocation request */
|
| 119 |
}
|
| 120 |
|
| 121 |
static int oom_setup(void)
|
| 122 |
{
|
| 123 |
oom_buffer = malloc(OOM_SAFE_MEM);
|
| 124 |
if (!oom_buffer) return -1;
|
| 125 |
|
| 126 |
xalloc_setcb(bnetd_oom_handler);
|
| 127 |
return 0;
|
| 128 |
}
|
| 129 |
|
| 130 |
static void oom_free(void)
|
| 131 |
{
|
| 132 |
if (oom_buffer) free(oom_buffer);
|
| 133 |
oom_buffer = NULL;
|
| 134 |
}
|
| 135 |
|
| 136 |
FILE *hexstrm = NULL;
|
| 137 |
|
| 138 |
char serviceLongName[] = "PvPGN service";
|
| 139 |
char serviceName[] = "pvpgn";
|
| 140 |
char serviceDescription[] = "Player vs. Player Gaming Network - Server";
|
| 141 |
|
| 142 |
// by quetzal. indicates service status
|
| 143 |
// -1 - not in service mode
|
| 144 |
// 0 - stopped
|
| 145 |
// 1 - running
|
| 146 |
// 2 - paused
|
| 147 |
int g_ServiceStatus = -1;
|
| 148 |
|
| 149 |
static void usage(char const * progname);
|
| 150 |
|
| 151 |
static void usage(char const * progname)
|
| 152 |
{
|
| 153 |
fprintf(stderr,
|
| 154 |
"usage: %s [<options>]\n"
|
| 155 |
" -c FILE, --config=FILE use FILE as configuration file (default is " BNETD_DEFAULT_CONF_FILE ")\n"
|
| 156 |
" -d FILE, --hexdump=FILE do hex dump of packets into FILE\n"
|
| 157 |
#ifdef DO_DAEMONIZE
|
| 158 |
" -f, --foreground don't daemonize\n"
|
| 159 |
#else
|
| 160 |
" -f, --foreground don't daemonize (default)\n"
|
| 161 |
#endif
|
| 162 |
" -D, --debug run in debug mode (run in foreground and log to stdout)\n"
|
| 163 |
" -h, --help, --usage show this information and exit\n"
|
| 164 |
" -v, --version print version number and exit\n"
|
| 165 |
#ifdef WIN32
|
| 166 |
" Running as service functions:\n"
|
| 167 |
" --service run as service\n"
|
| 168 |
" -s install install service\n"
|
| 169 |
" -s uninstall uninstall service\n"
|
| 170 |
#endif
|
| 171 |
,progname);
|
| 172 |
}
|
| 173 |
|
| 174 |
|
| 175 |
// added some more exit status --> put in "compat/exitstatus.h" ???
|
| 176 |
#define STATUS_OOM_FAILURE 20
|
| 177 |
#define STATUS_STORAGE_FAILURE 30
|
| 178 |
#define STATUS_PSOCK_FAILURE 35
|
| 179 |
#define STATUS_MAPLISTS_FAILURE 40
|
| 180 |
#define STATUS_MATCHLISTS_FAILURE 50
|
| 181 |
#define STATUS_LADDERLIST_FAILURE 60
|
| 182 |
#define STATUS_WAR3XPTABLES_FAILURE 70
|
| 183 |
#define STATUS_SUPPORT_FAILURE 80
|
| 184 |
#define STATUS_FDWATCH_FAILURE 90
|
| 185 |
|
| 186 |
// new functions extracted from Fw()
|
| 187 |
int read_commandline(int argc, char * * argv, int *foreground, char const *preffile[], char *hexfile[]);
|
| 188 |
int pre_server_startup(void);
|
| 189 |
void post_server_shutdown(int status);
|
| 190 |
int eventlog_startup(void);
|
| 191 |
int fork_bnetd(int foreground);
|
| 192 |
char * write_to_pidfile(void);
|
| 193 |
void pvpgn_greeting(void);
|
| 194 |
|
| 195 |
// The functions
|
| 196 |
int read_commandline(int argc, char * * argv, int *foreground, char const *preffile[], char *hexfile[])
|
| 197 |
{
|
| 198 |
int a;
|
| 199 |
|
| 200 |
if (argc<1 || !argv || !argv[0]) {
|
| 201 |
fprintf(stderr,"bad arguments\n");
|
| 202 |
return -1;
|
| 203 |
}
|
| 204 |
#ifdef WIN32
|
| 205 |
if (argc > 1 && strncmp(argv[1], "--service", 9) == 0) {
|
| 206 |
Win32_ServiceRun();
|
| 207 |
return 0;
|
| 208 |
}
|
| 209 |
#endif
|
| 210 |
for (a=1; a<argc; a++) {
|
| 211 |
if (strncmp(argv[a],"--config=",9)==0) {
|
| 212 |
if (*preffile) {
|
| 213 |
fprintf(stderr,"%s: configuration file was already specified as \"%s\"\n",argv[0],preffile[0]);
|
| 214 |
usage(argv[0]);
|
| 215 |
return -1;
|
| 216 |
}
|
| 217 |
*preffile = &argv[a][9];
|
| 218 |
}
|
| 219 |
else if (strcmp(argv[a],"-c")==0) {
|
| 220 |
if (a+1>=argc) {
|
| 221 |
fprintf(stderr,"%s: option \"%s\" requires an argument\n",argv[0],argv[a]);
|
| 222 |
usage(argv[0]);
|
| 223 |
return -1;
|
| 224 |
}
|
| 225 |
if (*preffile) {
|
| 226 |
fprintf(stderr,"%s: configuration file was already specified as \"%s\"\n",argv[0],preffile[0]);
|
| 227 |
usage(argv[0]);
|
| 228 |
return -1;
|
| 229 |
}
|
| 230 |
a++;
|
| 231 |
*preffile = argv[a];
|
| 232 |
}
|
| 233 |
else if (strncmp(argv[a],"--hexdump=",10)==0) {
|
| 234 |
if (*hexfile) {
|
| 235 |
fprintf(stderr,"%s: configuration file was already specified as \"%s\"\n",argv[0],hexfile[0]);
|
| 236 |
usage(argv[0]);
|
| 237 |
return -1;
|
| 238 |
}
|
| 239 |
*hexfile = &argv[a][10];
|
| 240 |
}
|
| 241 |
else if (strcmp(argv[a],"-d")==0) {
|
| 242 |
if (a+1>=argc) {
|
| 243 |
fprintf(stderr,"%s: option \"%s\" requires an argument\n",argv[0],argv[a]);
|
| 244 |
usage(argv[0]);
|
| 245 |
return -1;
|
| 246 |
}
|
| 247 |
if (*hexfile) {
|
| 248 |
fprintf(stderr,"%s: configuration file was already specified as \"%s\"\n",argv[0],hexfile[0]);
|
| 249 |
usage(argv[0]);
|
| 250 |
return -1;
|
| 251 |
}
|
| 252 |
a++;
|
| 253 |
*hexfile = argv[a];
|
| 254 |
}
|
| 255 |
else if (strcmp(argv[a],"-f")==0 || strcmp(argv[a],"--foreground")==0)
|
| 256 |
*foreground = 1;
|
| 257 |
else if (strcmp(argv[a],"-D")==0 || strcmp(argv[a],"--debug")==0) {
|
| 258 |
eventlog_set_debugmode(1);
|
| 259 |
*foreground = 1;
|
| 260 |
}
|
| 261 |
#ifdef WIN32
|
| 262 |
else if (strcmp(argv[a],"-s") == 0) {
|
| 263 |
if (a < argc - 1) {
|
| 264 |
if (strcmp(argv[a+1], "install") == 0) {
|
| 265 |
fprintf(stderr, "Installing service");
|
| 266 |
Win32_ServiceInstall();
|
| 267 |
}
|
| 268 |
if (strcmp(argv[a+1], "uninstall") == 0) {
|
| 269 |
fprintf(stderr, "Uninstalling service");
|
| 270 |
Win32_ServiceUninstall();
|
| 271 |
}
|
| 272 |
}
|
| 273 |
return 0;
|
| 274 |
}
|
| 275 |
#endif
|
| 276 |
else if (strcmp(argv[a],"-v")==0 || strcmp(argv[a],"--version")==0) {
|
| 277 |
printf(PVPGN_SOFTWARE" version "PVPGN_VERSION"\n");
|
| 278 |
return 0;
|
| 279 |
}
|
| 280 |
else if (strcmp(argv[a],"-h")==0 || strcmp(argv[a],"--help")==0 || strcmp(argv[a],"--usage")==0) {
|
| 281 |
usage(argv[0]);
|
| 282 |
return 0;
|
| 283 |
}
|
| 284 |
else if (strcmp(argv[a],"--config")==0 || strcmp(argv[a],"--hexdump")==0) {
|
| 285 |
fprintf(stderr,"%s: option \"%s\" requires and argument.\n",argv[0],argv[a]);
|
| 286 |
usage(argv[0]);
|
| 287 |
return -1;
|
| 288 |
}
|
| 289 |
else {
|
| 290 |
fprintf(stderr,"%s: bad option \"%s\"\n",argv[0],argv[a]);
|
| 291 |
usage(argv[0]);
|
| 292 |
return -1;
|
| 293 |
}
|
| 294 |
}
|
| 295 |
return 1; // continue without exiting
|
| 296 |
}
|
| 297 |
|
| 298 |
int eventlog_startup(void)
|
| 299 |
{
|
| 300 |
char const * levels;
|
| 301 |
char * temp;
|
| 302 |
char const * tok;
|
| 303 |
|
| 304 |
eventlog_clear_level();
|
| 305 |
if ((levels = prefs_get_loglevels())) {
|
| 306 |
temp = xstrdup(levels);
|
| 307 |
tok = strtok(temp,","); /* strtok modifies the string it is passed */
|
| 308 |
while (tok) {
|
| 309 |
if (eventlog_add_level(tok)<0)
|
| 310 |
eventlog(eventlog_level_error,__FUNCTION__,"could not add log level \"%s\"",tok);
|
| 311 |
tok = strtok(NULL,",");
|
| 312 |
}
|
| 313 |
xfree(temp);
|
| 314 |
}
|
| 315 |
if (eventlog_open(prefs_get_logfile())<0) {
|
| 316 |
if (prefs_get_logfile()) {
|
| 317 |
eventlog(eventlog_level_fatal,__FUNCTION__,"could not use file \"%s\" for the eventlog (exiting)",prefs_get_logfile());
|
| 318 |
} else {
|
| 319 |
eventlog(eventlog_level_fatal,__FUNCTION__,"no logfile specified in configuration file \"%s\" (exiting)",preffile);
|
| 320 |
}
|
| 321 |
return -1;
|
| 322 |
}
|
| 323 |
eventlog(eventlog_level_info,__FUNCTION__,"logging event levels: %s",prefs_get_loglevels());
|
| 324 |
return 0;
|
| 325 |
}
|
| 326 |
|
| 327 |
int fork_bnetd(int foreground)
|
| 328 |
{
|
| 329 |
int pid;
|
| 330 |
|
| 331 |
#ifdef DO_DAEMONIZE
|
| 332 |
if (!foreground) {
|
| 333 |
if (chdir("/")<0) {
|
| 334 |
eventlog(eventlog_level_error,__FUNCTION__,"could not change working directory to / (chdir: %s)",pstrerror(errno));
|
| 335 |
return -1;
|
| 336 |
}
|
| 337 |
|
| 338 |
switch ((pid = fork())) {
|
| 339 |
case -1:
|
| 340 |
eventlog(eventlog_level_error,__FUNCTION__,"could not fork (fork: %s)",pstrerror(errno));
|
| 341 |
return -1;
|
| 342 |
case 0: /* child */
|
| 343 |
break;
|
| 344 |
default: /* parent */
|
| 345 |
return pid;
|
| 346 |
}
|
| 347 |
#ifndef WITH_D2
|
| 348 |
close(STDINFD);
|
| 349 |
close(STDOUTFD);
|
| 350 |
close(STDERRFD);
|
| 351 |
#endif
|
| 352 |
# ifdef HAVE_SETPGID
|
| 353 |
if (setpgid(0,0)<0) {
|
| 354 |
eventlog(eventlog_level_error,__FUNCTION__,"could not create new process group (setpgid: %s)",pstrerror(errno));
|
| 355 |
return -1;
|
| 356 |
}
|
| 357 |
# else
|
| 358 |
# ifdef HAVE_SETPGRP
|
| 359 |
# ifdef SETPGRP_VOID
|
| 360 |
if (setpgrp()<0) {
|
| 361 |
eventlog(eventlog_level_error,__FUNCTION__,"could not create new process group (setpgrp: %s)",pstrerror(errno));
|
| 362 |
return -1;
|
| 363 |
}
|
| 364 |
# else
|
| 365 |
if (setpgrp(0,0)<0) {
|
| 366 |
eventlog(eventlog_level_error,__FUNCTION__,"could not create new process group (setpgrp: %s)",pstrerror(errno));
|
| 367 |
return -1;
|
| 368 |
}
|
| 369 |
# endif
|
| 370 |
# else
|
| 371 |
# ifdef HAVE_SETSID
|
| 372 |
if (setsid()<0) {
|
| 373 |
eventlog(eventlog_level_error,__FUNCTION__,"could not create new process group (setsid: %s)",pstrerror(errno));
|
| 374 |
return -1;
|
| 375 |
}
|
| 376 |
# else
|
| 377 |
# error "One of setpgid(), setpgrp(), or setsid() is required"
|
| 378 |
# endif
|
| 379 |
# endif
|
| 380 |
# endif
|
| 381 |
}
|
| 382 |
return 0;
|
| 383 |
#endif
|
| 384 |
return 0;
|
| 385 |
}
|
| 386 |
|
| 387 |
char * write_to_pidfile(void)
|
| 388 |
{
|
| 389 |
char *pidfile = xstrdup(prefs_get_pidfile());
|
| 390 |
|
| 391 |
if (pidfile[0]=='\0') {
|
| 392 |
xfree((void *)pidfile); /* avoid warning */
|
| 393 |
return NULL;
|
| 394 |
}
|
| 395 |
if (pidfile) {
|
| 396 |
#ifdef HAVE_GETPID
|
| 397 |
FILE * fp;
|
| 398 |
|
| 399 |
if (!(fp = fopen(pidfile,"w"))) {
|
| 400 |
eventlog(eventlog_level_error,__FUNCTION__,"unable to open pid file \"%s\" for writing (fopen: %s)",pidfile,pstrerror(errno));
|
| 401 |
xfree((void *)pidfile); /* avoid warning */
|
| 402 |
return NULL;
|
| 403 |
} else {
|
| 404 |
fprintf(fp,"%u",(unsigned int)getpid());
|
| 405 |
if (fclose(fp)<0)
|
| 406 |
eventlog(eventlog_level_error,__FUNCTION__,"could not close pid file \"%s\" after writing (fclose: %s)",pidfile,pstrerror(errno));
|
| 407 |
}
|
| 408 |
#else
|
| 409 |
eventlog(eventlog_level_warn,__FUNCTION__,"no getpid() system call, disable pid file in bnetd.conf");
|
| 410 |
xfree((void *)pidfile); /* avoid warning */
|
| 411 |
return NULL;
|
| 412 |
#endif
|
| 413 |
}
|
| 414 |
return pidfile;
|
| 415 |
}
|
| 416 |
|
| 417 |
int pre_server_startup(void)
|
| 418 |
{
|
| 419 |
pvpgn_greeting();
|
| 420 |
if (oom_setup() < 0) {
|
| 421 |
eventlog(eventlog_level_error, __FUNCTION__, "OOM init failed");
|
| 422 |
return STATUS_OOM_FAILURE;
|
| 423 |
}
|
| 424 |
if (storage_init(prefs_get_storage_path()) < 0) {
|
| 425 |
eventlog(eventlog_level_error, "pre_server_startup", "storage init failed");
|
| 426 |
return STATUS_STORAGE_FAILURE;
|
| 427 |
}
|
| 428 |
if (psock_init() < 0) {
|
| 429 |
eventlog(eventlog_level_error, __FUNCTION__, "could not initialize socket functions");
|
| 430 |
return STATUS_PSOCK_FAILURE;
|
| 431 |
}
|
| 432 |
if (support_check_files(prefs_get_supportfile()) < 0) {
|
| 433 |
eventlog(eventlog_level_error, "pre_server_startup","some needed files are missing");
|
| 434 |
eventlog(eventlog_level_error, "pre_server_startup","please make sure you installed the supportfiles in %s",prefs_get_filedir());
|
| 435 |
return STATUS_SUPPORT_FAILURE;
|
| 436 |
}
|
| 437 |
if (anongame_maplists_create() < 0) {
|
| 438 |
eventlog(eventlog_level_error, "pre_server_startup", "could not load maps");
|
| 439 |
return STATUS_MAPLISTS_FAILURE;
|
| 440 |
}
|
| 441 |
if (anongame_matchlists_create() < 0) {
|
| 442 |
eventlog(eventlog_level_error, "pre_server_startup", "could not create matchlists");
|
| 443 |
return STATUS_MATCHLISTS_FAILURE;
|
| 444 |
}
|
| 445 |
if (fdwatch_init(prefs_get_max_connections())) {
|
| 446 |
eventlog(eventlog_level_error, __FUNCTION__, "error initilizing fdwatch");
|
| 447 |
return STATUS_FDWATCH_FAILURE;
|
| 448 |
}
|
| 449 |
connlist_create();
|
| 450 |
gamelist_create();
|
| 451 |
timerlist_create();
|
| 452 |
server_set_name();
|
| 453 |
channellist_create();
|
| 454 |
if (helpfile_init(prefs_get_helpfile())<0)
|
| 455 |
eventlog(eventlog_level_error,__FUNCTION__,"could not load helpfile");
|
| 456 |
ipbanlist_create();
|
| 457 |
if (ipbanlist_load(prefs_get_ipbanfile())<0)
|
| 458 |
eventlog(eventlog_level_error,__FUNCTION__,"could not load IP ban list");
|
| 459 |
if (adbannerlist_create(prefs_get_adfile())<0)
|
| 460 |
eventlog(eventlog_level_error,__FUNCTION__,"could not load adbanner list");
|
| 461 |
if (autoupdate_load(prefs_get_mpqfile())<0)
|
| 462 |
eventlog(eventlog_level_error,__FUNCTION__,"could not load autoupdate list");
|
| 463 |
if (versioncheck_load(prefs_get_versioncheck_file())<0)
|
| 464 |
eventlog(eventlog_level_error,__FUNCTION__,"could not load versioncheck list");
|
| 465 |
if (news_load(prefs_get_newsfile())<0)
|
| 466 |
eventlog(eventlog_level_error,__FUNCTION__,"could not load news list");
|
| 467 |
watchlist_create();
|
| 468 |
output_init();
|
| 469 |
accountlist_load_default();
|
| 470 |
accountlist_create();
|
| 471 |
if (ladder_createxptable(prefs_get_xplevel_file(),prefs_get_xpcalc_file())<0) {
|
| 472 |
eventlog(eventlog_level_error, "pre_server_startup", "could not load WAR3 xp calc tables");
|
| 473 |
return STATUS_WAR3XPTABLES_FAILURE;
|
| 474 |
}
|
| 475 |
ladders_init();
|
| 476 |
ladders_load_accounts_to_ladderlists();
|
| 477 |
ladder_update_all_accounts();
|
| 478 |
if (characterlist_create("")<0)
|
| 479 |
eventlog(eventlog_level_error,__FUNCTION__,"could not load character list");
|
| 480 |
if (prefs_get_track()) /* setup the tracking mechanism */
|
| 481 |
tracker_set_servers(prefs_get_trackserv_addrs());
|
| 482 |
if (command_groups_load(prefs_get_command_groups_file())<0)
|
| 483 |
eventlog(eventlog_level_error,__FUNCTION__,"could not load command_groups list");
|
| 484 |
aliasfile_load(prefs_get_aliasfile());
|
| 485 |
if (trans_load(prefs_get_transfile(),TRANS_BNETD)<0)
|
| 486 |
eventlog(eventlog_level_error,__FUNCTION__,"could not load trans list");
|
| 487 |
tournament_init(prefs_get_tournament_file());
|
| 488 |
anongame_infos_load(prefs_get_anongame_infos_file());
|
| 489 |
clanlist_load();
|
| 490 |
teamlist_load();
|
| 491 |
if (realmlist_create(prefs_get_realmfile())<0)
|
| 492 |
eventlog(eventlog_level_error,__FUNCTION__,"could not load realm list");
|
| 493 |
topiclist_load(prefs_get_topicfile());
|
| 494 |
return 0;
|
| 495 |
}
|
| 496 |
|
| 497 |
void post_server_shutdown(int status)
|
| 498 |
{
|
| 499 |
switch (status)
|
| 500 |
{
|
| 501 |
case 0:
|
| 502 |
topiclist_unload();
|
| 503 |
realmlist_destroy();
|
| 504 |
teamlist_unload();
|
| 505 |
clanlist_unload();
|
| 506 |
tournament_destroy();
|
| 507 |
anongame_infos_unload();
|
| 508 |
trans_unload();
|
| 509 |
aliasfile_unload();
|
| 510 |
command_groups_unload();
|
| 511 |
tracker_set_servers(NULL);
|
| 512 |
characterlist_destroy();
|
| 513 |
ladder_destroyxptable();
|
| 514 |
case STATUS_WAR3XPTABLES_FAILURE:
|
| 515 |
|
| 516 |
case STATUS_LADDERLIST_FAILURE:
|
| 517 |
ladder_update_all_accounts();
|
| 518 |
ladders_destroy();
|
| 519 |
output_dispose_filename();
|
| 520 |
accountlist_destroy();
|
| 521 |
accountlist_unload_default();
|
| 522 |
watchlist_destroy();
|
| 523 |
news_unload();
|
| 524 |
versioncheck_unload();
|
| 525 |
autoupdate_unload();
|
| 526 |
adbannerlist_destroy();
|
| 527 |
ipbanlist_save(prefs_get_ipbanfile());
|
| 528 |
ipbanlist_destroy();
|
| 529 |
helpfile_unload();
|
| 530 |
channellist_destroy();
|
| 531 |
server_clear_name();
|
| 532 |
timerlist_destroy();
|
| 533 |
gamelist_destroy();
|
| 534 |
connlist_destroy();
|
| 535 |
fdwatch_close();
|
| 536 |
case STATUS_FDWATCH_FAILURE:
|
| 537 |
anongame_matchlists_destroy();
|
| 538 |
case STATUS_MATCHLISTS_FAILURE:
|
| 539 |
anongame_maplists_destroy();
|
| 540 |
case STATUS_MAPLISTS_FAILURE:
|
| 541 |
case STATUS_SUPPORT_FAILURE:
|
| 542 |
if (psock_deinit())
|
| 543 |
eventlog(eventlog_level_error, __FUNCTION__, "got error from psock_deinit()");
|
| 544 |
case STATUS_PSOCK_FAILURE:
|
| 545 |
storage_close();
|
| 546 |
case STATUS_STORAGE_FAILURE:
|
| 547 |
oom_free();
|
| 548 |
case STATUS_OOM_FAILURE:
|
| 549 |
case -1:
|
| 550 |
break;
|
| 551 |
default:
|
| 552 |
eventlog(eventlog_level_error,__FUNCTION__,"got bad status \"%d\" during shutdown",status);
|
| 553 |
}
|
| 554 |
return;
|
| 555 |
}
|
| 556 |
|
| 557 |
void pvpgn_greeting(void)
|
| 558 |
{
|
| 559 |
#ifdef HAVE_GETPID
|
| 560 |
eventlog(eventlog_level_info,__FUNCTION__,PVPGN_SOFTWARE" version "PVPGN_VERSION" process %u",(unsigned int)getpid());
|
| 561 |
#else
|
| 562 |
eventlog(eventlog_level_info,__FUNCTION__,PVPGN_SOFTWARE" version "PVPGN_VERSION);
|
| 563 |
#endif
|
| 564 |
|
| 565 |
printf("You are currently Running "PVPGN_SOFTWARE" "PVPGN_VERSION"\n");
|
| 566 |
printf("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n");
|
| 567 |
printf("Make sure to visit:\n");
|
| 568 |
printf("http://www.pvpgn.org\n");
|
| 569 |
printf("We can also be found on: irc.pvpgn.org\n");
|
| 570 |
printf("Channel: #pvpgn\n");
|
| 571 |
printf("Server is now running.\n");
|
| 572 |
printf("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n");
|
| 573 |
|
| 574 |
return;
|
| 575 |
}
|
| 576 |
|
| 577 |
// MAIN STARTS HERE!!!
|
| 578 |
#ifdef WIN32_GUI
|
| 579 |
extern int server_main(int argc, char * * argv)
|
| 580 |
#else
|
| 581 |
extern int main(int argc, char * * argv)
|
| 582 |
#endif
|
| 583 |
{
|
| 584 |
int a;
|
| 585 |
int foreground = 0;
|
| 586 |
char *hexfile = NULL;
|
| 587 |
char *pidfile;
|
| 588 |
|
| 589 |
// Read the command line and set variables
|
| 590 |
if ((a = read_commandline(argc, argv, &foreground, &preffile, &hexfile)) != 1)
|
| 591 |
return a;
|
| 592 |
|
| 593 |
// Fork to child process if not set to foreground
|
| 594 |
if ((a = fork_bnetd(foreground)) != 0)
|
| 595 |
return a < 0 ? a : 0; /* dizzy: dont return code != 0 when things are OK! */
|
| 596 |
|
| 597 |
eventlog_set(stderr);
|
| 598 |
/* errors to eventlog from here on... */
|
| 599 |
|
| 600 |
// Load the prefs
|
| 601 |
if (preffile) {
|
| 602 |
if (prefs_load(preffile)<0) { // prefs are loaded here ...
|
| 603 |
eventlog(eventlog_level_fatal,__FUNCTION__,"could not parse specified configuration file (exiting)");
|
| 604 |
return -1;
|
| 605 |
}
|
| 606 |
} else {
|
| 607 |
if (prefs_load(BNETD_DEFAULT_CONF_FILE)<0) // or prefs are loaded here .. if not defined on command line ...
|
| 608 |
eventlog(eventlog_level_warn,__FUNCTION__,"using default configuration"); // or use defaults if default conf is not found
|
| 609 |
}
|
| 610 |
|
| 611 |
// Start logging to log file
|
| 612 |
if (eventlog_startup() == -1)
|
| 613 |
return -1;
|
| 614 |
/* eventlog goes to log file from here on... */
|
| 615 |
|
| 616 |
// Give up root privileges
|
| 617 |
/* Hakan: That's way too late to give up root privileges... Have to look for a better place */
|
| 618 |
if (give_up_root_privileges(prefs_get_effective_user(),prefs_get_effective_group())<0) {
|
| 619 |
eventlog(eventlog_level_fatal,__FUNCTION__,"could not give up privileges (exiting)");
|
| 620 |
return -1;
|
| 621 |
}
|
| 622 |
|
| 623 |
// Write the pidfile
|
| 624 |
pidfile = write_to_pidfile();
|
| 625 |
|
| 626 |
// Open the hexfile for writing
|
| 627 |
if (hexfile) {
|
| 628 |
if (!(hexstrm = fopen(hexfile,"w")))
|
| 629 |
eventlog(eventlog_level_error,__FUNCTION__,"could not open file \"%s\" for writing the hexdump (fopen: %s)",hexfile,pstrerror(errno));
|
| 630 |
else
|
| 631 |
fprintf(hexstrm,"# dump generated by "PVPGN_SOFTWARE" version "PVPGN_VERSION"\n");
|
| 632 |
}
|
| 633 |
|
| 634 |
// Run the pre server stuff
|
| 635 |
a = pre_server_startup();
|
| 636 |
|
| 637 |
// now process connections and network traffic
|
| 638 |
if (a == 0) {
|
| 639 |
if (server_process() < 0)
|
| 640 |
eventlog(eventlog_level_fatal,__FUNCTION__,"failed to initialize network (exiting)");
|
| 641 |
}
|
| 642 |
|
| 643 |
// run post server stuff and exit
|
| 644 |
post_server_shutdown(a);
|
| 645 |
|
| 646 |
// Close hexfile
|
| 647 |
if (hexstrm) {
|
| 648 |
fprintf(hexstrm,"# end of dump\n");
|
| 649 |
if (fclose(hexstrm)<0)
|
| 650 |
eventlog(eventlog_level_error,__FUNCTION__,"could not close hexdump file \"%s\" after writing (fclose: %s)",hexfile,pstrerror(errno));
|
| 651 |
}
|
| 652 |
|
| 653 |
// Delete pidfile
|
| 654 |
if (pidfile) {
|
| 655 |
if (remove(pidfile)<0)
|
| 656 |
eventlog(eventlog_level_error,__FUNCTION__,"could not remove pid file \"%s\" (remove: %s)",pidfile,pstrerror(errno));
|
| 657 |
xfree((void *)pidfile); /* avoid warning */
|
| 658 |
}
|
| 659 |
|
| 660 |
if (a == 0)
|
| 661 |
eventlog(eventlog_level_info,__FUNCTION__,"server has shut down");
|
| 662 |
prefs_unload();
|
| 663 |
eventlog_close();
|
| 664 |
|
| 665 |
if (a == 0)
|
| 666 |
return 0;
|
| 667 |
|
| 668 |
return -1;
|
| 669 |
}
|