summaryrefslogtreecommitdiff
path: root/src/sig_handler.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/sig_handler.c')
-rw-r--r--src/sig_handler.c169
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