1 /*
2 * Copyright (c) 2001-2014 Hypertriton, Inc. <http://hypertriton.com/>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
18 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
23 * USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 /*
27 * Core initialization routines.
28 */
29
30 #include <agar/config/version.h>
31 #include <agar/config/release.h>
32 #include <agar/config/enable_nls.h>
33 #include <agar/config/localedir.h>
34 #include <agar/config/ag_threads.h>
35 #include <agar/config/ag_network.h>
36 #include <agar/config/have_clock_gettime.h>
37 #include <agar/config/have_nanosleep.h>
38 #include <agar/config/have_gettimeofday.h>
39 #include <agar/config/have_select.h>
40 #include <agar/config/have_db4.h>
41 #include <agar/config/have_getpwuid.h>
42 #include <agar/config/have_getuid.h>
43 #include <agar/config/have_getaddrinfo.h>
44 #include <agar/config/have_winsock1.h>
45 #include <agar/config/have_winsock2.h>
46 #include <agar/config/have_csidl.h>
47 #ifdef AG_THREADS
48 # include <agar/config/have_pthreads_xopen.h>
49 # include <agar/config/have_pthread_mutex_recursive.h>
50 # include <agar/config/have_pthread_mutex_recursive_np.h>
51 #endif
52
53 #include <agar/core/core.h>
54 #include <agar/core/config.h>
55 #include <agar/core/dso.h>
56
57 #include <stdio.h>
58 #include <stdlib.h>
59 #ifndef _WIN32
60 # include <unistd.h>
61 #endif
62
63 #ifdef AG_THREADS
64 pthread_mutexattr_t agRecursiveMutexAttr; /* Recursive mutex attributes */
65 AG_Thread agEventThread; /* Event-processing thread */
66 #endif
67
68 AG_Config *agConfig; /* Global Agar config data */
69 void (*agAtexitFunc)(void) = NULL; /* User exit function */
70 void (*agAtexitFuncEv)(AG_Event *) = NULL; /* User exit handler */
71 char *agProgName = NULL; /* Optional application name */
72
73 int agVerbose = 0; /* Verbose console output */
74 int agSoftTimers = 0; /* Disable hardware timers */
75
76 int
AG_InitCore(const char * progname,Uint flags)77 AG_InitCore(const char *progname, Uint flags)
78 {
79 if (flags & AG_VERBOSE)
80 agVerbose = 1;
81 if (flags & AG_SOFT_TIMERS)
82 agSoftTimers = 1;
83
84 if (progname != NULL) {
85 if ((agProgName = TryStrdup(progname)) == NULL)
86 return (-1);
87 } else {
88 agProgName = NULL;
89 }
90
91 #ifdef ENABLE_NLS
92 bindtextdomain("agar", LOCALEDIR);
93 bind_textdomain_codeset("agar", "UTF-8");
94 textdomain("agar");
95 #endif
96
97 if (AG_InitErrorSubsystem() == -1 ||
98 AG_InitStringSubsystem() == -1 ||
99 AG_InitEventSubsystem(flags) == -1) {
100 return (-1);
101 }
102 AG_GetCPUInfo(&agCPU);
103
104 /* Initialize the thread resources. */
105 #ifdef AG_THREADS
106 agEventThread = AG_ThreadSelf(); /* Main thread */
107 # ifdef _XBOX
108 ptw32_processInitialize();
109 # endif
110 pthread_mutexattr_init(&agRecursiveMutexAttr);
111 # ifdef HAVE_PTHREAD_MUTEX_RECURSIVE_NP
112 pthread_mutexattr_settype(&agRecursiveMutexAttr,
113 PTHREAD_MUTEX_RECURSIVE_NP);
114 # else
115 pthread_mutexattr_settype(&agRecursiveMutexAttr,
116 PTHREAD_MUTEX_RECURSIVE);
117 # endif
118 AG_MutexInitRecursive(&agDSOLock);
119 #endif /* AG_THREADS */
120
121 /* Register the object classes from ag_core. */
122 AG_InitClassTbl();
123 AG_RegisterClass(&agConfigClass);
124 AG_RegisterClass(&agDbClass);
125 #ifdef HAVE_DB4
126 AG_RegisterClass(&agDbHashClass);
127 AG_RegisterClass(&agDbBtreeClass);
128 #endif
129
130 /* Select the default AG_Time(3) backend. */
131 #if defined(_WIN32)
132 AG_SetTimeOps(&agTimeOps_win32);
133 #elif defined(HAVE_CLOCK_GETTIME) && defined(HAVE_NANOSLEEP)
134 AG_SetTimeOps(&agTimeOps_posix);
135 #elif defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SELECT)
136 AG_SetTimeOps(&agTimeOps_gettimeofday);
137 #else
138 AG_SetTimeOps(&agTimeOps_dummy);
139 #endif
140
141 /* Select the network access routines. */
142 #ifdef AG_NETWORK
143 {
144 int rv;
145 # if defined(HAVE_WINSOCK2)
146 rv = AG_InitNetworkSubsystem(&agNetOps_winsock2);
147 # elif defined(HAVE_WINSOCK1)
148 rv = AG_InitNetworkSubsystem(&agNetOps_winsock1);
149 # elif defined(HAVE_GETADDRINFO)
150 rv = AG_InitNetworkSubsystem(&agNetOps_bsd);
151 # else
152 rv = AG_InitNetworkSubsystem(&agNetOps_dummy);
153 # endif
154 if (rv != 0)
155 return (-1);
156 }
157 #endif
158
159 /* Select the user account interface routines. */
160 #if defined(_XBOX)
161 AG_SetUserOps(&agUserOps_xbox);
162 #elif defined(_WIN32) && defined(HAVE_CSIDL)
163 AG_SetUserOps(&agUserOps_win32);
164 #elif defined(HAVE_GETPWUID) && defined(HAVE_GETUID)
165 AG_SetUserOps(&agUserOps_posix);
166 #else
167 AG_SetUserOps(&agUserOps_dummy);
168 #endif
169
170 AG_InitTimers();
171 AG_DataSourceInitSubsystem();
172
173 if ((agConfig = TryMalloc(sizeof(AG_Config))) == NULL) {
174 return (-1);
175 }
176 if (AG_ConfigInit(agConfig, flags) == -1) {
177 return (-1);
178 }
179 return (0);
180 }
181
182 /* Register a function to invoke in AG_Quit(). */
183 void
AG_AtExitFunc(void (* func)(void))184 AG_AtExitFunc(void (*func)(void))
185 {
186 agAtexitFunc = func;
187 }
188
189 void
AG_AtExitFuncEv(void (* func)(AG_Event *))190 AG_AtExitFuncEv(void (*func)(AG_Event *))
191 {
192 agAtexitFuncEv = func;
193 }
194
195 /* Immediately terminate the application. */
196 void
AG_Quit(void)197 AG_Quit(void)
198 {
199 AG_Destroy();
200 exit(0);
201 }
202
203 /* Clean up the resources allocated by Agar-Core. */
204 void
AG_Destroy(void)205 AG_Destroy(void)
206 {
207 if (agAtexitFunc != NULL) { agAtexitFunc(); }
208 if (agAtexitFuncEv != NULL) { agAtexitFuncEv(NULL); }
209
210 AG_ObjectDestroy(agConfig);
211 AG_DataSourceDestroySubsystem();
212 AG_DestroyTimers();
213 if (agUserOps != NULL && agUserOps->destroy != NULL) {
214 agUserOps->destroy();
215 agUserOps = NULL;
216 }
217 #ifdef AG_NETWORK
218 AG_DestroyNetworkSubsystem();
219 #endif
220 AG_DestroyClassTbl();
221 #ifdef AG_THREADS
222 pthread_mutexattr_destroy(&agRecursiveMutexAttr);
223 AG_MutexDestroy(&agDSOLock);
224 #endif
225 AG_DestroyEventSubsystem();
226 AG_DestroyStringSubsystem();
227 AG_DestroyErrorSubsystem();
228 Free(agProgName); agProgName = NULL;
229 }
230
231 void
AG_GetVersion(AG_AgarVersion * ver)232 AG_GetVersion(AG_AgarVersion *ver)
233 {
234 ver->major = AGAR_MAJOR_VERSION;
235 ver->minor = AGAR_MINOR_VERSION;
236 ver->patch = AGAR_PATCHLEVEL;
237 ver->release = RELEASE;
238 }
239