Implement signals.

diff --git a/dlls/msvcrt/except.c b/dlls/msvcrt/except.c
index 44ac230..6ba972a 100644
--- a/dlls/msvcrt/except.c
+++ b/dlls/msvcrt/except.c
@@ -2,6 +2,7 @@
  * msvcrt.dll exception handling
  *
  * Copyright 2000 Jon Griffiths
+ * Copyright 2005 Juan Lang
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -37,12 +38,13 @@
 #include "wine/exception.h"
 #include "msvcrt.h"
 #include "excpt.h"
+#include "wincon.h"
+#include "msvcrt/float.h"
+#include "msvcrt/signal.h"
 #include "wine/debug.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
 
-typedef void (*MSVCRT_sig_handler_func)(void);
-
 /* VC++ extensions to Win32 SEH */
 typedef struct _SCOPETABLE
 {
@@ -385,11 +387,144 @@
 }
 #endif /* i386 */
 
+static __sighandler_t sighandlers[NSIG] = { SIG_DFL };
+
+static BOOL WINAPI msvcrt_console_handler(DWORD ctrlType)
+{
+    BOOL ret = FALSE;
+
+    switch (ctrlType)
+    {
+    case CTRL_C_EVENT:
+        if (sighandlers[SIGINT])
+        {
+            if (sighandlers[SIGINT] != SIG_IGN)
+                sighandlers[SIGINT](SIGINT);
+            ret = TRUE;
+        }
+        break;
+    }
+    return ret;
+}
+
+typedef void (*float_handler)(int, int);
+
+/* The exception codes are actually NTSTATUS values */
+struct
+{
+    NTSTATUS status;
+    int signal;
+} float_exception_map[] = {
+ { EXCEPTION_FLT_DENORMAL_OPERAND, _FPE_DENORMAL },
+ { EXCEPTION_FLT_DIVIDE_BY_ZERO, _FPE_ZERODIVIDE },
+ { EXCEPTION_FLT_INEXACT_RESULT, _FPE_INEXACT },
+ { EXCEPTION_FLT_INVALID_OPERATION, _FPE_INVALID },
+ { EXCEPTION_FLT_OVERFLOW, _FPE_OVERFLOW },
+ { EXCEPTION_FLT_STACK_CHECK, _FPE_STACKOVERFLOW },
+ { EXCEPTION_FLT_UNDERFLOW, _FPE_UNDERFLOW },
+};
+
+static LONG WINAPI msvcrt_exception_filter(struct _EXCEPTION_POINTERS *except)
+{
+    LONG ret = EXCEPTION_CONTINUE_SEARCH;
+
+    switch (except->ExceptionRecord->ExceptionCode)
+    {
+    case EXCEPTION_ACCESS_VIOLATION:
+        if (sighandlers[SIGSEGV])
+        {
+            if (sighandlers[SIGSEGV] != SIG_IGN)
+                sighandlers[SIGSEGV](SIGSEGV);
+            ret = EXCEPTION_CONTINUE_EXECUTION;
+        }
+        break;
+    /* According to
+     * http://msdn.microsoft.com/library/en-us/vclib/html/_CRT_signal.asp
+     * the FPE signal handler takes as a second argument the type of
+     * floating point exception.
+     */
+    case EXCEPTION_FLT_DENORMAL_OPERAND:
+    case EXCEPTION_FLT_DIVIDE_BY_ZERO:
+    case EXCEPTION_FLT_INEXACT_RESULT:
+    case EXCEPTION_FLT_INVALID_OPERATION:
+    case EXCEPTION_FLT_OVERFLOW:
+    case EXCEPTION_FLT_STACK_CHECK:
+    case EXCEPTION_FLT_UNDERFLOW:
+        if (sighandlers[SIGFPE])
+        {
+            if (sighandlers[SIGFPE] != SIG_IGN)
+            {
+                int i, float_signal = _FPE_INVALID;
+
+                float_handler handler = (float_handler)sighandlers[SIGFPE];
+                for (i = 0; i < sizeof(float_exception_map) /
+                 sizeof(float_exception_map[0]); i++)
+                    if (float_exception_map[i].status ==
+                     except->ExceptionRecord->ExceptionCode)
+                    {
+                        float_signal = float_exception_map[i].signal;
+                        break;
+                    }
+                handler(SIGFPE, float_signal);
+            }
+            ret = EXCEPTION_CONTINUE_EXECUTION;
+        }
+        break;
+    case EXCEPTION_ILLEGAL_INSTRUCTION:
+        if (sighandlers[SIGILL])
+        {
+            if (sighandlers[SIGILL] != SIG_IGN)
+                sighandlers[SIGILL](SIGILL);
+            ret = EXCEPTION_CONTINUE_EXECUTION;
+        }
+        break;
+    }
+    return ret;
+}
+
+void msvcrt_init_signals(void)
+{
+    SetConsoleCtrlHandler(msvcrt_console_handler, TRUE);
+    SetUnhandledExceptionFilter(msvcrt_exception_filter);
+}
+
+void msvcrt_free_signals(void)
+{
+    SetConsoleCtrlHandler(msvcrt_console_handler, FALSE);
+    SetUnhandledExceptionFilter(NULL);
+}
+
 /*********************************************************************
  *		signal (MSVCRT.@)
+ * MS signal handling is described here:
+ * http://msdn.microsoft.com/library/en-us/vclib/html/_CRT_signal.asp
+ * Some signals may never be generated except through an explicit call to
+ * raise.
  */
