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