]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - win/inspircd_win32wrapper.cpp
2be5a8bcdf59382bf99ccbdaa8e1c556158c806d
[user/henk/code/inspircd.git] / win / inspircd_win32wrapper.cpp
1 #include "inspircd_win32wrapper.h"\r
2 #include "inspircd.h"\r
3 #include <string>\r
4 #include <errno.h>\r
5 #include <assert.h>\r
6 using namespace std;\r
7 \r
8 #ifndef INADDR_NONE\r
9 #define INADDR_NONE 0xffffffff\r
10 #endif\r
11 \r
12 HANDLE hIPCPipe;\r
13 \r
14 int inet_aton(const char *cp, struct in_addr *addr)\r
15 {\r
16         unsigned long ip = inet_addr(cp);\r
17         addr->s_addr = ip;\r
18         return (addr->s_addr == INADDR_NONE) ? 0 : 1;\r
19 }\r
20 \r
21 const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt)\r
22 {\r
23 \r
24         if (af == AF_INET)\r
25         {\r
26                 struct sockaddr_in in;\r
27                 memset(&in, 0, sizeof(in));\r
28                 in.sin_family = AF_INET;\r
29                 memcpy(&in.sin_addr, src, sizeof(struct in_addr));\r
30                 getnameinfo((struct sockaddr *)&in, sizeof(struct sockaddr_in), dst, cnt, NULL, 0, NI_NUMERICHOST);\r
31                 return dst;\r
32         }\r
33         else if (af == AF_INET6)\r
34         {\r
35                 struct sockaddr_in6 in;\r
36                 memset(&in, 0, sizeof(in));\r
37                 in.sin6_family = AF_INET6;\r
38                 memcpy(&in.sin6_addr, src, sizeof(struct in_addr6));\r
39                 getnameinfo((struct sockaddr *)&in, sizeof(struct sockaddr_in6), dst, cnt, NULL, 0, NI_NUMERICHOST);\r
40                 return dst;\r
41         }\r
42         return NULL;\r
43 }\r
44 \r
45 int geteuid()\r
46 {\r
47         return 1;\r
48 }\r
49 \r
50 int inet_pton(int af, const char *src, void *dst)\r
51 {\r
52         sockaddr_in sa;\r
53         int len = sizeof(SOCKADDR);\r
54         int rv = WSAStringToAddress((LPSTR)src, af, NULL, (LPSOCKADDR)&sa, &len);\r
55         memcpy(dst, &sa.sin_addr, sizeof(struct in_addr));\r
56         return rv;\r
57 }\r
58 \r
59 char * strtok_r(char *_String, const char *_Control, char **_Context)\r
60 {\r
61         unsigned char *str;\r
62         const unsigned char *ctl = (const unsigned char*)_Control;\r
63         unsigned char map[32];\r
64 \r
65         if (_Context == 0 || !_Control)\r
66                 return 0;\r
67 \r
68         if (!(_String != NULL || *_Context != NULL))\r
69                 return 0;\r
70 \r
71         memset(map, 0, 32);\r
72 \r
73         do {\r
74                 map[*ctl >> 3] |= (1 << (*ctl & 7));\r
75         } while (*ctl++);\r
76 \r
77         /* If string is NULL, set str to the saved\r
78         * pointer (i.e., continue breaking tokens out of the string\r
79         * from the last strtok call) */\r
80         if (_String != NULL)\r
81         {\r
82                 str = (unsigned char*)_String;\r
83         }\r
84         else\r
85         {\r
86                 str = (unsigned char*)*_Context;\r
87         }\r
88 \r
89         /* Find beginning of token (skip over leading delimiters). Note that\r
90         * there is no token iff this loop sets str to point to the terminal\r
91         * null (*str == 0) */\r
92         while ((map[*str >> 3] & (1 << (*str & 7))) && *str != 0)\r
93         {\r
94                 str++;\r
95         }\r
96 \r
97         _String = (char*)str;\r
98 \r
99         /* Find the end of the token. If it is not the end of the string,\r
100         * put a null there. */\r
101         for ( ; *str != 0 ; str++ )\r
102         {\r
103                 if (map[*str >> 3] & (1 << (*str & 7)))\r
104                 {\r
105                         *str++ = 0;\r
106                         break;\r
107                 }\r
108         }\r
109 \r
110         /* Update context */\r
111         *_Context = (char*)str;\r
112 \r
113         /* Determine if a token has been found. */\r
114         if (_String == (char*)str)\r
115         {\r
116                 return NULL;\r
117         }\r
118         else\r
119         {\r
120                 return _String;\r
121         }\r
122 }\r
123 \r
124 void setcolor(int color_code)\r
125 {\r
126         SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color_code);\r
127 }\r
128 \r
129 DIR * opendir(const char * path)\r
130 {\r
131         std::string search_path = string(path) + "\\*.*";\r
132         WIN32_FIND_DATA fd;\r
133         HANDLE f = FindFirstFile(search_path.c_str(), &fd);\r
134         if (f != INVALID_HANDLE_VALUE)\r
135         {\r
136                 DIR * d = new DIR;\r
137                 memcpy(&d->find_data, &fd, sizeof(WIN32_FIND_DATA));\r
138                 d->find_handle = f;\r
139                 d->first = true;\r
140                 return d;\r
141         }\r
142         else\r
143         {\r
144                 return 0;\r
145         }\r
146 }\r
147 \r
148 dirent * readdir(DIR * handle)\r
149 {\r
150         if (handle->first)\r
151                 handle->first = false;\r
152         else\r
153         {\r
154                 if (!FindNextFile(handle->find_handle, &handle->find_data))\r
155                         return 0;\r
156         }\r
157 \r
158         strncpy(handle->dirent_pointer.d_name, handle->find_data.cFileName, MAX_PATH);\r
159         return &handle->dirent_pointer;\r
160 }\r
161 \r
162 void closedir(DIR * handle)\r
163 {\r
164         FindClose(handle->find_handle);\r
165         delete handle;\r
166 }\r
167 \r
168 const char * dlerror()\r
169 {\r
170         static char errormessage[500];\r
171         DWORD error = GetLastError();\r
172         SetLastError(0);\r
173         if (error == 0)\r
174                 return 0;\r
175 \r
176         FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)errormessage, 500, 0);\r
177         return errormessage;\r
178 }\r
179 \r
180 int printf_c(const char * format, ...)\r
181 {\r
182         // Better hope we're not multithreaded, otherwise we'll have chickens crossing the road other side to get the to :P\r
183         static char message[500];\r
184         static char temp[10];\r
185         int color1, color2;\r
186         \r
187         /* parse arguments */\r
188         va_list ap;\r
189         va_start(ap, format);\r
190         vsnprintf(message, 500, format, ap);\r
191         va_end(ap);\r
192 \r
193         /* search for unix-style escape sequences */\r
194         int t;\r
195         int c = 0;\r
196         const char * p = message;\r
197         while(*p != 0)\r
198         {\r
199                 if (*p == '\033')\r
200                 {\r
201                         // Escape sequence -> copy into the temp buffer, and parse the color.\r
202                         p++;\r
203                         t = 0;\r
204                         while(*p != 'm')\r
205                         {\r
206                                 temp[t++] = *p;\r
207                                 ++p;\r
208                         }\r
209                         \r
210                         temp[t] = 0;\r
211                         p++;\r
212                         if (!_stricmp(temp, "[0"))\r
213                         {\r
214                                 // Returning to normal colour.\r
215                                 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);\r
216                         }\r
217                         else if (sscanf(temp, "[%u;%u", &color1, &color2) == 2)\r
218                         {\r
219                                 switch(color2)\r
220                                 {\r
221                                         case 32:                // Green\r
222                                                 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN | FOREGROUND_INTENSITY);\r
223                                         break;\r
224         \r
225                                         default:                // Unknown\r
226                                                 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);\r
227                                         break;\r
228                                 }\r
229                         }\r
230                         else\r
231                         {\r
232                                 char message[50];\r
233                                 sprintf("Unknown color code: %s", temp);\r
234                                 MessageBox(0, message, message, MB_OK);\r
235                         }\r
236                 }\r
237 \r
238                 putchar(*p);\r
239                 ++c;\r
240                 ++p;\r
241         }\r
242 \r
243         return c;\r
244 }\r
245 \r
246 int arg_counter = 1;\r
247 char optarg[514];\r
248 int getopt_long_only(int ___argc, char *const *___argv, const char *__shortopts, const struct option *__longopts, int *__longind)\r
249 {\r
250         // burlex todo: handle the shortops, at the moment it only works with longopts.\r
251 \r
252         if (___argc == 1 || arg_counter == ___argc)                     // No arguments (apart from filename)\r
253                 return -1;\r
254 \r
255         const char * opt = ___argv[arg_counter];\r
256         int return_val = 0;\r
257 \r
258         // if we're not an option, return an error.\r
259         if (strnicmp(opt, "--", 2) != 0)\r
260                 return 1;\r
261         else\r
262                 opt += 2;\r
263 \r
264 \r
265         // parse argument list\r
266         int i = 0;\r
267         for (; __longopts[i].name != 0; ++i)\r
268         {\r
269                 if (!strnicmp(__longopts[i].name, opt, strlen(__longopts[i].name)))\r
270                 {\r
271                         // woot, found a valid argument =)\r
272                         char * par = 0;\r
273                         if ((arg_counter + 1) != ___argc)\r
274                         {\r
275                                 // grab the parameter from the next argument (if its not another argument)\r
276                                 if (strnicmp(___argv[arg_counter+1], "--", 2) != 0)\r
277                                 {\r
278                                         arg_counter++;          // Trash this next argument, we won't be needing it.\r
279                                         par = ___argv[arg_counter];\r
280                                 }\r
281                         }                       \r
282 \r
283                         // increment the argument for next time\r
284                         arg_counter++;\r
285 \r
286                         // determine action based on type\r
287                         if (__longopts[i].has_arg == required_argument && !par)\r
288                         {\r
289                                 // parameter missing and its a required parameter option\r
290                                 return 1;\r
291                         }\r
292 \r
293                         // store argument in optarg\r
294                         if (par)\r
295                                 strncpy(optarg, par, 514);\r
296 \r
297                         if (__longopts[i].flag != 0)\r
298                         {\r
299                                 // this is a variable, we have to set it if this argument is found.\r
300                                 *__longopts[i].flag = 1;\r
301                                 return 0;\r
302                         }\r
303                         else\r
304                         {\r
305                                 if (__longopts[i].val == -1 || par == 0)\r
306                                         return 1;\r
307                                 \r
308                                 return __longopts[i].val;\r
309                         }                       \r
310                         break;\r
311                 }\r
312         }\r
313 \r
314         // return 1 (invalid argument)\r
315         return 1;\r
316 }\r
317 \r
318 /* IPC Messages */\r
319 #define IPC_MESSAGE_REHASH      1\r
320 #define IPC_MESSAGE_DIE         2\r
321 #define IPC_MESSAGE_RESTART     3\r
322 \r
323 void InitIPC()\r
324 {\r
325         static DWORD buflen = 1024;\r
326         static const char * pipename = "\\\\.\\mailslot\\Inspircd";\r
327         hIPCPipe = CreateMailslot(pipename, buflen, 0, 0);\r
328         if (hIPCPipe == INVALID_HANDLE_VALUE)\r
329                 printf("IPC Pipe could not be created. Are you sure you didn't start InspIRCd twice?\n");\r
330 }\r
331 \r
332 void CheckIPC(InspIRCd * Instance)\r
333 {\r
334         if (hIPCPipe == INVALID_HANDLE_VALUE)\r
335                 return;\r
336 \r
337         DWORD bytes;\r
338         DWORD action;\r
339 \r
340         BOOL res = ReadFile(hIPCPipe, &action, sizeof(DWORD), &bytes, 0);\r
341         if (!res)\r
342         {\r
343                 if (GetLastError() != ERROR_SEM_TIMEOUT)\r
344                         Instance->Log(DEFAULT, "IPC Pipe Error %u: %s", GetLastError(), dlerror());\r
345                 return;\r
346         }\r
347 \r
348         switch (action)\r
349         {\r
350                 case IPC_MESSAGE_REHASH:\r
351                         InspIRCd::Rehash(0);\r
352                 break;\r
353                 \r
354                 case IPC_MESSAGE_DIE:\r
355                         InspIRCd::Exit(0);\r
356                 break;\r
357 \r
358                 case IPC_MESSAGE_RESTART:\r
359                         Instance->Restart("IPC_MESSAGE_RESTART received by mailslot.");\r
360                 break;\r
361         }\r
362 }\r
363 \r
364 void CloseIPC()\r
365 {\r
366         CloseHandle(hIPCPipe);\r
367 }\r
368 \r
369 \r
370 /* These three functions were created from looking at how ares does it\r
371  * (...and they look far tidier in C++)\r
372  */\r
373 \r
374 /* Get active nameserver */\r
375 bool GetNameServer(HKEY regkey, const char *key, char* &output)\r
376 {\r
377         DWORD size = 0;\r
378         DWORD result = RegQueryValueEx(regkey, key, 0, NULL, NULL, &size);\r
379         if (((result != ERROR_SUCCESS) && (result != ERROR_MORE_DATA)) || (!size))\r
380                 return false;\r
381 \r
382         output = new char[size+1];\r
383 \r
384         if ((RegQueryValueEx(regkey, key, 0, NULL, (LPBYTE)output, &size) != ERROR_SUCCESS) || (!*output))\r
385         {\r
386                 delete output;\r
387                 return false;\r
388         }\r
389         return true;\r
390 }\r
391 \r
392 /* Check a network interface for its nameserver */\r
393 bool GetInterface(HKEY regkey, const char *key, char* &output)\r
394 {\r
395         char buf[39];\r
396         DWORD size = 39;\r
397         int idx = 0;\r
398         HKEY top;\r
399 \r
400         while (RegEnumKeyEx(regkey, idx++, buf, &size, 0, NULL, NULL, NULL) != ERROR_NO_MORE_ITEMS)\r
401         {\r
402                 size = 39;\r
403                 if (RegOpenKeyEx(regkey, buf, 0, KEY_QUERY_VALUE, &top) != ERROR_SUCCESS)\r
404                         continue;\r
405                 int rc = GetNameServer(top, key, output);\r
406                 RegCloseKey(top);\r
407                 if (rc)\r
408                         return true;\r
409         }\r
410         return false;\r
411 }\r
412 \r
413 \r
414 std::string FindNameServerWin()\r
415 {\r
416         std::string returnval = "127.0.0.1";\r
417         HKEY top, key;\r
418         char* dns = NULL;\r
419 \r
420         /* Lets see if the correct registry hive and tree exist */\r
421         if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "System\\CurrentControlSet\\Services\\Tcpip\\Parameters", 0, KEY_READ, &top) == ERROR_SUCCESS)\r
422         {\r
423                 /* If they do, attempt to get the nameserver name */\r
424                 RegOpenKeyEx(top, "Interfaces", 0, KEY_QUERY_VALUE|KEY_ENUMERATE_SUB_KEYS, &key);\r
425                 if ((GetNameServer(top, "NameServer", dns)) || (GetNameServer(top, "DhcpNameServer", dns))\r
426                         || (GetInterface(key, "NameServer", dns)) || (GetInterface(key, "DhcpNameServer", dns)))\r
427                 {\r
428                         if (dns)\r
429                         {\r
430                                 returnval = dns;\r
431                                 delete dns;\r
432                         }\r
433                 }\r
434                 RegCloseKey(key);\r
435                 RegCloseKey(top);\r
436         }\r
437         return returnval;\r
438 }\r
439 \r
440 \r
441 void ClearConsole()\r
442 {\r
443         COORD coordScreen = { 0, 0 };    /* here's where we'll home the cursor */\r
444         HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);\r
445         BOOL bSuccess;\r
446         DWORD cCharsWritten;\r
447         CONSOLE_SCREEN_BUFFER_INFO csbi; /* to get buffer info */ \r
448         DWORD dwConSize;                 /* number of character cells in the current buffer */ \r
449 \r
450         /* get the number of character cells in the current buffer */ \r
451 \r
452         if (GetConsoleScreenBufferInfo( hConsole, &csbi ))\r
453         {\r
454                 dwConSize = csbi.dwSize.X * csbi.dwSize.Y;\r
455                 /* fill the entire screen with blanks */ \r
456                 if (FillConsoleOutputCharacter( hConsole, (TCHAR) ' ', dwConSize, coordScreen, &cCharsWritten ))\r
457                 {\r
458                         /* get the current text attribute */ \r
459                         if (GetConsoleScreenBufferInfo( hConsole, &csbi ))\r
460                         {\r
461                                 /* now set the buffer's attributes accordingly */\r
462                                 if (FillConsoleOutputAttribute( hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten ))\r
463                                 {\r
464                                         /* put the cursor at (0, 0) */\r
465                                         SetConsoleCursorPosition( hConsole, coordScreen );\r
466                                 }\r
467                         }\r
468                 }\r
469         }\r
470         return;\r
471 }