-void* MSVCRT_signal(int sig, MSVCRT_sig_handler_func func)
+__sighandler_t MSVCRT_signal(int sig, __sighandler_t func)
 {
-  FIXME("(%d %p):stub\n", sig, func);
-  return (void*)-1;
+    __sighandler_t ret = SIG_ERR;
+
+    TRACE("(%d, %p)\n", sig, func);
+
+    if (func == SIG_ERR) return SIG_ERR;
+
+    switch (sig)
+    {
+    /* Cases handled internally.  Note SIGTERM is never generated by Windows,
+     * so we effectively mask it.
+     */
+    case SIGABRT:
+    case SIGFPE:
+    case SIGILL:
+    case SIGSEGV:
+    case SIGINT:
+    case SIGTERM:
+        ret = sighandlers[sig];
+        sighandlers[sig] = func;
+        break;
+    default:
+        ret = SIG_ERR;
+    }
+    return ret;
 }
diff --git a/dlls/msvcrt/main.c b/dlls/msvcrt/main.c
index 4297bb8..b8660bb 100644
--- a/dlls/msvcrt/main.c
+++ b/dlls/msvcrt/main.c
@@ -51,6 +51,7 @@
     msvcrt_init_io();
     msvcrt_init_console();
     msvcrt_init_args();
+    msvcrt_init_signals();
     MSVCRT_setlocale(0, "C");
     TRACE("finished process init\n");
     break;
@@ -61,6 +62,7 @@
     msvcrt_free_io();
     msvcrt_free_console();
     msvcrt_free_args();
+    msvcrt_free_signals();
     if (!msvcrt_free_tls())
       return FALSE;
     TRACE("finished process free\n");
diff --git a/dlls/msvcrt/msvcrt.h b/dlls/msvcrt/msvcrt.h
index b6d4637..03f553d 100644
--- a/dlls/msvcrt/msvcrt.h
+++ b/dlls/msvcrt/msvcrt.h
@@ -125,6 +125,8 @@
 extern void msvcrt_free_console(void);
 extern void msvcrt_init_args(void);
 extern void msvcrt_free_args(void);
+extern void msvcrt_init_signals(void);
+extern void msvcrt_free_signals(void);
 
 extern unsigned msvcrt_create_io_inherit_block(STARTUPINFOA*);
 
diff --git a/include/Makefile.in b/include/Makefile.in
index 47b9582..a46acd6 100644
--- a/include/Makefile.in
+++ b/include/Makefile.in
@@ -291,6 +291,7 @@
 	msvcrt/search.h \
 	msvcrt/setjmp.h \
 	msvcrt/share.h \
+	msvcrt/signal.h \
 	msvcrt/stddef.h \
 	msvcrt/stdio.h \
 	msvcrt/stdlib.h \
diff --git a/include/msvcrt/float.h b/include/msvcrt/float.h
index 0fa9322..3122093 100644
--- a/include/msvcrt/float.h
+++ b/include/msvcrt/float.h
@@ -114,6 +114,19 @@
 #define _FPCLASS_PN   0x0100  /* Positive Normal */
 #define _FPCLASS_PINF 0x0200  /* Positive Infinity */
 
+/* floating point error signals */
+#define _FPE_INVALID            0x81
+#define _FPE_DENORMAL           0x82
+#define _FPE_ZERODIVIDE         0x83
+#define _FPE_OVERFLOW           0x84
+#define _FPE_UNDERFLOW          0x85
+#define _FPE_INEXACT            0x86
+#define _FPE_UNEMULATED         0x87
+#define _FPE_SQRTNEG            0x88
+#define _FPE_STACKOVERFLOW      0x8a
+#define _FPE_STACKUNDERFLOW     0x8b
+#define _FPE_EXPLICITGEN        0x8c
+
 double _copysign (double, double);
 double _chgsign (double);
 double _scalb(double, long);
diff --git a/include/msvcrt/signal.h b/include/msvcrt/signal.h
new file mode 100644
index 0000000..38a3e58
--- /dev/null
+++ b/include/msvcrt/signal.h
@@ -0,0 +1,45 @@
+/*
+ * Signal definitions
+ *
+ * Copyright 2005 Juan Lang
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef _WINE_SIGNAL_H
+#define _WINE_SIGNAL_H
+#ifndef __WINE_USE_MSVCRT
+#define __WINE_USE_MSVCRT
+#endif
+
+#define SIGINT   2
+#define SIGILL   4
+#define SIGFPE   8
+#define SIGSEGV  11
+#define SIGTERM  15
+#define SIGBREAK 21
+#define SIGABRT  22
+
+#define NSIG     (SIGABRT + 1)
+
+typedef void (*__sighandler_t)(int);
+
+#define SIG_DFL ((__sighandler_t)0)
+#define SIG_IGN ((__sighandler_t)1)
+#define SIG_ERR ((__sighandler_t)-1)
+
+__sighandler_t signal(int sig, __sighandler_t func);
+int raise(int sig);
+
+#endif /* _WINE_SIGNAL_H */