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