]>
jfr.im git - solanum.git/blob - libratbox/src/win32.c
2 * ircd-ratbox: A slightly useful ircd.
3 * win32.c: select() compatible network routines.
5 * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
6 * Copyright (C) 1996-2002 Hybrid Development Team
7 * Copyright (C) 2001 Adrian Chadd <adrian@creative.net.au>
8 * Copyright (C) 2005-2006 Aaron Sethman <androsyn@ratbox.org>
9 * Copyright (C) 2002-2006 ircd-ratbox development team
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
26 * $Id: win32.c 25038 2008-01-23 16:03:08Z androsyn $
29 #include <libratbox_config.h>
30 #include <ratbox_lib.h>
31 #include <commio-int.h>
37 #define WM_SOCKET WM_USER
39 * having gettimeofday is nice...
44 unsigned __int64 ft_i64
;
49 #define Const64(x) x##LL
51 #define Const64(x) x##i64
53 /* Number of 100 nanosecond units from 1/1/1601 to 1/1/1970 */
54 #define EPOCH_BIAS Const64(116444736000000000)
59 return GetCurrentProcessId();
64 rb_gettimeofday(struct timeval
*tp
, void *not_used
)
68 /* this returns time in 100-nanosecond units (i.e. tens of usecs) */
69 GetSystemTimeAsFileTime(&ft
.ft_val
);
71 /* seconds since epoch */
72 tp
->tv_sec
= (long) ((ft
.ft_i64
- EPOCH_BIAS
) / Const64(10000000));
74 /* microseconds remaining */
75 tp
->tv_usec
= (long) ((ft
.ft_i64
/ Const64(10)) % Const64(1000000));
82 rb_spawn_process(const char *path
, const char **argv
)
84 PROCESS_INFORMATION pi
;
87 memset(&pi
, 0, sizeof(pi
));
88 memset(&si
, 0, sizeof(si
));
89 rb_strlcpy(cmd
, path
, sizeof(cmd
));
90 if(CreateProcess(cmd
, cmd
, NULL
, NULL
, TRUE
, 0, NULL
, NULL
, &si
, &pi
) == FALSE
)
93 return (pi
.dwProcessId
);
97 waitpid(int pid
, int *status
, int flags
)
99 DWORD timeout
= (flags
& WNOHANG
) ? 0 : INFINITE
;
103 hProcess
= OpenProcess(PROCESS_ALL_ACCESS
, TRUE
, pid
);
106 waitcode
= WaitForSingleObject(hProcess
, timeout
);
107 if(waitcode
== WAIT_TIMEOUT
)
109 CloseHandle(hProcess
);
112 else if(waitcode
== WAIT_OBJECT_0
)
114 if(GetExitCodeProcess(hProcess
, &waitcode
))
116 *status
= (int) ((waitcode
& 0xff) << 8);
117 CloseHandle(hProcess
);
121 CloseHandle(hProcess
);
130 setenv(const char *name
, const char *value
, int overwrite
)
136 if((buf
= getenv(name
)) != NULL
)
144 if(name
== NULL
|| value
== NULL
)
146 len
= strlen(name
) + strlen(value
) + 5;
147 buf
= rb_malloc(len
);
148 rb_snprintf(buf
, len
, "%s=%s", name
, value
);
155 kill(int pid
, int sig
)
158 hProcess
= OpenProcess(PROCESS_ALL_ACCESS
, TRUE
, pid
);
169 if(TerminateProcess(hProcess
, sig
))
173 CloseHandle(hProcess
);
184 rb_pass_fd_to_process(int fd
, pid_t process
, rb_fde_t
*F
)
186 WSAPROTOCOL_INFO info
;
187 WSADuplicateSocket((SOCKET
)fd
, process
, &info
);
188 rb_write(F
, &info
, sizeof(info
));
193 static LRESULT CALLBACK
194 rb_process_events(HWND nhwnd
, UINT umsg
, WPARAM wparam
, LPARAM lparam
)
203 F
= rb_find_fd(wparam
);
205 if(F
!= NULL
&& IsFDOpen(F
))
207 switch (WSAGETSELECTEVENT(lparam
))
213 if((hdl
= F
->read_handler
) != NULL
)
215 F
->read_handler
= NULL
;
226 if((hdl
= F
->write_handler
) != NULL
)
228 F
->write_handler
= NULL
;
229 data
= F
->write_data
;
230 F
->write_data
= NULL
;
246 return DefWindowProc(nhwnd
, umsg
, wparam
, lparam
);
252 rb_init_netio_win32(void)
254 /* this muchly sucks, but i'm too lazy to do overlapped i/o, maybe someday... -androsyn */
256 static const char *classname
= "ircd-ratbox-class";
259 wc
.lpfnWndProc
= (WNDPROC
) rb_process_events
;
264 wc
.hbrBackground
= NULL
;
265 wc
.lpszMenuName
= NULL
;
266 wc
.lpszClassName
= classname
;
267 wc
.hInstance
= GetModuleHandle(NULL
);
269 if(!RegisterClass(&wc
))
270 rb_lib_die("cannot register window class");
272 hwnd
= CreateWindow(classname
, classname
, WS_POPUP
, CW_USEDEFAULT
,
273 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
274 (HWND
) NULL
, (HMENU
) NULL
, wc
.hInstance
, NULL
);
276 rb_lib_die("could not create window");
281 rb_sleep(unsigned int seconds
, unsigned int useconds
)
285 tv
.tv_usec
= useconds
;
286 select(0, NULL
, NULL
, NULL
, &tv
);
290 rb_setup_fd_win32(rb_fde_t
* F
)
295 SetHandleInformation((HANDLE
) F
->fd
, HANDLE_FLAG_INHERIT
, 0);
301 if(ioctlsocket((SOCKET
) F
->fd
, FIONBIO
, &nonb
) == -1)
315 rb_setselect_win32(rb_fde_t
* F
, unsigned int type
, PF
* handler
, void *client_data
)
317 int old_flags
= F
->pflags
;
319 lrb_assert(IsFDOpen(F
));
321 /* Update the list, even though we're not using it .. */
322 if(type
& RB_SELECT_READ
)
325 F
->pflags
|= FD_CLOSE
| FD_READ
| FD_ACCEPT
;
327 F
->pflags
&= ~(FD_CLOSE
| FD_READ
| FD_ACCEPT
);
328 F
->read_handler
= handler
;
329 F
->read_data
= client_data
;
332 if(type
& RB_SELECT_WRITE
)
335 F
->pflags
|= FD_WRITE
| FD_CONNECT
;
337 F
->pflags
&= ~(FD_WRITE
| FD_CONNECT
);
338 F
->write_handler
= handler
;
339 F
->write_data
= client_data
;
342 if(old_flags
== 0 && F
->pflags
== 0)
345 if(F
->pflags
!= old_flags
)
347 WSAAsyncSelect(F
->fd
, hwnd
, WM_SOCKET
, F
->pflags
);
353 static int has_set_timer
= 0;
356 rb_select_win32(long delay
)
359 if(has_set_timer
== 0)
361 /* XXX should probably have this handle all the events
362 * instead of busy looping
364 SetTimer(hwnd
, 0, delay
, NULL
);
368 if(GetMessage(&msg
, NULL
, 0, 0) == FALSE
)
370 rb_lib_die("GetMessage failed..byebye");
374 DispatchMessage(&msg
);
383 wsock_strerror(int error
)
390 return "Interrupted system call";
392 return "Bad file number";
394 return "Permission denied";
396 return "Bad address";
398 return "Invalid argument";
400 return "Too many open sockets";
402 return "Operation would block";
404 return "Operation now in progress";
406 return "Operation already in progress";
408 return "Socket operation on non-socket";
409 case WSAEDESTADDRREQ
:
410 return "Destination address required";
412 return "Message too long";
414 return "Protocol wrong type for socket";
416 return "Bad protocol option";
417 case WSAEPROTONOSUPPORT
:
418 return "Protocol not supported";
419 case WSAESOCKTNOSUPPORT
:
420 return "Socket type not supported";
422 return "Operation not supported on socket";
423 case WSAEPFNOSUPPORT
:
424 return "Protocol family not supported";
425 case WSAEAFNOSUPPORT
:
426 return "Address family not supported";
428 return "Address already in use";
429 case WSAEADDRNOTAVAIL
:
430 return "Can't assign requested address";
432 return "Network is down";
434 return "Network is unreachable";
436 return "Net connection reset";
437 case WSAECONNABORTED
:
438 return "Software caused connection abort";
440 return "Connection reset by peer";
442 return "No buffer space available";
444 return "Socket is already connected";
446 return "Socket is not connected";
448 return "Can't send after socket shutdown";
449 case WSAETOOMANYREFS
:
450 return "Too many references, can't splice";
452 return "Connection timed out";
453 case WSAECONNREFUSED
:
454 return "Connection refused";
456 return "Too many levels of symbolic links";
457 case WSAENAMETOOLONG
:
458 return "File name too long";
460 return "Host is down";
461 case WSAEHOSTUNREACH
:
462 return "No route to host";
464 return "Directory not empty";
466 return "Too many processes";
468 return "Too many users";
470 return "Disc quota exceeded";
472 return "Stale NFS file handle";
474 return "Too many levels of remote in path";
476 return "Network system is unavailable";
477 case WSAVERNOTSUPPORTED
:
478 return "Winsock version out of range";
479 case WSANOTINITIALISED
:
480 return "WSAStartup not yet called";
482 return "Graceful shutdown in progress";
483 case WSAHOST_NOT_FOUND
:
484 return "Host not found";
486 return "No host data of that type was found";
488 return strerror(error
);
491 #else /* win32 not supported */
493 rb_init_netio_win32(void)
500 rb_setselect_win32(rb_fde_t
* F
, unsigned int type
, PF
* handler
, void *client_data
)
507 rb_select_win32(long delay
)
514 rb_setup_fd_win32(rb_fde_t
* F
)