]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - win/configure.cpp
94547faeed44f4a7b4003e2cb2f1fe4a9d04a19f
[user/henk/code/inspircd.git] / win / configure.cpp
1 #include <windows.h>\r
2 #include <stdio.h>\r
3 #include <string>\r
4 #include "colours.h"\r
5 \r
6 using namespace std;\r
7 void Run();\r
8 void Banner();\r
9 void WriteCompileModules();\r
10 void WriteCompileCommands();\r
11 \r
12 /* detects if we are running windows xp or higher (5.1) */\r
13 bool iswinxp()\r
14 {\r
15         OSVERSIONINFO vi;\r
16         vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);\r
17         GetVersionEx(&vi);\r
18         if(vi.dwMajorVersion > 5)\r
19                 return true;\r
20 \r
21         if(vi.dwMajorVersion >= 5 && vi.dwMinorVersion >= 1)\r
22                 return true;\r
23         \r
24         return false;\r
25 }\r
26 \r
27 int get_int_option(const char * text, int def)\r
28 {\r
29         static char buffer[500];\r
30         int ret;\r
31         printf_c("%s\n[\033[1;32m%u\033[0m] -> ", text, def);\r
32         fgets(buffer, 500, stdin);\r
33         if(sscanf(buffer, "%u", &ret) != 1)\r
34                 ret = def;\r
35 \r
36         printf("\n");\r
37         return ret;\r
38 }\r
39 \r
40 bool get_bool_option(const char * text, bool def)\r
41 {\r
42         static char buffer[500];\r
43         char ret[100];\r
44         printf_c("%s [\033[1;32m%c\033[0m] -> ", text, def ? 'y' : 'n');\r
45         fgets(buffer, 500, stdin);\r
46         if(sscanf(buffer, "%s", ret) != 1)\r
47                 strcpy(ret, def ? "y" : "n");\r
48 \r
49         printf("\n");\r
50         return !strncmp(ret, "y", 1);\r
51 }\r
52 \r
53 void get_string_option(const char * text, char * def, char * buf)\r
54 {\r
55         static char buffer[500];\r
56         printf_c("%s\n[\033[1;32m%s\033[0m] -> ", text, def);\r
57         fgets(buffer, 500, stdin);\r
58         if(sscanf(buffer, "%s", buf) != 1)\r
59                 strcpy(buf, def);\r
60 \r
61         printf("\n");\r
62 }\r
63 \r
64 // escapes a string for use in a c++ file\r
65 bool escape_string(char * str, size_t size)\r
66 {\r
67         size_t len = strlen(str);\r
68         char * d_str = (char*)malloc(len * 2);\r
69     \r
70         size_t i = 0;\r
71         size_t j = 0;\r
72 \r
73         for(; i < len; ++i)\r
74         {\r
75                 if(str[i] == '\\')\r
76                 {\r
77                         d_str[j++] = '\\';\r
78                         d_str[j++] = '\\';\r
79                 }\r
80                 else\r
81                 {\r
82                         d_str[j++] = str[i];\r
83                 }\r
84         }\r
85 \r
86         d_str[j++] = 0;\r
87 \r
88     if(j > size)\r
89         {\r
90                 free(d_str);\r
91                 return false;\r
92         }\r
93 \r
94         strcpy(str, d_str);\r
95         free(d_str);\r
96         return true;\r
97 }\r
98 \r
99 /* gets the svn revision */\r
100 int get_svn_revision(char * buffer, size_t len)\r
101 {\r
102         /* again.. I am lazy :p cbf to pipe output of svn info to us, so i'll just read the file */\r
103         /*\r
104         8\r
105 \r
106         dir\r
107         7033\r
108         */\r
109         char buf[1000];\r
110         FILE * f = fopen("..\\.svn\\entries", "r");\r
111         if(!f) goto bad_rev;\r
112     \r
113         if(!fgets(buf, 1000, f)) goto bad_rev;\r
114         if(!fgets(buf, 1000, f)) goto bad_rev;\r
115         if(!fgets(buf, 1000, f)) goto bad_rev;\r
116         if(!fgets(buf, 1000, f)) goto bad_rev;\r
117         int rev = atoi(buf);\r
118         if(rev == 0) goto bad_rev;\r
119         sprintf(buffer, "%u", rev);\r
120         fclose(f);\r
121         return rev;\r
122         \r
123 bad_rev:\r
124         strcpy(buffer, "non-svn");\r
125         if(f) fclose(f);\r
126         return 0;\r
127 }\r
128 \r
129 int __stdcall WinMain(IN HINSTANCE hInstance, IN HINSTANCE hPrevInstance, IN LPSTR lpCmdLine, IN int nShowCmd )\r
130 {\r
131         // Skip if configure is already-existant.\r
132         FILE * f = fopen("inspircd_config.h", "r");\r
133         if(f)\r
134         {\r
135                 fclose(f);\r
136                 return 0;\r
137         }\r
138 \r
139         AllocConsole();\r
140 \r
141         // pipe standard handles to this console\r
142         freopen("CONIN$", "r", stdin);\r
143         freopen("CONOUT$", "w", stdout);\r
144         freopen("CONOUT$", "w", stderr);\r
145 \r
146         Banner();\r
147         Run();\r
148         WriteCompileCommands();\r
149         WriteCompileModules();\r
150         FreeConsole();\r
151         return 0;\r
152 }\r
153 \r
154 void Banner()\r
155 {\r
156         printf_c("\nWelcome to the \033[1mInspIRCd\033[0m Configuration program! (\033[1minteractive mode\033[0m)\n"\r
157                          "\033[1mPackage maintainers: Type ./configure --help for non-interactive help\033[0m\n\n");\r
158         printf_c("*** If you are unsure of any of these values, leave it blank for    ***\n"\r
159                          "*** standard settings that will work, and your server will run      ***\n"\r
160                          "*** using them. Please consult your IRC network admin if in doubt.  ***\n\n"\r
161                          "Press \033[1m<RETURN>\033[0m to accept the default for any option, or enter\n"\r
162                          "a new value. Please note: You will \033[1mHAVE\033[0m to read the docs\n"\r
163                          "dir, otherwise you won't have a config file!\n\n");\r
164 \r
165 }\r
166 \r
167 void Run()\r
168 {\r
169         int max_fd = 1024;\r
170         bool use_iocp = false;\r
171         bool support_ip6links = false;\r
172         char mod_path[MAX_PATH];\r
173         char config_file[MAX_PATH];\r
174         char library_dir[MAX_PATH];\r
175         char base_path[MAX_PATH];\r
176         char bin_dir[MAX_PATH];\r
177         char revision_text[MAX_PATH];\r
178 \r
179         int max_clients = 1024;\r
180         int nicklen = 31;\r
181         int chanlen = 64;\r
182         int modechanges = 20;\r
183         int identlen = 12;\r
184         int quitlen = 255;\r
185         int topiclen = 500;\r
186         int kicklen = 255;\r
187         int rllen = 128;\r
188         int awaylen = 200;\r
189         int revision = get_svn_revision(revision_text, MAX_PATH);\r
190         char version[514];\r
191 \r
192         // grab version\r
193         FILE * fI = fopen("..\\src\\version.sh", "r");\r
194         if(fI)\r
195         {\r
196                 fgets(version, 514, fI);\r
197                 fgets(version, 514, fI);\r
198                 char * p2 = version;\r
199                 while(*p2 != '\"')\r
200                         ++p2;\r
201                 ++p2;\r
202                 strcpy(version, p2);\r
203                 p2 = version;\r
204                 while(*p2 != '\"')\r
205                         ++p2;\r
206                 *p2 = 0;\r
207                 fclose(fI);\r
208         }\r
209         else\r
210                 strcpy(version, "InspIRCD-Unknown");\r
211         printf_c("Your operating system is: \033[1;32mwindows \033[0m\n");\r
212         printf_c("InspIRCd revision ID: \033[1;32m%s \033[0m\n\n", revision ? revision_text : "(Non-SVN build)");\r
213 \r
214         max_fd = get_int_option("What is the maximum file descriptor count you would like to allow?", 1024);\r
215 \r
216         // detect windows\r
217         if(iswinxp())\r
218         {\r
219                 printf_c("You are running Windows XP or above, and IOCP support is most likely available.\n"\r
220                              "This removes the socket number limitation of select and is much more efficent.\n"\r
221                                  "If you are unsure, answer yes.\n\n");\r
222 \r
223                 use_iocp = get_bool_option("Do you want to use the IOCP implementation?", true);\r
224         }\r
225 \r
226         support_ip6links = get_bool_option("\nYou have chosen to build an \033[1;32mIPV4-only\033[0m server.\nWould you like to enable support for linking to IPV6-enabled InspIRCd servers?\nIf you are using a recent operating system and are unsure, answer yes.\nIf you answer 'no' here, your InspIRCd server will be unable\nto parse IPV6 addresses (e.g. for CIDR bans)", \r
227                 true);\r
228         \r
229         printf_c("\033[1mAll paths are relative to the binary directory.\033[0m\n");\r
230         get_string_option("In what directory do you wish to install the InspIRCd base?", "..", base_path);\r
231         get_string_option("In what directory are the configuration files?", "../conf", config_file);\r
232         get_string_option("In what directory are the modules to be compiled to?", "../modules", mod_path);\r
233         get_string_option("In what directory is the IRCd binary to be placed?", ".", bin_dir);\r
234         get_string_option("In what directory are the IRCd libraries to be placed?", "../lib", library_dir);\r
235 \r
236         printf_c("The following questions will ask you for various figures relating\n"\r
237                 "To your IRCd install. Please note that these should usually be left\n"\r
238                 "as defaults unless you have a real reason to change them. If they\n"\r
239                 "changed, then the values must be identical on all servers on your\n"\r
240                 "network, or malfunctions and/or crashes may occur, with the exception\n"\r
241                 "of the 'maximum number of clients' setting which may be different on\n"\r
242                 "different servers on the network.\n\n");\r
243 \r
244     \r
245         max_clients = get_int_option("Please enter the maximum number of clients at any one time?", 1024);\r
246         nicklen = get_int_option("Please enter the maximum length of nicknames?", 31);\r
247         chanlen = get_int_option("Please enter the maximum length of channel names?", 64);\r
248         modechanges = get_int_option("Please enter the maximum number of mode changes in one line?", 20);\r
249         identlen = get_int_option("Please enter the maximum length of an ident (username)?", 12);\r
250         quitlen = get_int_option("Please enter the maximum length of a quit message?", 255);\r
251         topiclen = get_int_option("Please enter the maximum length of a channel topic?", 307);\r
252         kicklen = get_int_option("Please enter the maximum length of a kick message?", 255);\r
253         rllen = get_int_option("Please enter the maximum length of a GECOS (real name)?", 128);\r
254         awaylen = get_int_option("Please enter the maximum length of an away message?", 200);\r
255 \r
256         printf_c("\n\033[1;32mPre-build configuration is complete!\n\n");       sc(TNORMAL);\r
257 \r
258         // dump all the options back out\r
259         printf_c("\033[0mBase install path:\033[1;32m        %s\n", base_path);\r
260         printf_c("\033[0mConfig path:\033[1;32m              %s\n", config_file);\r
261         printf_c("\033[0mModule path:\033[1;32m              %s\n", mod_path);\r
262         printf_c("\033[0mLibrary path:\033[1;32m             %s\n", library_dir);\r
263         printf_c("\033[0mSocket Engine:\033[1;32m            %s\n", use_iocp ? "iocp" : "select");\r
264         printf_c("\033[0mMax file descriptors:\033[1;32m     %u\n", max_fd);\r
265         printf_c("\033[0mMax connections:\033[1;32m          %u\n", max_clients);\r
266         printf_c("\033[0mMax nickname length:\033[1;32m      %u\n", nicklen);\r
267         printf_c("\033[0mMax channel length:\033[1;32m       %u\n", chanlen);\r
268         printf_c("\033[0mMax mode length:\033[1;32m          %u\n", modechanges);\r
269         printf_c("\033[0mMax ident length:\033[1;32m         %u\n", identlen);\r
270         printf_c("\033[0mMax quit length:\033[1;32m          %u\n", quitlen);\r
271         printf_c("\033[0mMax topic length:\033[1;32m         %u\n", topiclen);\r
272         printf_c("\033[0mMax kick length:\033[1;32m          %u\n", kicklen);\r
273         printf_c("\033[0mMax name length:\033[1;32m          %u\n", rllen);\r
274         printf_c("\033[0mMax away length:\033[1;32m          %u\n", awaylen);\r
275         printf("\n"); sc(TNORMAL);\r
276         if(get_bool_option("Are these settings correct?", true) == false)\r
277         {\r
278                 Run();\r
279                 return;\r
280         }\r
281         printf("\n");\r
282 \r
283         // escape the pathes\r
284         escape_string(config_file, MAX_PATH);\r
285         escape_string(mod_path, MAX_PATH);\r
286         escape_string(library_dir, MAX_PATH);\r
287 \r
288         printf("\nWriting inspircd_config.h...");\r
289         FILE * f = fopen("inspircd_config.h", "w");\r
290         fprintf(f, "/* Auto generated by configure, do not modify! */\n");\r
291         fprintf(f, "#ifndef __CONFIGURATION_AUTO__\n");\r
292         fprintf(f, "#define __CONFIGURATION_AUTO__\n\n");\r
293         if(use_iocp)\r
294                 fprintf(f, "#define CONFIG_USE_IOCP 1\n\n");\r
295 \r
296         fprintf(f, "#define CONFIG_FILE \"%s/inspircd.conf\"\n", config_file);\r
297         fprintf(f, "#define MOD_PATH \"%s\"\n", mod_path);\r
298         fprintf(f, "#define MAX_DESCRIPTORS %u\n", max_fd);\r
299         fprintf(f, "#define MAXCLIENTS %u\n", max_clients);\r
300         fprintf(f, "#define MAXCLIENTS_S \"%u\"\n", max_clients);\r
301         fprintf(f, "#define SOMAXCONN_S \"128\"\n");\r
302         fprintf(f, "#define NICKMAX %u\n", nicklen+1);\r
303         fprintf(f, "#define CHANMAX %u\n", chanlen+1);\r
304         fprintf(f, "#define MAXMODES %u\n", modechanges);\r
305         fprintf(f, "#define IDENTMAX %u\n", identlen);\r
306         fprintf(f, "#define MAXQUIT %u\n", quitlen);\r
307         fprintf(f, "#define MAXTOPIC %u\n", topiclen);\r
308         fprintf(f, "#define MAXKICK %u\n", kicklen);\r
309         fprintf(f, "#define MAXGECOS %u\n", rllen);\r
310         fprintf(f, "#define MAXAWAY %u\n", awaylen);\r
311         fprintf(f, "#define LIBRARYDIR \"%s\"\n", library_dir);\r
312         fprintf(f, "#define VERSION \"%s\"\n", version);\r
313         fprintf(f, "#define REVISION \"%s\"\n", revision_text);\r
314         if(support_ip6links)\r
315                 fprintf(f, "#define SUPPORT_IP6LINKS 1\n");\r
316 \r
317         OSVERSIONINFO vi;\r
318         vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);\r
319         GetVersionEx(&vi);\r
320         fprintf(f, "#define SYSTEM \"Windows %u.%u.%u %s\"\n", vi.dwMajorVersion, vi.dwMinorVersion, vi.dwBuildNumber, vi.szCSDVersion);\r
321         fprintf(f, "#define MAXBUF 514\n");\r
322 \r
323         fprintf(f, "\n#include \"inspircd_win32wrapper.h\"\n\n");\r
324         fprintf(f, "#endif\n\n");\r
325         fclose(f);\r
326 \r
327         sc(TGREEN); printf(" done\n"); sc(TNORMAL);\r
328         printf("Writing inspircd_se_config.h...");\r
329 \r
330         f = fopen("inspircd_se_config.h", "w");\r
331         fprintf(f, "/* Auto generated by configure, do not modify or commit to svn! */\n");\r
332         fprintf(f, "#ifndef __CONFIGURATION_SOCKETENGINE__\n");\r
333         fprintf(f, "#define __CONFIGURATION_SOCKETENGINE__\n\n");\r
334         fprintf(f, "#include \"socketengine_%s.h\"\n\n", use_iocp ? "iocp" : "select");\r
335         fprintf(f, "#endif\n\n");\r
336         fclose(f);\r
337 \r
338         sc(TGREEN); printf(" done\n"); sc(TNORMAL);\r
339         printf("Writing command and module compilation scripts...");\r
340         WriteCompileCommands();\r
341         WriteCompileModules();\r
342         sc(TGREEN); printf(" done\n"); sc(TNORMAL);\r
343 \r
344         printf("\nconfigure is done.. exiting!\n");\r
345 }\r
346 \r
347 void WriteCompileCommands()\r
348 {\r
349         char commands[300][100];\r
350         int command_count = 0;\r
351         printf("\n  Finding Command Sources...\n");\r
352         WIN32_FIND_DATA fd;\r
353         HANDLE fh = FindFirstFile("..\\src\\cmd_*.cpp", &fd);\r
354         if(fh == INVALID_HANDLE_VALUE)\r
355                 printf_c("\033[1;32m  No command sources could be found! This \033[1m*could*\033[1;32m be a bad thing.. :P\033[0m");\r
356         else\r
357         {\r
358                 sc(TGREEN);\r
359                 do \r
360                 {\r
361                         strcpy(commands[command_count], fd.cFileName);\r
362                         commands[command_count][strlen(fd.cFileName) - 4] = 0;\r
363                         printf("    %s\n", commands[command_count]);\r
364                         ++command_count;\r
365                 } while(FindNextFile(fh, &fd));\r
366                 sc(TNORMAL);\r
367         }\r
368     \r
369         // Write our spiffy new makefile :D\r
370         // I am such a lazy fucker :P\r
371 #ifdef _DEBUG\r
372         FILE * f = fopen("..\\src\\commands.mak", "w");\r
373 #else\r
374         FILE * f = fopen("..\\src\\commands-release.mak", "w");\r
375 #endif\r
376 \r
377         fprintf(f, "# Generated at SOMETIME\n");\r
378         fprintf(f, "!include <win32.mak>\n\n");\r
379         fprintf(f, "all: ");\r
380 \r
381         // dump modules.. first time :)\r
382         for(int i = 0; i < command_count; ++i)\r
383                 fprintf(f, "%s.so ", commands[i]);\r
384 \r
385         fprintf(f, "\n.cpp.obj:\n");\r
386 #ifdef _DEBUG\r
387         fprintf(f, "  $(cc) /nologo /LD /Od /I \".\" /I \"../include\" /I \"../include/modes\" /I \"../include/commands\" /I \"../win\" /D \"WIN32\" /D \"_DEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"DLL_BUILD\" /Gm /EHsc /GS /RTC1 /MTd /Fo\"Debug/\" /Fd\"Debug/vc70.pdb\" /W3 /Wp64 /Zi /TP $*.cpp ..\\win\\inspircd_memory_functions.cpp /link ..\\bin\\debug\\bin\\inspircd.lib /OUT:\"$*.so\"\n\n");\r
388 #else\r
389         fprintf(f, "  $(cc) /nologo /LD /Od /I \".\" /I \"../include\" /I \"../include/modes\" /I \"../include/commands\" /I \"../win\" /D \"WIN32\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"DLL_BUILD\" /EHsc /GS /MT /Fo\"Release/\" /Fd\"Release/vc70.pdb\" /W3 /Wp64 /Zi /TP $*.cpp ..\\win\\inspircd_memory_functions.cpp /link ..\\bin\\release\\bin\\inspircd.lib /OUT:\"$*.so\"\n\n");\r
390 #endif\r
391 \r
392         \r
393         // dump modules.. again the second and last time :)\r
394         for(int i = 0; i < command_count; ++i)\r
395                 fprintf(f, "%s.so : %s.obj\n", commands[i], commands[i]);\r
396 \r
397         fprintf(f, "\n");\r
398         fclose(f);\r
399 }\r
400 \r
401 void WriteCompileModules()\r
402 {\r
403         char modules[300][100];\r
404         int module_count = 0;\r
405 \r
406         printf("Finding Modules...\n");\r
407         WIN32_FIND_DATA fd;\r
408         HANDLE fh = FindFirstFile("..\\src\\modules\\m_*.cpp", &fd);\r
409         if(fh == INVALID_HANDLE_VALUE)\r
410                 printf_c("\033[1;32m  No module sources could be found! This \033[1m*could*\033[1;32m be a bad thing.. :P\033[0m");\r
411         else\r
412         {\r
413                 sc(TGREEN);\r
414                 do \r
415                 {\r
416                         strcpy(modules[module_count], fd.cFileName);\r
417                         modules[module_count][strlen(fd.cFileName) - 4] = 0;\r
418                         printf("  %s\n", modules[module_count]);\r
419                         ++module_count;\r
420                 } while(FindNextFile(fh, &fd));\r
421                 sc(TNORMAL);\r
422         }\r
423 \r
424         // Write our spiffy new makefile :D\r
425         // I am such a lazy fucker :P\r
426 #ifdef _DEBUG\r
427         FILE * f = fopen("..\\src\\modules\\modules.mak", "w");\r
428 #else\r
429         FILE * f = fopen("..\\src\\modules\\modules-release.mak", "w");\r
430 #endif\r
431 \r
432         fprintf(f, "# Generated at SOMETIME\n");\r
433         fprintf(f, "!include <win32.mak>\n\n");\r
434         fprintf(f, "all: ");\r
435 \r
436         // dump modules.. first time :)\r
437         for(int i = 0; i < module_count; ++i)\r
438                 fprintf(f, "%s.so ", modules[i]);\r
439 \r
440         fprintf(f, "\n.cpp.obj:\n");\r
441 #ifdef _DEBUG\r
442         fprintf(f, "  $(cc) /nologo /LD /Od /I \".\" /I \"../../include\" /I \"../../include/modes\" /I \"../../include/modules\" /I \"../../win\" /D \"WIN32\" /D \"_DEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"DLL_BUILD\" /Gm /EHsc /GS /RTC1 /MTd /Fo\"Debug/\" /Fd\"Debug/vc70.pdb\" /W3 /Wp64 /Zi /TP $*.cpp ..\\..\\win\\inspircd_memory_functions.cpp /link ..\\..\\bin\\debug\\bin\\inspircd.lib ws2_32.lib /OUT:\"$*.so\"\n\n");\r
443 #else\r
444         fprintf(f, "  $(cc) /nologo /LD /Od /I \".\" /I \"../../include\" /I \"../../include/modes\" /I \"../../include/modules\" /I \"../../win\" /D \"WIN32\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"DLL_BUILD\" /EHsc /GS /MT /Fo\"Release/\" /Fd\"Release/vc70.pdb\" /W3 /Wp64 /Zi /TP $*.cpp ..\\..\\win\\inspircd_memory_functions.cpp /link ..\\..\\bin\\release\\bin\\inspircd.lib ws2_32.lib /OUT:\"$*.so\"\n\n");\r
445 #endif\r
446 \r
447 \r
448         // dump modules.. again the second and last time :)\r
449         for(int i = 0; i < module_count; ++i)\r
450                 fprintf(f, "%s.so : %s.obj\n", modules[i], modules[i]);\r
451 \r
452         fprintf(f, "\n");\r
453         fclose(f);\r
454 }\r