OregonCore  revision 3611e8a-git
Your Favourite TBC server
Main.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the OregonCore Project. See AUTHORS file for Copyright information
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License as published by the
6  * Free Software Foundation; either version 2 of the License, or (at your
7  * option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "SystemConfig.h"
19 
20 #include "Common.h"
21 #include "Database/DatabaseEnv.h"
22 #include "Config/Config.h"
23 #include "Log.h"
24 #include "Master.h"
25 #include <ace/Version.h>
26 #include <ace/Get_Opt.h>
27 
28 #ifndef _OREGON_CORE_CONFIG
29 # define _OREGON_CORE_CONFIG "oregoncore.conf"
30 #endif //_OREGON_CORE_CONFIG
31 
32 // Format is YYYYMMDDRR where RR is the change in the conf file
33 // for that day.
34 #ifndef _OREGON_CORE_CONFVER
35 # define _OREGON_CORE_CONFVER 2014091557
36 #endif //_OREGON_CORE_CONFVER
37 
38 #ifdef _WIN32
39 #include "ServiceWin32.h"
40 #include <process.h>
41 char serviceName[] = "Oregond";
42 char serviceLongName[] = "Oregon core service";
43 char serviceDescription[] = "Massive Network Game Object Server";
44 /*
45  * -1 - not in service mode
46  * 0 - stopped
47  * 1 - running
48  * 2 - paused
49  */
50 int m_ServiceStatus = -1;
51 #endif
52 
56 
58 
59 // Print out the usage string for this program on the console.
60 void usage(const char* prog)
61 {
62  sLog.outString("Usage: \n %s [<options>]\n"
63  " -v, --version print version and exit\n\r"
64  " -c config_file use config_file as configuration file\n\r"
65  #ifdef _WIN32
66  " Running as service functions:\n\r"
67  " -s run run as service\n\r"
68  " -s install install service\n\r"
69  " -s uninstall uninstall service\n\r"
70  #endif
71  " -t --run-tests run regression tests and exit\n\r"
72  , prog);
73 }
74 
75 // Launch the oregon server
76 extern int main(int argc, char** argv)
77 {
78  // Command line parsing
79  char const* cfg_file = _OREGON_CORE_CONFIG;
80 
81  #ifdef _WIN32
82  char const* options = ":c:s:";
83  #else
84  char const* options = ":c:";
85  #endif
86 
87  bool runRegressionTtests = false;
88 
89  ACE_Get_Opt cmd_opts(argc, argv, options);
90  cmd_opts.long_option("version", 'v');
91  cmd_opts.long_option("run-tests", 't');
92 
93  int option;
94  while ((option = cmd_opts()) != EOF)
95  {
96  switch (option)
97  {
98  case 'c':
99  cfg_file = cmd_opts.opt_arg();
100  break;
101  case 'v':
102  printf("%s\n", _FULLVERSION);
103  return 0;
104  #ifdef _WIN32
105  case 's':
106  {
107  const char* mode = cmd_opts.opt_arg();
108 
109  if (!strcmp(mode, "install"))
110  {
111  if (WinServiceInstall())
112  sLog.outString("Installing service");
113  return 1;
114  }
115  else if (!strcmp(mode, "uninstall"))
116  {
117  if (WinServiceUninstall())
118  sLog.outString("Uninstalling service");
119  return 1;
120  }
121  else if (!strcmp(mode, "run"))
122  WinServiceRun();
123  else
124  {
125  sLog.outError("Runtime-Error: -%c unsupported argument %s", cmd_opts.opt_opt(), mode);
126  usage(argv[0]);
127  return 1;
128  }
129  break;
130  }
131  #endif
132  case 't':
133  runRegressionTtests = true;
134  break;
135  case ':':
136  sLog.outError("Runtime-Error: -%c option requires an input argument", cmd_opts.opt_opt());
137  usage(argv[0]);
138  return 1;
139  default:
140  sLog.outError("Runtime-Error: bad format of commandline arguments");
141  usage(argv[0]);
142  return 1;
143  }
144  }
145 
146  if (!sConfig.SetSource(cfg_file))
147  {
148  sLog.outError("Invalid or missing configuration file : %s", cfg_file);
149  sLog.outError("Verify that the file exists and has \'[worldserver]' written in the top of the file!");
150  return 1;
151  }
152  sLog.outString("Using configuration file %s.", cfg_file);
153 
154  uint32 confVersion = sConfig.GetIntDefault("ConfVersion", 0);
155  if (confVersion < _OREGON_CORE_CONFVER)
156  {
157  sLog.outError("*****************************************************************************");
158  sLog.outError(" WARNING: Your oregoncore.conf version indicates your conf file is out of date!");
159  sLog.outError(" Please check for updates, as your current default values may cause");
160  sLog.outError(" strange behavior.");
161  sLog.outError("*****************************************************************************");
162  clock_t pause = 3000 + clock();
163 
164  while (pause > clock()) {}
165  }
166 
167  sLog.outDetail("Using ACE: %s", ACE_VERSION);
168 
169  // and run the 'Master'
170  // todo - Why do we need this 'Master'? Can't all of this be in the Main as for Realmd?
171  int exitcode = sMaster.Run(runRegressionTtests);
172  if (exitcode == 2)
173  {
174  /* We need to close all fds except the standard ones,
175  to avoid resoruce leaking. In the current status
176  this is the best way to do it. */
177 
178  int fd;
179  #ifdef _WIN32
180  _CrtSetReportMode(_CRT_ASSERT, 0); // Disable complaining about passing invalid values to close()
181  fd = _getmaxstdio();
182  #elif defined(OPEN_MAX)
183  fd = OPEN_MAX;
184  #elif defined(NOFILE)
185  fd = NOFILE;
186  #else
187  fd = getdtablesize();
188  #endif
189  while (fd > 2)
190  close(fd--);
191 
192  #ifndef _WIN32
193  execv(argv[0], argv);
194  #else
195  /* On windows we have to quote first argument
196  because spawned process won't be able to restart */
197  std::string arg0;
198  arg0.append(1, '"');
199  arg0.append(argv[0]);
200  arg0.append(1, '"');
201 
202  char* path = argv[0];
203  argv[0] = const_cast<char*>(arg0.c_str());
204  _execv(path, argv);
205  #endif
206 
207  fprintf(stderr, "Couldn't restart server: %s", strerror(errno));
208  _exit(exitcode); // avoid crashes as we closed fds
209  }
210  return exitcode;
211  // at sMaster return function exist with codes
212  // 0 - normal shutdown
213  // 1 - shutdown at error
214  // 2 - restart command used, this code can be used by restarter for restart OregonCore
215 }
216 
int main(int argc, char **argv)
Definition: Main.cpp:76
#define sConfig
Definition: Config.h:52
DatabaseType WorldDatabase
Accessor to the world database.
Definition: Main.cpp:53
#define sMaster
Definition: Master.h:46
#define sLog
Log class singleton.
Definition: Log.h:187
void usage(const char *prog)
Definition: Main.cpp:60
DatabaseType LoginDatabase
Accessor to the realm/login database.
Definition: Main.cpp:55
#define _FULLVERSION
Definition: SystemConfig.h:40
#define _OREGON_CORE_CONFVER
Definition: Main.cpp:35
DatabaseType CharacterDatabase
Accessor to the character database.
Definition: Main.cpp:54
ACE_UINT32 uint32
Definition: Define.h:71
uint32 realmID
Id of the realm.
Definition: Main.cpp:57
#define _OREGON_CORE_CONFIG
Definition: Main.cpp:29