diff options
Diffstat (limited to 'src/sig_handler.c')
-rw-r--r-- | src/sig_handler.c | 169 |
1 files changed, 155 insertions, 14 deletions
diff --git a/src/sig_handler.c b/src/sig_handler.c index 69dc0a7..461c341 100644 --- a/src/sig_handler.c +++ b/src/sig_handler.c @@ -37,21 +37,18 @@ #include "log.h" -#ifndef _MSC_VER +#include "sig_handler.h" +#include <errno.h> + +#ifndef WINVER + #include <signal.h> #include <unistd.h> #include <fcntl.h> #include <sys/select.h> -#include <errno.h> - -#include "sig_handler.h" - -#include <stdio.h> - static int sig_pipe_fds[2]; - static void sig_handler(int sig) { sigset_t set; @@ -159,21 +156,165 @@ void signal_stop() close(sig_pipe_fds[0]); close(sig_pipe_fds[1]); } + #else -int signal_init() + +#include <winsock2.h> +#include <windows.h> + +static SOCKET sig_sock_fds[2]; +static SOCKET server_sock; + +static DWORD WINAPI signal_connect_thread(void* p) { - // nothing yet + u_int16_t port = *((u_int16_t*)p); + + SOCKET client; + client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if(client == INVALID_SOCKET) { + log_printf(ERROR, "Error at socket(): 0x%04X\n", WSAGetLastError()); + return -1; + } + + struct sockaddr_in server; + server.sin_family = AF_INET; + server.sin_addr.s_addr = inet_addr("127.0.0.1"); + server.sin_port = port; + + int cnt = 0; + int ret = SOCKET_ERROR; + do { + Sleep(100); + ret = connect(client, (SOCKADDR*) &server, sizeof(server)); + cnt++; + } + while(ret != 0 && cnt < 10); + + if(ret != 0) { + log_printf(ERROR, "connect() failed: 0x%04X", WSAGetLastError()); + closesocket(client); + return -1; + } + + log_printf(DEBUG, "sig_handler connected to port %d", port); + + sig_sock_fds[1] = client; + return 0; } +static BOOL WINAPI signal_ctrl_handler(DWORD ctrlType) +{ + char c = (char)ctrlType; + send(sig_sock_fds[1], &c, 1, 0); + return 1; +} + +int signal_init() +{ + WSADATA wsaData; + int ret = WSAStartup(MAKEWORD(2,2), &wsaData); + if(ret != NO_ERROR) { + log_printf(ERROR, "Error at WSAStartup(): 0x%04X", WSAGetLastError()); + return -1; + } + + server_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if(server_sock == INVALID_SOCKET) { + log_printf(ERROR, "Error at socket(): 0x%04X\n", WSAGetLastError()); + WSACleanup(); + return -1; + } + + struct sockaddr_in service; + service.sin_family = AF_INET; + service.sin_addr.s_addr = inet_addr("127.0.0.1"); + service.sin_port = 0; + + if(bind(server_sock, (SOCKADDR*) &service, sizeof(service)) == SOCKET_ERROR) { + log_printf(ERROR, "bind() failed: 0x%04X", WSAGetLastError()); + closesocket(server_sock); + WSACleanup(); + return -1; + } + + struct sockaddr_in hugo; + int hugo_len = sizeof(hugo); + if(getsockname(server_sock, (SOCKADDR*) &hugo, &hugo_len) == SOCKET_ERROR) { + log_printf(ERROR, "getsockname() failed: 0x%04X", WSAGetLastError()); + closesocket(server_sock); + WSACleanup(); + return -1; + } + + if(listen(server_sock, 1) == SOCKET_ERROR) { + log_printf(ERROR, "listen() failed: 0x%04X", WSAGetLastError()); + closesocket(server_sock); + WSACleanup(); + return -1; + } + + log_printf(DEBUG, "sig_handler listening on port %d", hugo.sin_port); + + HANDLE t = CreateThread(NULL, 0, signal_connect_thread, &(hugo.sin_port), 0, NULL); + if(t == INVALID_HANDLE_VALUE) { + log_printf(ERROR, "CreateThread() failed: 0x%04X", GetLastError()); + closesocket(server_sock); + WSACleanup(); + return -1; + } + + sig_sock_fds[0] = accept(server_sock, NULL, NULL); + if(sig_sock_fds[0] == INVALID_SOCKET) { + log_printf(ERROR, "accept() failed: 0x%04X", WSAGetLastError()); + closesocket(server_sock); + WSACleanup(); + WaitForSingleObject(t, INFINITE); + return -1; + } + + WaitForSingleObject(t, INFINITE); + + if(!SetConsoleCtrlHandler(signal_ctrl_handler, 1)) { + log_printf(ERROR, "adding console ctrl handler failed: 0x%04X" , GetLastError()); + } + + return sig_sock_fds[0]; +} + int signal_handle() { - // nothing yet - return 0; + char c; + int ret = recv(sig_sock_fds[0], &c, 1, 0); + if(ret == 1) { + switch(c) { + case CTRL_C_EVENT: log_printf(NOTICE, "CTRL-C Event received, exitting"); return 1; + case CTRL_BREAK_EVENT: log_printf(NOTICE, "CTRL-Break Event received, ignoring"); return 1; + case CTRL_CLOSE_EVENT: log_printf(NOTICE, "Close Event received, exitting"); return 1; + case CTRL_LOGOFF_EVENT: log_printf(NOTICE, "LogOff Event received, exitting"); return 1; + case CTRL_SHUTDOWN_EVENT: log_printf(NOTICE, "Shutdown Event received, exitting"); return 1; + default: log_printf(NOTICE, "unknown event received 0x%02X, ignoring", c); return 0; + } + } + + if(ret == 0) { + log_printf(ERROR, "signal socket closed normally, exitting"); + return 1; + } + + log_printf(ERROR, "signal socket closed with error 0x%04X, exitting", GetLastError()); + return 1; } void signal_stop() { - // nothing yet + if(!SetConsoleCtrlHandler(signal_ctrl_handler, 0)) { + log_printf(ERROR, "removeing console ctrl handler failed: 0x%04X" , GetLastError()); + } + closesocket(sig_sock_fds[0]); + closesocket(sig_sock_fds[1]); + closesocket(server_sock); + WSACleanup(); + return; } -#endif
\ No newline at end of file +#endif |